【问题标题】:How to read dll from specific path in C#如何从 C# 中的特定路径读取 dll
【发布时间】:2016-11-25 14:26:16
【问题描述】:

我需要将 SglW32.dll 导入我的解决方案。

但我明白了:

AccessViolation 异常:试图读或写保护 记忆。这通常表明其他内存已损坏。

我不能只使用 DllImport。在这种情况下找不到 dll。

这是一个完整的例子。

using System;
using System.Runtime.InteropServices;
namespace TestDllimport
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new MyClass();
            var result = a.getValue();
        }
    }
    class FunctionLoader
    {
        [DllImport("Kernel32.dll")]
        private static extern IntPtr LoadLibrary(string path);

        [DllImport("Kernel32.dll")]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        public static Delegate LoadFunction<T>(string dllPath, string functionName)
        {
            var hModule = LoadLibrary(dllPath);
            var functionAddress = GetProcAddress(hModule, functionName);
            return Marshal.GetDelegateForFunctionPointer(functionAddress, typeof(T));
        }
    }

    public class MyClass
    {
        //Define your path to dll.
        //Get dll from: http://www.sg-lock.com/download/sglw32_v2_28.zip
        private const string DLL_Path = @"C:\Users\admin123\Desktop\MyDlls\SglW32.dll";

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate ulong SglAuthentA(IntPtr AuthentCode);
        static MyClass()
        {
            sglAuthentA = (SglAuthentA)FunctionLoader.LoadFunction<SglAuthentA>(DLL_Path, "SglAuthentA");
        }

        static private SglAuthentA sglAuthentA;

        unsafe public ulong getValue()
        {
            IntPtr d = new IntPtr(5);
            var a1 = sglAuthentA(d); // Exception IS HERE !!!!!
            return a1;
        }
    }
}

我正在使用加载函数从任何路径获取 dll。之后,我从所需的功能中创建委托。在我的例子中,函数是 SglAuthentA。 此解决方案适用于另一个 dll,但不适用于 SglW32.dll。

产品:http://www.sg-lock.com/us/

所需的 dll:http://www.sg-lock.com/download/sglw32_v2_28.zip

手册:http://www.sg-lock.com/download/SG-Lock_Manual_Eng.pdf

来源1:https://stackoverflow.com/a/8836228/2451446


编辑:感谢Hans Passant回答和ja72评论

的解决方案

See How to import dll

using System.Runtime.InteropServices;

namespace TestDllimport
{
    class Program
    {
        static void Main(string[] args)
        {
            var testA = DllImportClass.SglAuthentA(new uint[] { 5, 6, 7 }, new uint[] { 5, 6, 7 }, new uint[] { 5, 6, 7 });
            var testB = DllImportClass.SglAuthentB(new uint[] { 5, 6, 7 });
        }
    }

    static class DllImportClass
    {
        [DllImport("SglW32.dll")]
        public static extern uint SglAuthentA(uint[] AuthentCode0, uint[] AuthentCode1, uint[] AuthentCode2);

        [DllImport("SglW32.dll")]
        public static extern uint SglAuthentB(uint[] AuthentCode);
    }

}

【问题讨论】:

  • 为什么不使用[DllImport],就像对 Win32 API 函数所做的那样?只需确保将 DLL 分发在与 exe 相同的文件夹中(无论如何您都应该这样做)。桌面是放置 DLL 的错误位置,即使是用于开发
  • 由于某种原因找不到 dll。我不知道为什么。
  • 您在使用 Visual Studio 吗?你不能在你的项目中添加对 dll 的引用吗?右键单击项目“参考”文件夹并选择“添加参考”,然后使用浏览找到您的 .dll,选择它并单击确定。
  • 是的,我正在使用 Visual Studio。不,我不能添加对项目的引用。如果我感冒了就很容易了。
  • 请参阅this answer,了解如何始终让 DLL 具有编译器输出。

标签: c# .net dll


【解决方案1】:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate ulong SglAuthentA(IntPtr AuthentCode);

委托声明不正确,与 api 函数签名不匹配。 C 中的 ULONG 是 C# 中的 uint。 C 中的 ULONG* 不明确,可能是 ref uint,也可能是 uint[]。由于您应该传递一个 48 字节的身份验证代码,因此您知道它是一个数组。修复:

private delegate uint SglAuthentA(uint[] authentCode);

请务必通过正确的验证码。它不是 5,数组必须有 12 个元素。如果您没有,请致电制造商获取。


private const string DLL_Path = @"C:\Users\admin123\Desktop\MyDlls\SglW32.dll";

请注意,这不是无法使用 [DllImport] 的解决方法。硬编码路径是一个问题,文件不会出现在用户机器上的那个目录中。 DLL 本身没有任何阻止它加载的依赖项,遇到麻烦的唯一可能的原因是您忘记将 DLL 复制到正确的位置。只有一个这样的地方,与您的 EXE 相同的目录。

以正确的方式修复此问题,使用 Project > Add Existing Item > 选择 DLL。在解决方案资源管理器窗口中选择添加的文件。在“属性”窗口中,将“复制到输出目录”设置更改为“如果较新则复制”。重建您的项目并注意您现在将在项目的 bin\Debug 目录中获得 DLL。现在 [DllImport] 将起作用。


关于手册的注意事项,它列出了 Visual Basic 中的代码示例。这通常是您通常用作学习如何使用 api 的指南。然而,该代码不是 VB.NET 代码,它是 VB6 代码。在示例代码中看到Long 时,您应该使用uintint

非常马虎,给产品质量打了一个大大的问号。他们似乎根本没有解决的其他问题是如何确保您自己的代码安全。使用加密狗时非常重要。请注意,任何人对您的身份验证代码进行逆向工程都是非常微不足道的。更糟糕的是,反编译您的程序并删除身份验证检查。您需要使用混淆器。

【讨论】:

  • 感谢您的帮助。你的回答非常好。明天我才能奖励你,这是堆栈溢出的约束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多