32位客户端和64位服务器之间的免注册COM互操作

时间:2020-07-02 22:51:53

标签: c# com interop 32bit-64bit com-interop

我需要在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>

0 个答案:

没有答案
相关问题