简体   繁体   English

C#中的奇怪COM对象行为

[英]Strange COM Object Behavior in C#

I've run into an issue that I think is related to the way the CLR interops with COM objects, but I was hoping some folks here could maybe offer a little more insight. 我遇到了一个问题,我认为这与CLR与COM对象的交互方式有关,但我希望这里的一些人可以提供更多的洞察力。 I want to apologize in advance for the vagueness of the question, unfortunately I'm integrating with a somewhat opaque system. 我想提前为这个问题的模糊性道歉,不幸的是我正在整合一个有些不透明的系统。

Consider the following code: 请考虑以下代码:

class Foo
{
    private IComInterface comObject;

    Foo(IServiceProvider provider)
    {
        this.comObject = serverProvider.GetService(typeof(ISomeService)) as IComInterface;
        Debug.Assert(this.comObject != null); // comObject is *not* null here
    }

    void Bar()
    {
        IOtherComInterface otherInterface = this.comObject as IOtherComInterface;
        Console.WriteLine(otherInterface == null);
    }
}

The COM interop types are embedded in my assembly, which is loaded as a plugin by another program. COM互操作类型嵌入在我的程序集中,由另一个程序作为插件加载。 When I first create an instance of Foo , the COM object provided by the service provider (which is provided by the program) is non-null. 当我第一次创建Foo实例时,服务提供者提供的COM对象(由程序提供)是非空的。 However, when I immediately call Bar() , the cast to IComOtherInterface doesn't work: the method prints "true". 但是,当我立即调用Bar() ,对IComOtherInterface不起作用:该方法打印“true”。

My problem, though, is that after some other plugins are loaded, calling Bar() again prints "false" . 但问题是,在加载了其他一些插件后,调用Bar()再次打印“false” I've verified that it's the same instance of Foo , and in fact the same instance of comObject (I tagged both with IDs using the debugger and the numbers didn't change). 我已经验证它与Foo实例相同,实际上是comObject的相同实例(我使用调试器标记了ID并且数字没有改变)。 So now the cast is succeeding. 所以现在演员阵容成功了。

So my question is this: how is this possible? 所以我的问题是:这怎么可能? Is it possible that the object stored in comObject is actually wrapping a new native COM object the second time through the same RCW? 是否有可能存储在comObject中的对象实际上是第二次通过相同的RCW包装新的本机COM对象? Is it possible that loading other assemblies has somehow changed the type-identity of IOtherComInterface so that the cast now works? 是否有可能加载其他程序集以某种方式改变了IOtherComInterface的类型标识,以便现在可以使用IOtherComInterface Some other crazy possibility that I can't actually fathom? 其他一些我无法理解的疯狂可能性?

COM objects "live" in their apartments, so do their proxies. COM对象在他们的公寓中“活着”,他们的代理也是如此。 Passing "raw" COM interface pointers across apartment boundaries (which might sometimes read "across thread boundaries") is a typical reason to have COM interface pointers still operational in terms of no access violations and otherwise crashes, but failing on the expected tasks, including failing to return another interface pointer via QueryInterface . 在公寓边界上传递“原始”COM接口指针(有时可能跨越线程边界读取)是使COM接口指针在没有访问冲突和其他方面崩溃仍然可操作的典型原因,但是在预期任务上失败,包括无法通过QueryInterface返回另一个接口指针。

Once you have a COM interface pointer, you are interested to use it in the COM apartment and respective threads, where you obtained the pointer on. 一旦有了COM接口指针,您就有兴趣在COM公寓和相应的线程中使用它,在那里您获得了指针。

To pass pointers between apartments/threads, you need to take additional steps (marshal the pointer on original thread, and then unmarshal back on the target thread). 要在公寓/线程之间传递指针,您需要采取其他步骤(将指针封送在原始线程上,然后在目标线程上解组)。 See also: 也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM