在 C# 中通过变量访问的基于IDispatch的已检测 COM 对象的QueryInterface()
日志显示(除其他外)未知的 IID 。谷歌、GitHub 和 microsoft.com 出现了 zilch。有谁知道这个接口可能是什么,如果是的话,有人会用它做什么?dynamic
{B86A98CC-DCC0-3205-8777-7911A07DAAAF}
FWIW,对象是这样实例化的:
var type = Type.GetTypeFromProgID(THE_PROGID);
var obj = (dynamic)Activator.CreateInstance(type);
然后接口查询日志立即被转储。在LINQPad中,我得到了这个:
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,Framework 4.5.2)中的相同代码给出了类似的结果:
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 位模式之间没有明显区别(当然,除了显示指针的宽度)。
该对象本身是从 Delphi 的TAutoObject派生的,它解释了它如何响应IProvideClassInfo
查询。但是,对于其他不支持该接口的对象,无论是响应 0 还是响应 1,初始接口查询顺序基本相同IDispatch::GetTypeInfoCount()
。
但是,每个成员访问不仅会导致对未知接口的查询,IDispatch
还会导致对未知接口的两次查询:
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 语句访问,如下所示:
Console.WriteLine("ApartmentType {0}", obj.ApartmentType);
如果我在将每个成员访问的结果传递给其真实数据类型之前将其转换为真实数据类型,则未知接口的双重查询将完全消失Console.WriteLine()
:
Console.WriteLine("ApartmentType {0}", (string)obj.ApartmentType);
未知查询似乎是 CLR 的事情,而不是 LINQPad 的事情,因为它也出现在 VS2015 中。
有谁知道,哪个接口{B86A98CC-DCC0-3205-8777-7911A07DAAAF}
代表,以及可以用来做什么?