首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >动态COM对象在C#中请求未知接口{B86A98CC-DCC0-3205-8777-7911A07DAAAF}

动态COM对象在C#中请求未知接口{B86A98CC-DCC0-3205-8777-7911A07DAAAF}
EN

Stack Overflow用户
提问于 2021-03-06 20:11:12
回答 1查看 174关注 0票数 1

通过QueryInterface()变量在C#中访问的已检测的IDispatch-based COM对象的dynamic日志显示(除其他外)未知的IID {B86A98CC-DCC0-3205-8777-7911A07DAAAF}。谷歌,GitHub和microsoft.com出现了zilch。有人知道这个接口是什么吗?如果是的话,你会用它做什么?

FWIW,对象实例化如下:

代码语言:javascript
运行
复制
var type = Type.GetTypeFromProgID(THE_PROGID);
var obj = (dynamic)Activator.CreateInstance(type);

然后立即转储接口查询日志。在LINQPad中我得到了这样的信息:

代码语言:javascript
运行
复制
099AC468 {00000000-0000-0000-C000-000000000046} IUnknown
-------- {C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4} IManagedObject
099AC420 {B196B283-BAB4-101A-B69C-00AA00341D07} IProvideClassInfo
-------- {AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90} IInspectable
-------- {ECC8691B-C1DB-4DC0-855E-65F6C551AF49} INoMarshal
-------- {94EA2B94-E9CC-49E0-C0FF-EE64CA8F5B90} IAgileObject
-------- {00000003-0000-0000-C000-000000000046} IMarshal
-------- {00000144-0000-0000-C000-000000000046} IRpcOptions
099AC42C {00020400-0000-0000-C000-000000000046} IDispatch
-------- {A6EF9860-C720-11D0-9337-00A0C90DCAA9} IDispatchEx
099AC42C {00020400-0000-0000-C000-000000000046} IDispatch
099AC42C {00020400-0000-0000-C000-000000000046} IDispatch
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
-------- {00000038-0000-0000-C000-000000000046} IWeakReferenceSource
099AC42C {00020400-0000-0000-C000-000000000046} IDispatch

C#单元测试用例(VS2015,Framework4.5.2)中的相同代码给出了类似的结果:

代码语言:javascript
运行
复制
0A41BFF0 {00000000-0000-0000-C000-000000000046} IUnknown
-------- {C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4} IManagedObject
0A41BFA8 {B196B283-BAB4-101A-B69C-00AA00341D07} IProvideClassInfo
-------- {AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90} IInspectable
-------- {ECC8691B-C1DB-4DC0-855E-65F6C551AF49} INoMarshal
-------- {94EA2B94-E9CC-49E0-C0FF-EE64CA8F5B90} IAgileObject
-------- {00000003-0000-0000-C000-000000000046} IMarshal
-------- {00000144-0000-0000-C000-000000000046} IRpcOptions
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
0A41BFB4 {00020400-0000-0000-C000-000000000046} IDispatch
-------- {A6EF9860-C720-11D0-9337-00A0C90DCAA9} IDispatchEx
0A41BFB4 {00020400-0000-0000-C000-000000000046} IDispatch

32位模式和64位模式之间没有明显的差别(当然,除了显示指针的宽度之外)。

该对象本身来自德尔福的TAutoObject,这说明了它如何响应IProvideClassInfo查询。但是,对于其他不支持该接口的对象,初始接口查询序列基本上是相同的,不管它们是响应于IDispatch::GetTypeInfoCount()还是响应于1。

但是,每次成员访问不仅导致了对IDispatch的查询,而且还导致了对未知接口的两个查询:

代码语言:javascript
运行
复制
099A5068 {00020400-0000-0000-C000-000000000046} IDispatch
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
099A5068 {00020400-0000-0000-C000-000000000046} IDispatch
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
-------- {B86A98CC-DCC0-3205-8777-7911A07DAAAF}
... and so on ad infinitum ...

这是从像这样重复的长串行中剪短的;不可能知道在相应的IDispatch调用之前是未知的查询、括号还是后面的查询。

回应Charlieface的评论:成员可以在如下长串printf语句中访问:

代码语言:javascript
运行
复制
Console.WriteLine("ApartmentType {0}", obj.ApartmentType);

如果在将每个成员访问的结果转换为其真正的数据类型后,对未知接口的双重查询就会完全消失,然后再传递给Console.WriteLine()

代码语言:javascript
运行
复制
Console.WriteLine("ApartmentType {0}", (string)obj.ApartmentType);

但是,未知查询似乎是CLR问题,而不是LINQPad问题,因为它也出现在VS2015中。

有谁知道,{B86A98CC-DCC0-3205-8777-7911A07DAAAF}代表的是哪个接口,以及使用它的目的是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-07 09:42:51

这是因为您使用的是dynamic关键字,它将触发来自.NET的所有类型的调用。

代码语言:javascript
运行
复制
/// <summary>
/// Creates a meta-object for the specified object. 
/// </summary>
/// <param name="value">The object to get a meta-object for.</param>
/// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
/// <returns>
/// If the given object implements <see cref="IDynamicMetaObjectProvider"/> and is not a remote object from outside the current AppDomain,
/// returns the object's specific meta-object returned by <see cref="IDynamicMetaObjectProvider.GetMetaObject"/>. Otherwise a plain new meta-object 
/// with no restrictions is created and returned.
/// </returns>
public static DynamicMetaObject Create(object value, Expression expression) {
    ContractUtils.RequiresNotNull(expression, "expression");

    IDynamicMetaObjectProvider ido = value as IDynamicMetaObjectProvider;
    if (ido != null && !RemotingServices.IsObjectOutOfAppDomain(value)) {
        var idoMetaObject = ido.GetMetaObject(expression);

        if (idoMetaObject == null ||
            !idoMetaObject.HasValue ||
            idoMetaObject.Value == null ||
            (object)idoMetaObject.Expression != (object)expression) {
            throw Error.InvalidMetaObjectCreated(ido.GetType());
        }

        return idoMetaObject;
    } else {
        return new DynamicMetaObject(expression, BindingRestrictions.Empty, value);
    }
}

{B86A98CC-DCC0-3205-8777-7911A07DAAAF}IDynamicMetaObjectProvider的(自动生成) IID,即:typeof(IDynamicMetaObjectProvider).GUID。它是一个纯托管接口,因此它在本机代码中没有用处。

要找到这一点,只需查看调用堆栈,但要确保线程隔离类型与对象兼容,否则将得到RPC远程处理“无用”堆栈。

在我的例子中,我必须在STAThread方法上添加.NET属性:

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66510188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档