[英]Dynamically calling 32-bit or 64-bit DLL from c# application using Environment.Is64BitProcess
I am working on a project written in C# for .NET 4.0 (via Visual Studio 2010). 我正在开发一个用C#编写的.NET 4.0项目(通过Visual Studio 2010)。 There is a 3rd party tool that requires the use of a C/C++ DLL and there are examples for 32-bit applications and 64-bit applications in C#. 有一个第三方工具需要使用C / C ++ DLL,并且在C#中有32位应用程序和64位应用程序的示例。
The problem is that the 32-bit demo statically links to the 32-bit DLL and the 64-bit demo statically links to the 64-bit DLL. 问题是32位演示静态链接到32位DLL,64位演示静态链接到64位DLL。 Being a .NET application it could run as either a 32-bit or 64-bit process on the client PCs. 作为.NET应用程序,它可以在客户端PC上作为32位或64位进程运行。
The .NET 4.0 framework provides the Environment.Is64BitProcess property that returns true if the application is running as a 64-bit process. .NET 4.0框架提供了Environment.Is64BitProcess属性,如果应用程序作为64位进程运行,则返回true。
What I would like to do is to dynamically load the correct DLL after checking the Is64BitProcess property. 我想要做的是在检查Is64BitProcess属性后动态加载正确的DLL。 However, when I research dynamically loading libraries I always come up with the following: 但是,当我研究动态加载库时,我总是想出以下内容:
[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);
It would appear that these methods are specifically for the 32-bit operating system. 看起来这些方法专门用于32位操作系统。 Are there 64-bit equivalents? 有64位等价物吗?
Would it cause problems to statically link both the 32-bit and 64-bit libraries as long as the appropriate methods are called based on the Is64BitProcess check? 只要根据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();
}
Thank you!! 谢谢!!
Lots of ways to do this: 有很多方法可以做到这一点:
this is a deployment problem, just get the right DLL copied by the installer, give them the same name 这是一个部署问题,只需获取安装程序复制的正确DLL,为它们指定相同的名称
very few programs actually need the massive address space provided by 64-bit code. 很少有程序实际上需要64位代码提供的大量地址空间。 Just set the Platform target to x86 只需将Platform目标设置为x86即可
use the EntryPoint field of the [DllImport] attribute. 使用[DllImport]属性的EntryPoint字段。 Set it to "KFUNC". 将其设置为“KFUNC”。 And give the methods different names. 并给方法不同的名称。 Now you can call one or the other, based on the value of IntPtr.Size 现在,您可以根据IntPtr.Size的值调用其中一个
Demonstrating the last solution: 演示最后的解决方案:
[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);
Ironically, on a 64-bit system, kernel32.dll
(residing in %windir%\\System32\\
) is the 64-bit version, and the %windir%\\SysWOW64\\
version is the 32-bit system. 具有讽刺意味的是,在64位系统上, kernel32.dll
(驻留在%windir%\\System32\\
)是64位版本, %windir%\\SysWOW64\\
version是32位系统。 Extremely unfortunate naming going on here... 非常不幸的命名在这里......
Anyway, what you can do is bind to both versions, using the paths as I linked them, to two different variable names (say, LoadLibrary
for the system32
version and LoadLibrary32
for the syswow64
version). 不管怎么说,你能做的就是绑定到两个版本,使用的路径,我联系他们,两个不同的变量名称(比如, LoadLibrary
的system32
版本和LoadLibrary32
为syswow64
版本)。 Then on a 32 bit system you can just use LoadLibrary
, and if you detect a 64 bit system, LoadLibrary
will be the 64-bit version, while LoadLibrary32
will be the 32-bit version. 然后在32位系统上,您可以使用LoadLibrary
,如果您检测到64位系统, LoadLibrary
将是64位版本,而LoadLibrary32
将是32位版本。
I question however that this will help you any since I don't think you can dynamically bind to mismatching bitness (gonna make this the word!) dynamic libraries... Would help your second example I guess, where you actually do get two different libraries, one for each case. 但我怀疑,这将有助于你任何,因为我不认为你可以动态绑定到不匹配位数(要补偿的话!)动态库......将有助于你的第二个例子我想,在这里你其实得到两个不同图书馆,每个案例一个。
Instead of doing so low level interop I would consider going more .Net route - use plugin-like assemblies to deal with it. 我不会考虑这样的低级别互操作,而是考虑使用更多.Net路由 - 使用类似插件的程序集来处理它。
Note that your second approach (picking methods based on bitness) should work fine. 请注意,您的第二种方法(基于位数的选择方法)应该可以正常工作。 I would still wrap all access to each DLL in classes with same interfaces and make sure that only correct one can be instantiated at run time. 我仍然会在具有相同接口的类中包装对每个DLL的所有访问,并确保只能在运行时实例化一个正确的DLL。
Keeping the dlls in two different directories and call them dynamically. 将dll保存在两个不同的目录中并动态调用它们。
Libs64\\ABC.dll Libs64 \\ ABC.dll
Libs32\\ABC.dll Libs32 \\ ABC.dll
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.