使用IMetadataImport时如何获取枚举值 [英] How to get an enumeration value when using IMetadataImport
问题描述
使用 IMetadataImport 时,如何从*.winmd
文件中获取与枚举关联的数值?
How to you get the numeric value associated with an enum from a *.winmd
file when using IMetadataImport?
一个很好的例子是 ApplicationHighContrastAdjustment 枚举:
A good example is ApplicationHighContrastAdjustment enumeration:
//Windows.UI.Xaml.ApplicationContrastMode (@020000006)
public enum ApplicationHighContrastAdjustment : uint
{
None = 0u,
Auto = 4294967295u
}
大多数枚举是0, 1, 2, ...
.但这枚举成员上还指定了其他值:
Most enumerations are 0, 1, 2, ...
. But this one has other values specified on the enum members:
- 0
- 4294967295
如何阅读以获取那些 UInt32 值
注意:该问题不必仅适用于WinRT. C#世界中使用相同的接口来检查.NET托管程序集. WinRT恰好使用相同的汇编文件格式.
Note: The question doesn't have to apply to just WinRT. The same interfaces are used in the C# world to inspect .NET managed assemblies. WinRT happens to use the same assembly file format.
我正在使用IMetadataImport
来读取*.winmd
(用于WinRT应用程序的TLB的现代版本)的内容.但是这个问题同样适用于读取有关.NET托管程序集的元数据.
I'm using IMetadataImport
to read the contents of an *.winmd
(the modern version of TLBs for WinRT applications). But the question applies equally to reading metadata about a .NET managed assembly.
关于如何启动并运行读取winmd元数据文件的精简版:
The abridged version of how to get up and running reading winmd metadata file:
// 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
的调用返回了枚举的三个成员:
The call to EnumMembers
returns us the three members of the enumeration:
- Windows.UI.Xaml.ApplicationContrastMode (@ 02000006)
- 值__ (@ 04000439,私有)
- 没有(@ 0400043A,公开)
- 自动(@ 0400043B,公开)
- Windows.UI.Xaml.ApplicationContrastMode (@02000006)
- value__ (@04000439, private)
- None (@0400043A, public)
- Auto (@0400043B, public)
我们实际上是通过调用 GetMemberProps 来找出他们的名字的(而且这个名字是私人的):
We actually find out their names (and that fact that one is private) through a call to GetMemberProps:
IMetaDataImporter.GetMemberProps(0x0400043A, ...); //"None" IMetaDataImporter.GetMemberProps(0x0400043B, ...); //"Auto"
注意:GetMemberProps是一个辅助函数.来自微软:
Note: GetMemberProps is a helper function. From Microsoft:
这是一个简单的辅助方法:如果 md 是MethodDef,则我们调用 GetMethodProps ;如果 md 是FieldDef,则称为 GetFieldProps .有关详细信息,请参见这些其他方法.
This is a simple helper method: if md is a MethodDef, then we call GetMethodProps; if md is a FieldDef, then we call GetFieldProps. See these other methods for details.
GetMemberProps 方法返回有关每个枚举值的全部信息-但不返回其实际枚举 value :
The GetMemberProps method returns a whole host of information about each enum value - but not their actual enum value:
| 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) |
我在成员属性中找不到任何指示该枚举分配值的内容.并查看其他 IMetadataImporter 方法:
I cannot find anything in the member properties that indicates the enumeration's assigned value. And looking at other IMetadataImporter methods:
- IMetdataImporter
- GetMemberProps (GetMemberProps是根据类型调用GetMethodProps或GetFieldProps的助手)
- GetMethodProps
- GetFieldProps
- IMetdataImporter
- GetMemberProps (GetMemberProps is a helper that calls GetMethodProps or GetFieldProps depending on the type)
- GetMethodProps
- GetFieldProps
- MSDN博客:元数据非托管API (初步PDF据我所知,旧版Word文档的版本是Metadata API的唯一Microsoft文档) (推荐答案
给出我想要的 Value 的枚举成员的 tokenID :
Given the tokenID of an enumeration member i want the Value of:
@0400043B = Windows.UI.Xaml.ApplicationHighContrastMode.Auto
您需要遍历 Constant 表(
0x0B
),并找到 Parent 列(columnIndex = 1)所在的位置.You need to iterate through the Constant table (
0x0B
), and find where the Parent column (columnIndex=1) is the element you want.常量表如下:
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
开始,您需要 QueryInterface ,因为它是IMetadataTables
界面:Starting with the
IMetadataImporter
, you need to QueryInterface for it'sIMetadataTables
interface://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工作的情况下,您实际上必须手动对表进行迭代:
Now with the scunt work out of the way, you have to actually manually iterate the table:
//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; }
这篇关于使用IMetadataImport时如何获取枚举值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- GetMemberProps (GetMemberProps is a helper that calls GetMethodProps or GetFieldProps depending on the type)
- GetMemberProps (GetMemberProps是根据类型调用GetMethodProps或GetFieldProps的助手)