2010-04-07 71 views
8

我有一个dll,它有32位和64位两种版本。我的.NET WinForm配置为“任何CPU”,我的老板不会让我们针对不同的操作系统版本进行单独安装。所以我想知道:如果我在安装时打包了两个dll,那么是否有办法让WinForm确定其64位/ 32位并加载正确的dll。基于64bit或32bit操作系统导入外部dll

我发现this article用于确定版本。但我不知道如何注入适当的 方式来定义我希望使用的方法的DLLImport属性。有任何想法吗?

回答

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

这实际上是我的“去”解决方案,如果我找不到一个更干净的方法来做到这一点。 – 2010-04-07 15:56:51

3

你应该把两种不同的私有extern方法,并作出检查IntPtr.Size并调用正确版本的内部方法。

3

我的解决方案是创建一个抽象类,具有加载和封装我的32位DLL的具体版本,以及加载和封装64位DLL的单独实现。基类中的单个工厂方法可用于基于IntPtr.Size实例化适当的实现。

这种方法的好处在于,其余代码与平台完全隔离 - 它只是使用基类工厂方法构造对象,并使用它。在所讨论的DLL中以统一的方式调用多个方法也很容易,并且所有的“本地”代码都可以轻松地推送到私有实现中。

14

您可以利用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); 
+0

这是一个很酷的解决方案。 – Kieron 2010-04-07 16:43:20