代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

如何在使用IMetadataImport时获取枚举值

  •  0
  • Ian Boyd  · 技术社区  · 7 年前

    短版

    如何获取与 枚举 *.winmd IMEADATAI进口

    一个很好的例子是 枚举:

    //Windows.UI.Xaml.ApplicationContrastMode (@020000006)
    public enum ApplicationHighContrastAdjustment : uint
    {
        None = 0u,
        Auto = 4294967295u
    }
    

    0, 1, 2, ... . 但此参数在枚举成员上指定了其他值:

    • 0

    我怎么读得到那些 UInt32

    注意 :这个问题不一定只适用于WinRT。在C世界中,相同的接口用于检查.NET托管程序集。WinRT恰好使用相同的程序集文件格式。

    长版

    我在用 IMetadataImport 阅读 *.winmd公司

    这个 abridged version 如何启动和运行读取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.UI.Xaml.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.
    

    我们现在有了一个阅读器。我不必列举程序集中的类型,而是可以直接跳到下面这个问题中有趣的类型: 0x02000006 :

    //Get metadata for enum Windows.UI.Xaml.ApplicationHighContrastAdjustment
    mdToken tokenID = 0x02000006; //Windows.UI.Xaml.ApplicationHighContrastAdjustment
    
    //btw, this is all hypothetical code that is vaguely C#/Java-like.
    
    Pointer enum = null;
    mdToken memberID;
    int nCount;
    while (reader.EnumMembers(ref enum, tokenID, out memberID, 1, out nCount) == S_OK)
    {
       //out MemberID receives the TokenID of each member of the enumeration
    }
    reader.CloseEnum(enum);
    

    EnumMembers

    • Windows.UI.Xaml.ApplicationContrast模式 (@0200006)
      • 价值__
      • 没有 (@0400043A,公共)
      • 自动 (@0400043B,公开)

    获取成员属性

    IMetaDataImporter.GetMemberProps(0x0400043A, ...); //"None"
    IMetaDataImporter.GetMemberProps(0x0400043B, ...); //"Auto"  
    

    :GetMemberProps是一个辅助函数。来自Microsoft:

    这是一个简单的辅助方法:if 是一个MethodDef,然后我们调用 ;如果 医学博士 是一个FieldDef,然后我们打电话 获取属性 . 有关详细信息,请参见这些其他方法。

    这个 获取成员属性 价值 :

    | Metadata          | @0400043A         | @0400043B       |
    |-------------------|-------------------|-----------------|
    | Name              | "None"            | "Auto"          |
    | Attributes        | 0x00008056        | 0x00008056      |
    | Signature         | 06 11 A3 95       | 06 11 A3 95     |
    | CodeRVA           | 0x00000000        | 0x00000000      |
    | CPlusTypeFlag     | ELEMENT_TYPE_U4   | ELEMENT_TYPE_U4 |
    | DefaultValue      | (none)            | (none)          |
    

    我在里面找不到任何东西 成员属性 指示枚举的赋值。看着其他人 IMETadatai进口商

    • IMETataImporter
      • (GetMemberProps是根据类型调用GetMethodProps或GetFieldProps的帮助程序)
      • 获取属性属性
      • 获取事件属性
      • 获取参数属性
      • GetInterfaceImplProps
      • GetTypeDefProps
      • GetScopeProps
      • GetPermissionSetProps
      • GetNestedClassProps
      • GetMemberRefProps

    额外阅读

    0 回复  |  直到 7 年前
        1
  •  1
  •   Ian Boyd    6 年前

    鉴于 令牌ID 一个枚举成员的 价值

    @0400043B = Windows.UI.Xaml.ApplicationHighContrastMode.Auto
    

    你需要迭代 0x0B ),然后找到 起源

    enter image description here

    这个 常数

    Rid  Type (iBYTE)         Parent (iCodedToken)  Value (iBLOB)
    ===  ===================  ====================  ===============
    1    ELEMENT_TYPE_I4 (8)  @04000002             00 00 00 00
    2    ELEMENT_TYPE_I4 (8)  @04000003             01 00 00 00
    3    ELEMENT_TYPE_I4 (8)  @04000005             00 00 00 00
    ...
    883  ELEMENT_TYPE_I4 (8)  @0400040A             02 00 00 00
    884  ELEMENT_TYPE_U4 (9)  @0400043A             00 00 00 00
    885  ELEMENT_TYPE_U4 (9)  @0400043B             FF FF FF FF
    886  ELEMENT_TYPE_I4 (8)  @0400043D             00 00 00 00
    ...
    

    IMetadataImporter ,你需要 因为它是 IMetadataTables 接口:

    //Get the tables interface
    IMetadataTables tables = reader as IMetadataImporter;
    
    //get the number of rows in the Constant (11) table
    UInt32 tabConstant = 11; //the "Constant" table
    
    UInt32 rowSize;
    UInt32 rowCount;
    UInt32 columnCount;
    UInt32 keyColumn;
    String tableName;
    tables.GetTableInfo(tabConstant,
           out rowSize,
           out rowCount,
           out columnCount,
           out keyColumn,
           out tableName);
    

    //Loop over ever row in the Constants table
    //and look for Parent (columnIndex=1) is the parent we want
    //all code released into the public domain; no attribution required
    UInt32 desiredToken = 0x0400043B;
    
    UInt32 colParent = 1; // Parent (iCodedToken)
    UInt32 colValue  = 2; // Value  (iBLOB)
    
    for (int i = 0 to rowCount-1)
    {
       //Get the Parent codedToken of this row
       UInt32 value;
       tables.GetColumn(tabConstant, colParent, i, outvalue);
    
       // Is it the parent we're interested in (i.e. @0400043A)
       if (value != desiredToken)
          continue;
    
       // We found it! Get the value from the "Value" (iBLOB) column 2
       tables.GetColumn(tabConstant, colValue, i, out value);
    
       //Convert blob UInt32 to a pointer to data
       UInt32 dataLen;
       Pointer data;
       tables.GetBlob(value, out dataLen, out dataLen, out data);
    
       //Convert the dataLen bytes pointed to by data to a UInt32
       UInt32 enumValue = PUInt32(data)^;
    
       return enumValue;
    }
    
    推荐文章