Com 使用IMetadataImport时如何获取枚举值 短版

Com 使用IMetadataImport时如何获取枚举值 短版,com,windows-runtime,midl,winmd,Com,Windows Runtime,Midl,Winmd,使用IMetadataImport时,如何从*.winmd文件获取与枚举关联的数值 ApplicationHighControlAdjustment枚举就是一个很好的例子: //Windows.UI.Xaml.ApplicationContrastMode (@020000006) public enum ApplicationHighContrastAdjustment : uint { None = 0u, Auto = 4294967295u } 大多数枚举是0、1、2、

使用IMetadataImport时,如何从*.winmd文件获取与枚举关联的数值

ApplicationHighControlAdjustment枚举就是一个很好的例子:

//Windows.UI.Xaml.ApplicationContrastMode (@020000006)
public enum ApplicationHighContrastAdjustment : uint
{
    None = 0u,
    Auto = 4294967295u
}
大多数枚举是0、1、2、。。。。但此枚举在枚举成员上指定了其他值:

0 4294967295 如何读取和获取这些UInt32值

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

长版本 我正在使用IMetadataImport读取*.winmd的内容,这是WinRT应用程序TLB的现代版本。但这个问题同样适用于读取有关.NET托管程序集的元数据

有关如何启动并运行读取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:

调用EnumMembers将返回枚举的三个成员:

//Windows.UI.Xaml.ApplicationContrastMode (@020000006)
public enum ApplicationHighContrastAdjustment : uint
{
    None = 0u,
    Auto = 4294967295u
}
Windows.UI.Xaml.ApplicationContrast模式@02000006 价值@04000439,私人 0400043A无,公共 自动@0400043B,公共 获取每个枚举值的信息 我们实际上通过调用GetMemberProps找到了他们的名字以及一个是私有的事实:

注意:GetMemberProps是一个帮助函数。来自Microsoft:

这是一个简单的助手方法:如果md是MethodDef,那么我们调用GetMethodProps;如果md是FieldDef,那么我们称之为GetFieldProps。有关详细信息,请参阅这些其他方法

GetMemberProps方法返回关于每个枚举值的全部信息,但不是它们的实际枚举值:

我在成员属性中找不到任何指示枚举赋值的内容。看看其他IMetadataImporter方法:

数据导入器 GetMemberProps GetMemberProps是根据类型调用GetMethodProps或GetFieldProps的帮助程序 GetMethodProps 格特菲尔德道具 GetPropertyProps GetEventProps GetParamProps GetInterfaceImplProps GetCustomAttributeProps GetTypeDefProps GetTypeRefProps GetScopeProps GetPermissionSetProps GetModuleRefProps GetNestedClassProps GetMemberRefProps 额外阅读 MSDN博客:旧Word文档的初步PDF版本,据我所知,它是唯一一个Microsoft元数据API文档 给定枚举成员的tokenID,我希望值为:

您需要遍历常量表0x0B,并找到所需元素的父列columnIndex=1所在的位置

常量表如下所示:

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);
现在,随着scunt工作的完成,您必须手动迭代表:

//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;
}

枚举成员是文本字段,因此您必须使用IMeadatatables从常量表中读取它们的值。请参阅第157页或Sergey Lidin在Microsoft.NET IL Assembler中的书:
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
...
//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;
}