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

4
我正在处理一个使用C#编写的.NET 4.0项目(通过Visual Studio 2010)。有一个第三方工具需要使用C/C++ DLL,并且有32位应用程序和64位应用程序在C#中的示例。
问题是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个回答

5
有很多种方法可以解决这个问题:
  • 这是一个“部署”问题,只需通过安装程序复制正确的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

讽刺的是,在64位系统上,kernel32.dll(位于%windir%\System32\)是64位版本,而%windir%\SysWOW64\版本是32位系统。 这里发生了非常不幸的命名...

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

然而,我怀疑这不会帮助您,因为我认为您不能动态绑定到不匹配位数(要成为单词!)的动态库...会帮助您的第二个示例,其中您实际上获得两个不同的库,每种情况下都有一个。


0

不要使用低级别的Interop,我建议您考虑更多的.NET路线-使用类似插件的程序集来处理它。

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

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


0

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

Libs64\ABC.dll
Libs32\ABC.dll


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