基于64位或32位操作系统导入外部dll

9
我有一个dll,分别提供32位和64位版本。我的.NET WinForm配置为“任意CPU”,而我的老板不允许我们针对不同的操作系统版本进行单独的安装。所以我想知道:如果我在安装中打包了这两个dll,那么是否有一种方法可以让WinForm确定它是64位/32位并加载正确的dll。
我找到了这篇文章来确定版本。但我不确定如何注入适当的方式来定义我希望使用的方法的DLLImport属性。有什么建议吗?
5个回答

15

你可以利用SetDllDirectory API函数来改变未托管程序集的搜索路径。将你的32位DLL文件存储在应用程序安装目录下的x86子目录中,将64位DLL文件存储在x64子目录中。

在进行任何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);

6

您能够导入它们并通过.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);

1
这实际上是我的“备选方案”,如果我找不到更简洁的方法来解决它。 - Mike_G

3
你应该创建两个不同的私有extern方法,并创建一个内部方法来检查IntPtr.Size并调用正确的版本。

3
我的解决方案是创建一个抽象类,其中包含一个具体版本,它加载和包装我的32位DLL,以及一个单独的实现,它加载和包装64位DLL。在基类中使用一个工厂方法来实例化适当的实现,基于 IntPtr.Size
这种方法的好处是,你的其余代码完全与平台隔离 - 它只是使用您的基类工厂方法构造对象,并与之一起工作。还可以非常容易地以统一的方式调用所涉及的DLL中的多个方法,并且所有 "本机" 代码都可以轻松地推入私有实现中。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接