使用Environment.Is64BitProcess从c#应用程序动态调用32位或64位DLL

时间:2012-05-25 16:18:31

标签: c# .net-4.0

我正在开发一个用C#编写的.NET 4.0项目(通过Visual Studio 2010)。有一个第三方工具需要使用C / C ++ DLL,并且在C#中有32位应用程序和64位应用程序的示例。

问题是32位演示静态链接到32位DLL,64位演示静态链接到64位DLL。作为.NET应用程序,它可以在客户端PC上作为32位或64位进程运行。

.NET 4.0框架提供了Environment.Is64BitProcess属性,如果应用程序作为64位进程运行,则返回true。

我想要做的是在检查Is64BitProcess属性后动态加载正确的DLL。但是,当我研究动态加载库时,我总是想出以下内容:

[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);

看起来这些方法专门针对32位操作系统。是否有64位等价物?

只要根据Is64BitProcess检查调用适当的方法,是否会导致静态链接32位和64位库的问题?

public class key32
{
    [DllImport("KEYDLL32.DLL", CharSet = CharSet.Auto)]
    private static extern uint KFUNC(int arg1, int arg2, int arg3, int arg4);

    public static bool IsValid()
    {
       ... calls KFUNC() ...
    }
}

public class key64
{
    [DllImport("KEYDLL64.DLL", CharSet = CharSet.Auto)]
    private static extern uint KFUNC(int arg1, int arg2, int arg3, int arg4);

    public static bool IsValid()
    {
       ... calls KFUNC() ...
    }
}

...

if (Environment.Is64BitProcess)
{
    Key64.IsValid();
}
else
{
    Key32.IsValid();
}

谢谢!

4 个答案:

答案 0 :(得分:4)

有很多方法可以做到这一点:

  • 这是一个部署问题,只需获取安装程序复制的正确DLL,给它们命名相同

  • 很少有程序实际上需要64位代码提供的大量地址空间。只需将平台目标设置为x86

  • 即可
  • 使用[DllImport]属性的EntryPoint字段。将其设置为" KFUNC"。并给方法不同的名称。现在,您可以根据IntPtr.Size

  • 的值调用其中一个

演示最后的解决方案:

[DllImport("KEYDLL32.DLL", EntryPoint = "KFUNC")]
private static extern uint KFUNC32(int arg1, int arg2, int arg3, int arg4);

[DllImport("KEYDLL64.DLL", EntryPoint = "KFUNC")]
private static extern uint KFUNC64(int arg1, int arg2, int arg3, int arg4);

...

if (IntPtr.Size == 8) KFUNC64(1, 2, 3, 4);
else                  KFUNC32(1, 2, 3, 4);

答案 1 :(得分:1)

具有讽刺意味的是,在64位系统上,kernel32.dll(驻留在%windir%\System32\中)是64位版本,%windir%\SysWOW64\版本是32位系统。非常不幸的命名在这里...

无论如何,您可以做的是使用我链接的路径将两个版本绑定到两个不同的变量名称(例如LoadLibrary system32 LoadLibrary32版本的版本和syswow64。然后在32位系统上,您可以使用LoadLibrary,如果您检测到64位系统,LoadLibrary将是64位版本,而LoadLibrary32将是32位版本

我怀疑这会对你有所帮助,因为我认为你不能动态地绑定到不匹配的位数(要使这个 这个词!)动态库...会帮助你的第二个例子我想,你实际上在哪里得到两个不同的库,每个案例一个。

答案 2 :(得分:0)

我不会考虑更低级别的互操作,而是考虑使用更多.Net路由 - 使用类似插件的程序集来处理它。

  • 创建2个程序集,链接到x86和x64版本的DLL(并为正确的平台编译)。
  • 使此程序集公开实现相同接口的类(或使它们相同的其他方法)。确保其余的代码可以使用其中一个库,可能需要使用基本类型/接口进行第三次组装。
  • 在运行时加载手动需要的程序集。确保它不会出现在搜索路径中,以避免错误地自动加载。

请注意,您的第二种方法(基于位数的选择方法)应该可以正常工作。我仍然会在具有相同接口的类中包装对每个DLL的所有访问,并确保只能在运行时实例化一个正确的DLL。

答案 3 :(得分:0)

将dll保存在两个不同的目录中并动态调用它们。

Libs64 \ ABC.dll
Libs32 \ ABC.dll