11

WinMD はバイナリ メダデータ ファイルであり、名前空間、型、クラス、メソッド、ネイティブ WinRT dll で使用できるパラメーターについて学習するために必要なすべてが含まれています。

Windows ランタイム設計から:

Windows ランタイムは、API メタデータ (.winmd ファイル) を使用して公開されます。これは、.NET フレームワーク (Ecma-335) で使用される形式と同じです。基になるバイナリ コントラクトにより、選択した開発言語で直接 Windows ランタイム API に簡単にアクセスできます。

各 .winmd ファイルは、1 つ以上の名前空間を公開します。これらの名前空間は、提供する機能によってグループ化されています。名前空間には、クラス、構造体、列挙型などの型が含まれています。

偉大な; どうすればアクセスできますか?

Winmd は COM です

内部の WinRT は引き続き COM です。また、WinRT の Winmd (Windows メタデータ) は、COM の古い TLB (タイプ ライブラリ) ファイルの最新バージョンです。

| COM                        | WinRT                          |
|----------------------------|--------------------------------|
| CoInitialize               | RoInitialize                   |
| CoCreateInstance(ProgID)¹  | RoActivateInstance(ClassName)  |
| *.tlb                      | *.winmd                        |
| compiled from idl          | compiled from idl              |
| HKCR\Classes\[ProgID]      | HKLM\Software\Microsoft\WindowsRuntime\ActivatableClassId\[ClassName] |
| Code stored in native dll  | Code stored in native dll      |
| DllGetClassObject          | DllGetClassObject              |
| Is native code             | Is native code                 |
| IUnknown                   | IUnknown (and IInspectible)    |
| stdcall calling convention | stdcall calling convention     |
| Everything returns HRESULT | Everything returns HRESULT     |
| LoadTypeLib(*.tlb)         | ???(*.winmd)                   |

COM tlb からのメタデータの読み取り

COM tlb ファイル (例: stdole.tlb) を指定すると、さまざまな Windows 関数を使用して tlb を解析し、そこから情報を取得できます。

LoadTypeLibを呼び出すと、ITypeLibインターフェイスが取得されます。

ITypeLib tlb = LoadTypeLib("c:\Windows\system32\stdole2.tlb");

そして、タイプ ライブラリ内のすべての反復処理を開始できます

for (int i = 0 to tlb.GetTypeInfoCount-1)
{
   ITypeInfo typeInfo = tlb.GetTypeInfo(i);
   TYPEATTR typeAttr = typeInfo.GetTypeAttr();

   case typeAttr.typeKind of
   TKIND_ENUM: LoadEnum(typeINfo, typeAttr);
   TKIND_DISPATCH,
   TKIND_INTERFACE: LoadInterface(typeInfo, typeAttr);
   TKIND_COCLASS: LoadCoClass(typeInfo, typeAttr);
   else
      //Unknown
   end;
   typeInfo.ReleaseTypeAttr(typeAttr);
}

*.winmdWinRT の世界のファイルで同じことを行うにはどうすればよいでしょうか?

ラリー・オスターマンより:

idl ファイルから winmd ファイルを生成します。winmd ファイルは、型の標準的な定義です。そして、それが言語プロジェクションに渡されます。言語プロジェクションは winmd ファイルを読み取り、バイナリ ファイルであるその winmd ファイルの内容を取得して、それを投影し、その言語に適した言語構造を生成する方法を知っています。

それらはすべてその winmd ファイルを読み取ります。たまたま ECMA-335 メタデータのみのアセンブリです。これは、パッケージ ファイル形式の技術的な詳細です。

winmd を生成することの良い点の 1 つは、それが規則的であるため、winmd ファイル内のメソッドと型を並べ替え、照合、結合するためのツールを構築できるようになったことです。

winmd からのメタデータの読み込み

RoGetMetaDataFileWinMDをロードするために使用してみました。ただし、RoGetMetaDataFileは、winmd ファイルを直接処理できるようにするためのものではありません。これは、既に存在し、その名前を知っている型に関する情報を発見できるようにすることを目的としています。

ファイル名を渡すと、RoGetMetadataFileの呼び出しは失敗しwinmdます。

HSTRING name = CreateWindowsString("C:\Windows\System32\WinMetadata\Windows.Globalization.winmd");
IMetaDataImport2 mdImport;
mdTypeDef mdType;

HRESULT hr = RoGetMetadataFile(name, null, null, out mdImport, out mdType);


0x80073D54
The process has no package identity

これは AppModel エラー コードに対応します。

#define APPMODEL_ERROR_NO_PACKAGE        15700L

ただし、クラスを渡すとRoGetMetadataFileは成功します。

RoGetMetadataFile("Windows.Globalization.Calendar", ...);

メタデータ ディスペンサー

MetaDataGetDispenserを使用してIMetaDataDispenserを作成するという提案がありました。

IMetaDataDispenser dispenser;
MetaDataGetDispenser(CLSID_CorMetaDataDispenser, IMetaDataDispenser, out dispenser);

おそらく、 OpenScopeメソッドを使用してwinmdファイルを開くことができます。

ディスク上の既存のファイルを開き、そのメタデータをメモリにマップします。
ファイルには、共通言語ランタイム (CLR) メタデータが含まれている必要があります。

最初のパラメーター ( Scope) は、「開くファイルの名前」です。

そこで、次のことを試みます。

IUnknown unk;
dispenser.OpenScope(name, ofRead, IID_?????, out unk);

私が求めているはずのインターフェースがわからないことを除いて。ドキュメントは言いません。それは次のように述べています。

メタデータのメモリ内コピーは、「インポート」インターフェイスの 1 つからのメソッドを使用してクエリを実行したり、「発行」インターフェイスの 1 つからのメソッドを使用して追加したりできます。

「インポート」「エミット」という言葉に重点を置いた著者は、おそらく手がかりを提供しようとしていますが、答えをあからさまに与えることはありません。

ボーナスおしゃべり

  • の名前空間または型がわかりませんwinmd(それが私たちが理解しようとしているものです)
  • WinRT では、CLR 内でマネージ コードを実行していません。これはネイティブコード用です

この質問に使用できる仮説的な動機は、まだ存在しない言語 (ada、bpl、b、c など) のプロジェクションを作成することです。もう 1 つの仮説的な動機は、IDE が wi​​nmd ファイルのメタデータ コンテンツを表示できるようにすることです。

また、WinRT は .NET とはまったく関係がないことに注意してください。

  • マネージド コードではありません。
  • アセンブリには存在しません。
  • .NET ランタイム内では実行されません。
  • しかし、.NET は既に COM と相互運用する方法を提供しているため (WinRTCOM であることを考えると)
  • マネージド コードから WinRT クラスを呼び出すことができる

多くの人は、WinRT は .NET の別名だと考えているようです。WinRT は、.NET、C#、.NET フレームワーク、または .NET ランタイムを使用、要求、または動作しません。

  • WinRT はネイティブ コードへ
  • .NET Framework クラス ライブラリはマネージ コードに対するものです。

WinRT は、ネイティブ コード用のクラス ライブラリです。.NET ユーザーは、独自のクラス ライブラリを既に持っています。

ボーナス質問

ECMA-335 バイナリ ファイルのメタデータを処理できるネイティブ mscore の関数は何ですか?

ボーナスリーディング

4

2 に答える 2