【问题标题】:Unable to cast COM object of type 'System.__ComObject' to class type AgentInfo无法将类型为“System.__ComObject”的 COM 对象转换为类类型 AgentInfo
【发布时间】:2018-06-05 00:20:10
【问题描述】:

我有两个 C# 项目,一个是 dll,另一个是 windows 窗体应用程序。

我在dll中定义了一个CoClass,如下`'

    [ComVisible(true),
    Guid("1620BE13-A68F-4FA3-B5C8-31092D626CDA"),
    ProgId("AgentDLLServer.AgentInfo"),
    ClassInterface(ClassInterfaceType.AutoDispatch),
            ComSourceInterfaces(typeof(IAgentInfoEvents))
    ]
    public class AgentInfo : _IAgentInfo {}

实现接口_IAgentInfo,定义如下

 [
     ComVisible(true),
     Guid("CF803265-AE9D-4308-B790-560FCF63DD4C"),
     InterfaceType(ComInterfaceType.InterfaceIsDual)
    ]
    public interface _IAgentInfo{}

两者都定义在一个dll中,使用注册成功

regasm /tlb

在另一个 C# windows 客户端应用程序中,我尝试通过强制转换从运行对象表或从另一个接口获得的对象来访问 AgentInfo,如下所示`

_IAgentInfo info =(_IAgentInfo) RotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");`.

上面的代码从 ROT 中检索对象 或者,我有另一个从ROT获取的接口,定义如下

    [ 
    ComVisible(true),
    Guid("9B539A5F-5671-48AD-BF9B-7A9AF150CE39"),
    InterfaceType(ComInterfaceType.InterfaceIsDual)
    ]
    public interface _IAgentDLLServer
    { AgentInfo GetAgentInfo();}

我从 ROT 中获取到接口 _IAgentDLLServer 的引用,然后在其上调用 GetAgentInfo() 方法

`_IAgentDLLServer server=  (_IAgentDLLServer)RotNativeMethods.GetObject("BizBrainAgentService.AgentServer") `AgentInfo info=server.GetAgentInfo();

我可以将它转换为_IAgentInfo,但是当我尝试将返回的对象转换为AgentInfo时,如下

 AgentInfo info =(_IAgentInfo) rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");

我收到以下错误

Unable to cast COM object of type 'System.__ComObject' to class type 'AgentDLLService.AgentInfo'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.

我尝试了以下解决方案

一个。 STAThread放在main方法上,因为有帖子提示线程放在 此对象正在运行的无权访问类型信息 按照 Why cannot I cast my COM object to the interface it implements in C#?

b.更改应用配置文件如下

    <configuration>
     <startup>
         <supportedRuntime version="v4.0.30319" sku=".NETFramework,Version=v4.5"/>
   </startup>
</configuration>

并且版本与注册表的 InProcServer32 中的版本匹配

HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1620BE13-A68F-4FA3-B5C8-31092D626CDA}\InprocServer32\1.0.0.0\RuntimeVersion, 

根据

.NET Framework 4.5 is default and .NET Framework 3.5 is optional The strange case of System.InvalidCastException (“Unable to cast COM object of type ‘System.__ComObject’ to class type System.Windows.Forms.UserControl”) showing toolwindow

c。我尝试了 ComImport 方法

[ComImport,
    Guid("1620BE13-A68F-4FA3-B5C8-31092D626CDA")]
    public class AgentInfo { } 

在我想使用这个对象的类中,根据 A lean method for invoking COM in C#

d。双重投射对象

AgentInfo info=(AgentInfo)(object)rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");

根据 Why can't I cast this interface to a concrete class?

e 使用 as 运算符

object obj=rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");
AgentInfo info=obj as AgentInfo

f。在 agentInfoClass 上实现 IProvideClassInfo 和 IProvideClassInfo2 接口[使用 ComImport 属性导入它们]

在所有这些尝试之后,我想知道是否可以从 COM 接口或运行对象表返回 COM CoClass,而不是 COM 接口。

另外,另一个问题是,根据消息,AgentInfo 是否被视为 C# /dot 网络类型而不是 COM 类型。真的是这样吗?在这种情况下,演员表会失败。

我知道返回 CoClass 而不是接口可能不是一个好习惯,但我需要能够监听来自 AgentInfo 对象的事件,而这似乎无法通过接口实现。

【问题讨论】:

    标签: c# casting com coclass


    【解决方案1】:

    BizBrainAgentService.AgentInfo 是如何定义的?您需要访问哪些 AgentInfo 方法,哪些方法在 _IAgentInfo 中不可用?

    AgentInfo info =(_IAgentInfo) rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");
    

    您似乎正在将 BizBrainAgentService.AgentInfo 转换为接口 _IAgentInfo,只要 BizBrainAgentService.AgentInfo 实现它就可以了。

    您不能将其转换回 AgentInfo,因为对象类型仍然是 BizBrainAgentService.AgentInfo。

    在 COM 中,QueryInterface 用于导航到不同的界面https://docs.microsoft.com/en-us/cpp/atl/queryinterface

    您看到的错误解释了这一点 -

    Unable to cast COM object of type 'System.__ComObject' to class type 'AgentDLLService.AgentInfo'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
    

    使用连接点实现 COM 事件接收器会有所帮助吗?

    【讨论】:

    • “BizBrainAgentService.AgentInfo”是用于在运行对象表中注册AgentInfo对象的名称,BizBrainAgentService是在ROT中注册AgentInfo对象的windows服务。
    • 我不明白为什么我不能将它转换回AgentInfo,因为AgentInfo 是我在BizBrainAgentServce 中注册的对象。短语“表示 COM 组件的类型实例不能转换为不表示 COM 组件的类型;”似乎暗示 interop /remoting 部分被绕过了,客户端和服务器都直接使用 dot net ,因为这篇文章的答案似乎暗示了 [stackoverflow.com/questions/18020815/….我正在尝试访问 Agentinfo 中的事件,但无法从 _IAgentInfo
    • 我明白了。在您链接到的帖子中,Hans 详细解释了为什么在双方都使用 .Net 时会出现问题。如果您对事件感兴趣,那么使用连接点实现 COM 事件接收器会有帮助吗?
    • 我目前是通过给_IAgentInfo传递一个回调接口来实现的。但是,连接点方法似乎很有趣,我以后一定会尝试一下。谢谢你的建议。那么,根据韩的帖子,是否确认我正在尝试做的事情是不可能的?
    • 我无法确认,但我会接受 Han's 提供的详细信息,并通过实现连接点来检查此行为。有很好的文章介绍如何在 .Net 中实现这一点。
    猜你喜欢
    • 2016-02-02
    • 2018-06-20
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    相关资源
    最近更新 更多