【问题标题】:System.InvalidCastException trying to build a COM client and a COM server in C#System.InvalidCastException 试图在 C# 中构建 COM 客户端和 COM 服务器
【发布时间】:2014-04-02 14:38:46
【问题描述】:

我正在尝试构建一个 COM 客户端,它必须在 C# 中实例化一个进程内 COM 服务器。 我做了两个 C# 项目:一个用于客户端,一个用于服务器。两个项目都使用 x86 目标平台,后者设置了“Register for COM interop”选项。我在 64 位 Windows 7 上使用 Visual Studio 2013 并使用 .net 4 进行编译。

这是服务器代码:

using System.Runtime.InteropServices;

namespace ComRibbonApplicationMenuServer 
{
    [ComVisible(true)]
    [Guid("CCF43AAC-0822-4C36-90FD-2AFF7B94E71D")]
    public interface IComRibbonApplicationMenuServer 
    {
        [DispId(1)]
        int OpenWindow();
    }

    [ComVisible(true)]
    [Guid("38B1DE85-BC15-48E1-AFAF-4A7EA506256B")]
    [ClassInterface(ClassInterfaceType.None)]
    public class ComRibbonApplicationMenuServerClass : IComRibbonApplicationMenuServer 
    {
        public ComRibbonApplicationMenuServerClass() 
        {
            // Needed for COM
        }

        public int OpenWindow() 
        {
            return 33;
        }
    }
}

这是客户端:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ComRibbonApplicationMenuClient 
{

    [Guid("CCF43AAC-0822-4C36-90FD-2AFF7B94E71D")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    interface IComRibbonApplicationMenuServer 
    {
        void OpenWindow();
    }

    [ComImport, Guid("38B1DE85-BC15-48E1-AFAF-4A7EA506256B")]
    class ComRibbonApplicationMenuServerClass 
    {
    }

    public partial class Form1 : Form 
    {

        public Form1() 
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) 
        {
            ComRibbonApplicationMenuServerClass comServerClass = new ComRibbonApplicationMenuServerClass();
            IComRibbonApplicationMenuServer comServer = (IComRibbonApplicationMenuServer)comServerClass;
            comServer.OpenWindow();
        }
    }
}

指令new ComRibbonApplicationMenuServerClass(); 抛出InvalidCastException HResult=-2147467262

我能做什么?

编辑:

感谢汉斯的回答。

如果我理解正确,正如我所怀疑的那样,如果没有一些黑客攻击,就不允许为 dotnet COM 服务器创建 dotnet COM 客户端。

正如您所猜想的那样,我正在尝试做的是测试一个 dotnet 程序,我发现该程序在作为独立应用程序执行时可以正常工作,但在由另一个应用程序执行时会崩溃(仅在 Windows XP 中)通过 COM。

为了重现该问题,我需要构建一个简单的测试程序,该程序必须启动服务器并调用一个方法来执行一些可能导致堆栈溢出异常的指令。这两个程序都使用了 GUI,这可能是问题的一部分。

为了简单起见,我首先尝试为 COM 客户端制作 winform 程序,但是,阅读您的回答后,我想我必须制作一个 MFC 应用程序来测试 COM 场景。你怎么看?

【问题讨论】:

    标签: c# .net visual-studio com


    【解决方案1】:

    抛出 InvalidCastException HResult=-2147467262。

    您将收到更多更详细的异常消息,它将告诉您由于 E_NOINTERFACE 错误返回而导致转换失败。这通常很难诊断,除了在这种情况下,真的 没有接口。您在客户端使用的声明与服务器中使用的声明严重不匹配:

    • 客户端中的 ComRibbonApplicationMenuServerClass 声明没有实现 any 接口。由于您任意省略了 [ClassInterface(ClassInterfaceType.None)],.NET 将自动生成一个。它有一个随机的 [Guid],永远不会匹配服务器的,因此会产生 E_NOINTERFACE 错误。

    • 您任意给客户端接口声明 [InterfaceType(ComInterfaceType.InterfaceIsDual)] 属性。服务器忽略它,因此使用默认值 ComInterfaceType.InterfaceIsIDispatch。这样的接口只能称为后期绑定,客户端必须使用IDispatch。这意味着如果您在第一个项目符号中解决了问题,它仍然会失败,因为服务器实际上并没有实现该接口。在 C# 中,您必须使用 dynamic 关键字才能使用这样的服务器。

    显然,客户端使用与服务器完全相同的声明是绝对必要的,通常通过在服务器上使用Tlbexp.exe 来生成类型库来确保。有点猜测你为什么进入这个pickle,IDE将拒绝让你添加对类型库的引用,它可以看到服务器是在.NET中实现的,并告诉你添加一个普通的.NET引用。这是一个相当好的建议,当普通的 .NET 方式已经以非常更好的方式工作时,使用 COM 根本没有意义。

    您可以通过在 Tlbexp.exe 生成的互操作库上使用反编译器来欺骗机器,并将它们复制/粘贴到客户端中,从而确保您有完全匹配。或者通过在客户端应用程序中使用带有 dynamic 关键字的后期绑定,无论如何都是必需的,因为服务器使用ComInterfaceType.InterfaceIsIDispatch。由于您在更改服务器时不必重复执行复制/粘贴步骤,因此痛苦也少了很多。

    但您确实需要记住,执行此操作时您实际上并没有使用 COM,CLR 本身足够聪明,可以看到 .NET 代码与 .NET 代码对话,并且会跳过创建 RCW 和 CCW。因此,如果您这样做是为了进行测试,请记住,您实际上是按照将在真实客户端应用程序中使用的方式测试服务器。您不妨通过实际添加一个 .NET 引用来对其进行测试。

    【讨论】:

    • 我在客户端的 ComRibbonApplicationMenuServerClass 中添加了属性 [ClassInterface(ClassInterfaceType.None)] 和属性 [InterfaceType(ComInterfaceType.InterfaceIsDual)] 到服务器上的 IComRibbonApplicationMenuServer,结果是一样的.我也尝试使用动态键。我将尝试使用 MFC 客户端。
    • 你没有听从我的建议,很难帮助你。
    • 用 MFC 实现。它完美地工作。无论如何,我认为应该在 .net 互操作文档中的某处说明它不可能使 .net COM 服务器表现得像一个普通的 COM 对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 2012-06-22
    • 2021-06-02
    • 2013-10-30
    • 1970-01-01
    • 2011-08-24
    • 2012-04-28
    相关资源
    最近更新 更多