我有一个32位和64位版本的DLL。 我的.NET WinFormconfiguration为“任何CPU”,我的老板不会让我们有不同的操作系统版本单独安装。 所以我想知道:如果我在安装中包装这两个DLL,那么有没有办法让WinForm确定它的64位/ 32位并加载正确的DLL。
我发现这篇文章确定版本。 但我不知道如何注入适当的方式来定义我想使用的方法的DLLImport属性。 有任何想法吗?
你可以导入他们两个,并决定通过.NET调用哪一个呢?
例如:
[DllImport("32bit.dll", CharSet = CharSet.Unicode, EntryPoint="CallMe")] public static extern int CallMe32 (IntPtr hWnd, String text, String caption, uint type); [DllImport("64bit.dll", CharSet = CharSet.Unicode, EntryPoint="CallMe")] public static extern int CallMe64 (IntPtr hWnd, String text, String caption, uint type);
您可以利用SetDllDirectory API函数,它会改变非托管程序集的搜索路径。 将32位DLL存储在应用程序安装目录(x64子目录中的64位DLL)的x86子目录中。
在进行任何P / Invoke之前,在应用程序启动时运行此代码:
using System.IO; using System.Reflection; using System.Runtime.InteropServices; ... public static void SetUnmanagedDllDirectory() { string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); path = Path.Combine(path, IntPtr.Size == 8 ? "x64 " : "x86"); if (!SetDllDirectory(path)) throw new System.ComponentModel.Win32Exception(); } [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool SetDllDirectory(string path);
您应该制作两个不同的私有extern
方法,并且创建一个内部方法来检查IntPtr.Size
并调用正确的版本。
我的解决方案是创建一个抽象类,加载和封装我的32位DLL的具体版本,以及加载和封装64位DLL的单独的实现。 基类中的单个工厂方法可用于基于IntPtr.Size
实例化适当的实现。
这种方法的好处在于,其余代码与平台完全隔离 – 它只是使用基类工厂方法构造一个对象,并使用它。 在所讨论的DLL中以统一的方式调用多个方法也很容易,所有的“本地”代码都可以很容易地被推送到一个私有的实现中。
…或者你可以使用Marshal.GetDelegateForFunctionPointer()
来做动态P / Invoke 。
…或在CLR尝试为您加载之前使用完全限定的路径调用LoadLibrary()
。