如何启动 AnyCPU 编译的 COM 服务器

How to start a AnyCPU compiled COM Server

我使用 Microsoft 的 COM 服务器示例: Out-of-process C# COM server (CSExeCOMServer)

一个简单的控制台 COM 客户端应该只启动服务器并使用它的方法、属性和事件。

    static void Main(string[] args)
    {            
        Type type = Type.GetTypeFromCLSID(new Guid(SimpleObject.ClassId));

        if (type == null)
        {
            throw new Exception("ClientObject component is not registered");
        }

        ISimpleObject comObject = (ISimpleObject)Activator.CreateInstance(type);

        string what = comObject.HelloWorld();

        float fvalue = (float) 2.22;
        comObject.FloatProperty = fvalue;
        fvalue = (float)3.33;
        fvalue = comObject.FloatProperty;
    }

这实际上直接起作用。由于其配置的平台目标 x86,服务器以 32 位出现。但是我有一个 64 位 OS,现在我想在 64 位中得到它 运行。 注册在服务器的 post 构建事件中完成。所以我更改了注册(使用 Framework64 regasm.exe)以便服务器也将以 64 位注册。然后我将平台目标更改为 AnyCPU。 如果我现在启动客户端,它会挂在行

    ISimpleObject comObject = (ISimpleObject)Activator.CreateInstance(type);

但我可以在任务管理器中看到服务器已在 64 位中正常启动。大约 1 分钟后,我得到以下异常:

Retrieving the COM class factory for component with CLSID {DB9935C1-19C5-4ED2-ADD2-9A57E19F53A3} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at ConsoleClient.Program.Main(String[] args) in C:\Source\User\MaLe\Tests\CSExeCOMServer\C#\ConsoleClient\Program.cs:line 17 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

如果我手动启动服务器 exe 并再次尝试通过 COM 连接到它,我可以在任务管理器中看到客户端启动了第二个服务器,而不是连接到第一个服务器。这个确实是 64 位的,但是发生了异常,在关闭客户端后,第二个服务器也关闭了。 如果我在带有 Prefere 32 位标志的 AnyCPU 中强制服务器为 32 位,一切正常,但在 32 位中。如果我将平台目标设置为 x64,那么在 64 位中也一切正常。因此,如果它以 64 位启动,则它仅在 AnyCPU 配置中不起作用。

有人知道我做错了什么吗? 即使是 64 位,我真的需要一个 COM-Server 在 AnyCPU 配置中 运行。我实际上不想有单独的 32 位和 64 位 exe。顺便说一句,当我测试它时,它也有效。

感谢您的帮助。

Does anyone have an idea what I do wrong? I really need a COM-Server to run in AnyCPU configuration even with 64bit. I actually do not want to have seperate 32bit and 64bit exe's.

COM 需要为 32 位和 64 位以及两个不同的 out-of-process COM 服务器单独注册 COM;因此您需要 32 位 COM exe 和 64 位 exe。你不能两者兼得。

这样的例子随处可见:

  • bit-specific 版本的 shell 扩展 Windows Explorer。例如乌龟SVN; TortoiseGit。 Windows Explorer 运行ning on 64-bit Windows 只接受 64 位扩展;类似地,运行ning 在 32 位 Windows

  • 分开 32 位和 64 位版本的 Microsoft Office(COM/Ole 已经有一段时间了)COM add-ins

可能 能够绕开说想要一个 32 位客户端连接到 64 位服务器的唯一方法是,如果您添加适当的 DCOM 注册和 运行 你的服务器在另一个盒子上(运行ning Windows 64 位),你的客户端通过网络连接到它。不过,这可能不是特别有用。