使用 Environment.Is64BitProcess 从 c# 应用程序动态调用 32 位或 64 位 DLL
本文关键字:位或 DLL 调用 动态 Is64BitProcess Environment 应用程序 使用 | 更新日期: 2023-09-27 18:35:31
我正在为.NET 4.0(通过Visual Studio 2010)编写一个用C#编写的项目。有一个第三方工具需要使用 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 位代码提供的大量地址空间。 只需将平台目标设置为 x86 即可
-
使用 [DllImport] 属性的入口点字段。 将其设置为"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'
版本是 32 位系统。这里发生了极其不幸的命名...
无论如何,您可以做的是使用我链接它们的路径绑定到两个版本,到两个不同的变量名称(例如,system32
版本为 LoadLibrary
,syswow64
版本为 LoadLibrary32
)。然后在 32 位系统上,您可以只使用 LoadLibrary
,如果您检测到 64 位系统,LoadLibrary
将是 64 位版本,而LoadLibrary32
将是 32 位版本。
但是,我质疑这会对您有所帮助,因为我认为您无法动态绑定到不匹配的位(将使其成为这个词!我想会对你的第二个例子有所帮助,你实际上得到了两个不同的库,每种情况一个。
与其做这么低级别的互操作,我会考虑采用更多的 .Net 路由 - 使用类似插件的程序集来处理它。
- 创建 2 个链接到 DLL 的 x86 和 x64 版本的程序集(并针对正确的平台进行编译)。
- 创建此程序集以公开实现相同接口的类(或使它们相同的其他方法)。确保其余代码可以使用任一库,可能需要具有基类型/接口的第三个程序集。
- 在运行时手动加载所需的程序集。确保它没有碰巧在搜索路径中,以避免错误地自动加载一个。
请注意,第二种方法(基于位数选择方法)应该可以正常工作。我仍然会将对每个 DLL 的所有访问包装在具有相同接口的类中,并确保在运行时只能实例化正确的一个。
将 dll 保存在两个不同的目录中并动态调用它们。
Libs64''ABC
.dllLibs32''ABC