简体   繁体   English

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

[英]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). 不管怎么说,你能做的就是绑定到两个版本,使用的路径,我联系他们,两个不同的变量名称(比如, LoadLibrarysystem32版本和LoadLibrary32syswow64版本)。 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路由 - 使用类似插件的程序集来处理它。

  • create 2 assemblies that link to x86 and x64 versions of the DLL (and compiled for correct platform). 创建2个程序集,链接到DLL的x86和x64版本(并编译为正确的平台)。
  • Make this assemblies to expose class(es) implementing the same interface (or some other way of making them the same). 使这个程序集公开实现相同接口的类(或使它们相同的其他方法)。 Make sure the rest of you code can use either of the libraries, may need third assembly with base types/interfaces. 确保你们其余的代码可以使用任何一个库,可能需要第三个程序集与基本类型/接口。
  • At run time load the assembly that you need manually. 在运行时加载手动需要的程序集。 Make sure that it does not happen to be in search path to avoid loading one automatically by mistake. 确保它不会出现在搜索路径中,以避免错误地自动加载。

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.

相关问题 从64位c#WinForms应用程序调用第三方32位dll时的事件处理 - Event handling at calling a third party 32-bit dll from a 64-bit c# WinForms application 调用 64 位 C/C++ DLL 的 C# 应用程序崩溃,但 32 位版本运行 - C# app calling 64-bit C/C++ DLL crashes, but 32-bit version runs 使用32位应用程序中的64位库 - Use 64-bit library from 32-bit application C#:根据平台访问32位/ 64位DLL - C#: Access 32-bit/64-bit DLL depending on platform 从 32 位 Windows 服务使用 64 位进程外 COM DLL - Using 64-bit out of process COM DLL from 32-bit Windows Serivce 将在64位系统上构建的C#中的应用程序与在32位系统上运行的应用程序匹配 - Matching application in C# that built on 64-bit system to running on 32-bit system 我可以在32位系统上运行在64位系统上开发的C#应用​​程序吗? - Can I run a C# application developed on a 64-bit system on a 32-bit system? C# 32 位和 64 位应用程序的单一部署项目 - C# Single Deployment project for 32-bit and 64-bit application 在 64 位机器上以 32 位方式运行 C# 应用程序 - Running a C# application as 32-bit on a 64-bit machine 当完整路径解析为64位目录时,无法从32位C#应用程序启动快捷方式(lnk)文件 - Unable to launch shortcut (lnk) files from 32-bit C# application when the full path resolves to a 64-bit directory
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM