使用Environment.Is64BitProcess从c#应用程序动态调用32位或64位DLL
我正在开发一个用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(); }
谢谢!!
有很多方法可以做到这一点:
-
这是一个部署问题,只需获取安装程序复制的正确DLL,为它们指定相同的名称
-
很少有程序实际上需要64位代码提供的大量地址空间。 只需将Platform目标设置为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);
具有讽刺意味的是,在64位系统上, kernel32.dll
(驻留在%windir%\System32\
)是64位版本, %windir%\SysWOW64\
version是32位系统。 非常不幸的命名在这里……
无论如何,你可以做的是使用我链接它们的路径将两个版本绑定到两个不同的变量名称(例如, system32
版本的LoadLibrary32
和syswow64
版本的LoadLibrary32
)。 然后在32位系统上,您可以使用LoadLibrary
,如果您检测到64位系统, LoadLibrary
将是64位版本,而LoadLibrary32
将是32位版本。
我怀疑这会对你有所帮助,因为我认为你不能动态地绑定到不匹配的位数(这会成为这个词!)动态库…会帮助你的第二个例子我想,你实际上会得到两个不同的图书馆,每个案例一个。
我不会考虑使用更低级别的互操作,而是考虑使用更多.Net路由 – 使用类似插件的程序集来处理它。
- 创建2个程序集,链接到x86和x64版本的DLL(并编译为正确的平台)。
- 使这个程序集公开实现相同接口的类(或使它们相同的其他方式)。 确保你们其余的代码可以使用任何一个库,可能需要第三个程序集与基本类型/接口。
- 在运行时加载手动需要的程序集。 确保它不会出现在搜索路径中,以避免错误地自动加载。
请注意,您的第二种方法(基于位数的选择方法)应该可以正常工作。 我仍然会在具有相同接口的类中包装对每个DLL的所有访问,并确保只能在运行时实例化一个正确的DLL。
将dll保存在两个不同的目录中并动态调用它们。
Libs64 \ ABC.dll
Libs32 \ ABC.dll