2

我将 Microsoft 示例用于 COM-Server: 进程外 C# COM 服务器 (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 位操作系统,现在我想让它在 64 位上运行。注册在服务器的构建后事件中完成。所以我更改了注册(使用Framework64 regasm.exe),以便服务器也将以64位注册。然后我将平台目标更改为 AnyCPU。如果我现在启动客户端,它会挂在行中

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

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

由于以下错误,检索具有 CLSID {DB9935C1-19C5-4ED2-ADD2-9A57E19F53A3} 的组件的 COM 类工厂失败:80080005 服务器执行失败(来自 HRESULT 的异常:0x80080005 (CO_E_SERVER_EXEC_FAILURE))。

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

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

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

感谢您的帮助。

4

1 回答 1

1

有谁知道我做错了什么?我真的需要一个 COM-Server 才能在 AnyCPU 配置中运行,即使是 64 位。我实际上不想拥有单独的 32 位和 64 位 exe。

COM 需要对 32 位和 64 位以及两个不同的进程外 COM 服务器进行单独的 COM 注册;因此,您需要 32 位 COM exe 和 64 位 exe。你不能两者兼得。

你会在任何地方看到这样的例子:

  • Windows Explorer 的特定位版本的 shell 扩展。例如TortoiseSVN;龟甲。在 64 位 Windows 上运行的 Windows Explorer 仅接受 64 位扩展;同样适用于在 32 位 Windows 上运行

  • 独立的 32 位和 64 位版本的Microsoft Office(COM/Ole 已经有一段时间了),对于 COM 加载项具有相同的位数

如果您希望 32 位客户端连接到 64 位服务器,那么您可能能够绕过的唯一方法是,如果您添加适当的 DCOM 注册并在您的客户端连接的另一个盒子(运行 Windows 64 位)上运行您的服务器通过网络发送给它。不过,这可能不是特别有用。

于 2017-02-03T15:16:13.320 回答