我有一个dll,它有32位和64位两种版本。我的.NET WinForm配置为“任何CPU”,我的老板不会让我们针对不同的操作系统版本进行单独安装。所以我想知道:如果我在安装时打包了两个dll,那么是否有办法让WinForm确定其64位/ 32位并加载正确的dll。基于64bit或32bit操作系统导入外部dll
我发现this article用于确定版本。但我不知道如何注入适当的 方式来定义我希望使用的方法的DLLImport属性。有任何想法吗?
我有一个dll,它有32位和64位两种版本。我的.NET WinForm配置为“任何CPU”,我的老板不会让我们针对不同的操作系统版本进行单独安装。所以我想知道:如果我在安装时打包了两个dll,那么是否有办法让WinForm确定其64位/ 32位并加载正确的dll。基于64bit或32bit操作系统导入外部dll
我发现this article用于确定版本。但我不知道如何注入适当的 方式来定义我希望使用的方法的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);
你应该把两种不同的私有extern
方法,并作出检查IntPtr.Size
并调用正确版本的内部方法。
我的解决方案是创建一个抽象类,具有加载和封装我的32位DLL的具体版本,以及加载和封装64位DLL的单独实现。基类中的单个工厂方法可用于基于IntPtr.Size
实例化适当的实现。
这种方法的好处在于,其余代码与平台完全隔离 - 它只是使用基类工厂方法构造对象,并使用它。在所讨论的DLL中以统一的方式调用多个方法也很容易,并且所有的“本地”代码都可以轻松地推送到私有实现中。
您可以利用SetDllDirectory API函数,它会改变非托管程序集的搜索路径。将您的32位DLL存储在应用程序安装目录的x86子目录中,即64位子目录中的64位DLL。
运行这段代码在应用程序启动你之前任何的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);
这是一个很酷的解决方案。 – Kieron 2010-04-07 16:43:20
...或者你可以使用Marshal.GetDelegateForFunctionPointer()
做dynamic P/Invoke。
...或致电LoadLibrary()
with a fully qualified path CLR尝试为您加载它之前。
这实际上是我的“去”解决方案,如果我找不到一个更干净的方法来做到这一点。 – 2010-04-07 15:56:51