如何从C#中的特定路径读取DLL

时间:2016-11-25 14:26:16

标签: c# .net dll

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

但我明白了:

  

AccessViolation exeption:尝试读取或写入受保护的   记忆。这通常表明其他内存已损坏。

我不能只使用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;
        }
    }
}

我正在使用load函数从任何路径获取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);
    }

}

1 个答案:

答案 0 :(得分:5)

[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&gt;添加现有项目&gt;选择DLL。在Solution Explorer窗口中选择添加的文件。在“属性”窗口中,将“复制到输出目录”设置更改为“#34;复制如果更新&#34;”。重建您的项目并注意您现在可以在项目的bin \ Debug目录中获取DLL。现在[DllImport]将起作用。

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

非常草率,它对产品的质量提出了很大的问号。他们似乎根本不解决的其他问题是如何确保自己的代码安全。使用加密狗时非常重要。请注意,任何人都可以对您的身份验证代码进行反向工程。更糟糕的是,要反编译您的程序并删除身份验证检查。你需要使用混淆器。