如何在运行时延迟绑定32位/ 64位库

问题描述:

我遇到了一个与here(加载程序集及其依赖关系)所述类似但存在细微差别的问题。如何在运行时延迟绑定32位/ 64位库

我有一个用于3D渲染的C++ DLL,这是我们向客户销售的产品。对于.NET用户,我们将有一个CLR包装器。 C++ DLL可以构建在32位和64位版本中,但我认为这意味着我们需要有两个CLR包装器,因为CLR绑定到特定的DLL?

现在说我们的客户有一个可以是32位或64位的.NET应用程序,它是一个纯粹的.NET应用程序,它使CLR能够从一套程序集中解决问题。问题是应用程序代码在运行时如何在我们的32位和64位CLR/DLL组合之间动态选择?

甚至更​​具体地说,对于上述问题的建议答案也适用于此(即创建ResolveEvent处理程序)?

我终于有这个似乎工作的答案。

编译两个32 & 64位版本 - 两个管理的&非托管 - 到单独的文件夹。然后让.NET应用程序在运行时选择从哪个目录加载程序集。

使用ResolveEvent的问题在于,如果找不到组件,它只会被调用,所以很容易意外终止32位版本。相反,使用第二个AppDomain对象,我们可以将ApplicationBase属性更改为指向正确的文件夹。所以,你最终用类似的代码:

static void Main(String[] argv) 
    { 
    // Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit 
    // sub-directories. 

    AppDomainSetup objADS = new AppDomainSetup(); 

    System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath); 
    switch (System.IntPtr.Size) 
    { 
     case (4): assemblyDir += "\\win32\\"; 
      break; 
     case (8): assemblyDir += "\\x64\\"; 
      break; 
    } 

    objADS.ApplicationBase = assemblyDir; 

    // We set the PrivateBinPath to the application directory, so that we can still 
    // load the platform neutral assemblies from the app directory. 
    objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath); 

    AppDomain objAD = AppDomain.CreateDomain("", null, objADS); 
    if (argv.Length > 0) 
     objAD.ExecuteAssembly(argv[0]); 
    else 
     objAD.ExecuteAssembly("MyApplication.exe"); 

    AppDomain.Unload(objAD); 

    } 

你最终2个EXE文件 - 您的正常应用,并且选择哪些位加载第二切换应用程序。 注 - 我不能赞扬这个我自己的细节。我的一位同事怀疑我已经给了我最初的指示。如果当他注册到*时,我会给他分配答案

我以前遇到过类似的情况。我使用的工具包在64位环境中表现不佳,我无法找到动态强制程序集绑定为32位的方式。

可以强制你的程序集工作在32位模式下,但这需要修补CLR头文件(有一个工具可以在框架中完成),如果你的程序集是强命名的,锻炼。

恐怕您需要为32位和64位平台构建和发布两套二进制文件。

大约一年前我能够做到这一点,但我不再记得所有的细节。基本上,您可以使用IntPtr.Size来确定要加载哪个DLL,然后通过p/Invoke执行实际的LoadLibrary。在那个时候,你已经在内存中获得了模块,你应该能够从内部调用p/Invoke函数 - 不应该再次重新载入相同的模块名称。我认为,在我的应用程序中,我实际上已经将C++ DLL注册为COM服务器,然后通过生成的.NET包装来访问它的功能 - 所以我不知道我是否曾经测试过p /直接调用。