我需要在32位应用程序中使用64位dll。
首先,我创建了一个单独的64位可执行文件,并使用Microsoft RPC从32位应用程序中调用64位代码(本来,二进制文件是本机的,但这无关紧要,我们可以随时编写.NET包装器) 。一切正常,但是我真的不喜欢为了启动RPC服务器,连接到它,运行可执行文件(并监视它)而需要编写的所有样板代码。我知道,进程外COM通过为客户端隐式地将dll托管在 dllhost.exe 进程中,可以处理很多此类工作。
因此,我按照here的说明进行了操作:创建64位服务器,32位客户端,然后使用 regasm 注册服务器,更改几个注册表项,一切正常。但是我不能在客户端计算机上使用 regasm ,所以我尝试了MSDN article中所述的免注册COM。一切都无需注册即可运行,直到服务器和客户端都是32位。但是,当我将服务器重建为64位二进制文件时,会出现以下错误:
未处理的异常:System.IO.FileLoadException:检索COM 具有CLSID的组件的类工厂 由于以下原因,{D698BA94-AEFF-3D4F-9D11-BC6DE81D330B}失败 错误:80131047给定的程序集名称或代码库无效。 (来自HRESULT的异常:0x80131047)。
我能从这两种方法中获得最大的好处吗:拥有免注册的COM Interop,但是在64位和32位代码之间?
更新
添加了源代码。在这里,如果我从清单中删除processorArchitecture="amd64"
并将服务器构建为x86二进制文件,则一切正常。
客户代码
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
Type ComType = Type.GetTypeFromCLSID(new Guid("D698BA94-AEFF-3D4F-9D11-BC6DE81D330B"));
var ComObject = Activator.CreateInstance(ComType);
ComType.InvokeMember("TestMe", BindingFlags.InvokeMethod, null, ComObject, null);
if (Marshal.IsComObject(ComObject))
Marshal.ReleaseComObject(ComObject);
}
}
}
客户端应用清单
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="ConsoleApp5" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity
name="ClassLibrary1"
version="1.0.0.0"
processorArchitecture="amd64"
/>
</dependentAssembly>
</dependency>
</assembly>
服务器代码
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ClassLibrary1
{
[ComVisible(true)]
[Guid("D698BA94-AEFF-3D4F-9D11-BC6DE81D330B")]
public class ComServer
{
/// <summary>
/// Default constructor - necessary for using with COM
/// </summary>
public ComServer() { }
/// <summary>
/// Test method to be called by COM sonsumer
/// </summary>
public void TestMe()
{
MessageBox.Show("Hello from the 64-bit world!");
}
}
}
服务器应用清单
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="ClassLibrary1" processorArchitecture="amd64"/>
<file name="ClassLibrary.dll"/>
<clrClass
clsid="{D698BA94-AEFF-3D4F-9D11-BC6DE81D330B}"
progid="ClassLibrary1.ComServer"
threadingModel="Both"
name="ClassLibrary1.ComServer"
runtimeVersion="v4.0.30319">
</clrClass>
</assembly>