Winapi 导入WinRT winmd时如何获取接口的接口ID(IID,即GUID)? 短版

Winapi 导入WinRT winmd时如何获取接口的接口ID(IID,即GUID)? 短版,winapi,com,windows-runtime,midl,winmd,Winapi,Com,Windows Runtime,Midl,Winmd,当使用IMetadataImport时,如何从*.winmd文件获取接口的接口标识符(IID) e、 g.Windows.Globalization.ICalendar:{CA30221D-86D9-40FB-A26B-D44EB7CF08EA} 较长版本 一个是Windows.Globalization.ICalendar界面。它的IID是CA30221D-86D9-40FB-A26B-D44EB7CF08EA 它在IDL里 您可以在源Windows.Globalization.idl文件中找

当使用IMetadataImport时,如何从
*.winmd
文件获取接口的接口标识符(IID)

e、 g.Windows.Globalization.ICalendar
{CA30221D-86D9-40FB-A26B-D44EB7CF08EA}

较长版本 一个是Windows.Globalization.ICalendar界面。它的IID是
CA30221D-86D9-40FB-A26B-D44EB7CF08EA

它在IDL里 您可以在源
Windows.Globalization.idl
文件中找到它:

[exclusiveto(Windows.Globalization.Calendar)]
[uuid(CA30221D-86D9-40FB-A26B-D44EB7CF08EA)]
[version(0x06020000)]
interface ICalendar : IInspectable
{
   //...snip...
}
提醒:您不应该解析这些文件。它被编译成一个
*.winmd
程序集,该数据库就是基本事实

在页眉里 您可以在
windows.globalization.h
文件中找到它,该文件是使用导入工具从
*.winmd
生成的:

namespace ABI {
    namespace Windows {
        namespace Globalization {

            MIDL_INTERFACE("CA30221D-86D9-40FB-A26B-D44EB7CF08EA")
            ICalendar : public IInspectable
            {
               //...snip...
            }
它甚至在winmd中 您甚至可以在结果编译的
*.winmd
程序集数据库中找到InterfaceID:

但是I在使用文档化的
imadataimporter
API时如何获得它呢

代码 如何启动并运行读取
winmd
元数据文件的步骤:

// Create your metadata dispenser:
IMetadataDispsener dispener;
MetaDataGetDispenser(CLSID_CorMetaDataDispenser, IMetaDataDispenser, out dispenser);

//Open the winmd file we want to dump
String filename = "C:\Windows\System32\WinMetadata\Windows.Globalization.winmd";

IMetaDataImport reader; //IMetadataImport2 supports generics
dispenser.OpenScope(filename, ofRead, IMetaDataImport, out reader); //"Import" is used to read metadata. "Emit" is used to write metadata.
额外阅读
  • MSDN博客:(旧Word文档的初步PDF版本,据我所知,它是唯一一个Microsoft元数据API文档)()
短版 自定义属性blobGuid类的C#序列化格式:

3.2.2定义属性 用于定义自定义属性的pBlob格式在本规范的后面部分进行了定义。(广义上讲,blob将参数值记录到类构造函数中,以及命名字段/属性的零个或多个值–换句话说,是在发出元数据时实例化指定对象所需的信息). 如果构造函数不需要参数,那么就不需要提供blob参数

4.3.6获取CustomAttributeProps 自定义属性存储为blob,其格式由元数据引擎和反射理解;本质上是将创建自定义属性实例的构造函数方法的参数值列表

为了获得GuidAttriuteguid值,必须模拟C#从流中反序列化guid对象

长版本 从您的IMetadataImport开始调用IMetadataImport.GetCustomAttributeByName

第一个棘手的部分是找出我要查找的属性的名称。我知道在IDL或C中查看时,它是
Guid

而在它下面,它实际上会被称为。但这两种方法都不起作用:

  • “Guid”
    :失败,出现
    S\u FALSE
  • “GuidAttribute”
    :失败,出现
    S\u FALSE
您可以尝试使用属性类的全名:

  • “系统.运行时.互操作服务.GuidAttribute”
但这也失败了,因为这是.NET framework中GuidAttribute类的名称。在WINRT库中,您必须使用<强> >代码>“Windows .Fase.NETMultudio.GueDealth> :

  • “Guid”
    :失败,出现
    S\u FALSE
  • “GuidAttribute”
    :失败,出现
    S\u FALSE
  • “System.Runtime.InteropServices.GuidAttribute”
    :失败,错误为
    S\u FALSE
    (仅限CLR)
  • < > >强> >代码> Windows .Basic。元数据属性。
现在我们已经计算出要查找的属性的名称,我们可以查询它:

mdToken calendarTokenID = 0x02000022; //Windows.Globalization.ICalendar
String  attributeName   = "Windows.Foundation.Metadata.GuidAttribute";

Pointer blob;
UInt32 blobLen;
reader.GetCustomAttributeByName(calendarTokenID, attributeName, out blob, out blobLen);
下一个棘手的部分是解码blob

破译blob 自定义属性都有不同的序列化格式。blob基本上被传递给属性的构造函数。序列化格式与C#序列化格式相同

对于GuidAttribute属性,二进制序列化格式为20字节:

01 00                                            Prolog (2-bytes)       0x0001 ==> version 1
1D 22 30 CA D9 86 FB 40 A2 6B D4 4E B7 CF 08 EA  Guid (16-bytes)        "CA30221D-86D9-40FB-A26B-D44EB7CF08EA"
00 00                                            Trailing null (2-bytes)
提取Guid的最简单方法是声明匹配的结构,将返回的指针强制转换为该结构的类型,并访问Guid成员:

struct SerializedGuidAttribute
{
   UInt16 prolog; //2-bytes. 0x0001 
   Guid   guid;   //16-byte guid
   UInt16 footer; //2-byte footer
}
typedef SerializedGuidAttribute* PSerializedGuidAttribute;

Guid guidAttriute = PSerializedGuidAttribute(blob).guid;
你有它吗 奖金
  • Microsoft元数据API文档
    • 2000年9月8日:
    • 2001年8月2日:

您需要调用<代码> GETCuto AtestTeByNAME<代码>来检索<代码> Windows .Fase.NETMID.GuIDActudio属性的值,然后解析生成的BLB。
struct SerializedGuidAttribute
{
   UInt16 prolog; //2-bytes. 0x0001 
   Guid   guid;   //16-byte guid
   UInt16 footer; //2-byte footer
}
typedef SerializedGuidAttribute* PSerializedGuidAttribute;

Guid guidAttriute = PSerializedGuidAttribute(blob).guid;
Guid GetGuidAttribute(IMetadataReader reader, mdToken intf)
{
   Pointer blob;
   UInt32 blobLen;
   reader.GetCustomAttributeByName(intf, "Windows.Foundation.Metadata.GuidAttribute", 
         out blob, out blobLen);

   //if (blobLen != 20) { throw new Exception("Something") };

   return PSerializedGuidAttribute(blob).guid;
}