7

私は奇妙な問題に遭遇しています。一部の C# ラッパー クラスを介して .NET で一部のレガシ C/C++ コードを使用できるようにする Windows ランタイム コンポーネント (Windows ストア用) を作成しました。

WRCプロジェクト(同じソリューション内の両方のプロジェクト) を参照するテスト ハーネス Store アプリ (以下、「test1」と呼びます) を作成しました。コンポーネントを呼び出し、すべて正常に動作します。

次に、WRC プロジェクトから次の出力ファイルを取得します。

MyWrtComponent.dll
MyWrtComponent.exp
MyWrtComponent.pdb
MyWrtComponent.pri
MyWrtComponent.winmd

...そして、別の Store アプリ プロジェクト ("test2") からそれらを使用しようとします。このプロジェクトでは、MyWrtComponent プロジェクトを参照する代わりに、.winmd ファイルへの参照を追加します。すべて正常にビルドされますが、test2 アプリを実行すると、MyWrtComponent に実装されている C# クラスの 1 つを使用しようとするとすぐに、mscorlib から System.IO.FileNotFound 例外が発生します。

at System.StubHelpers.StubHelpers.GetWinRTFactoryObject(IntPtr pCPCMD)
at MyWrtComponent.MyWrtClass..ctor()

The specified module could not be found.
(Exception from HRESULT: 0x8007007E)

MyWrtComponent のリリース ビルドとデバッグ ビルドを使用しても、違いはありません。

テスト 2 で ProcMon を実行すると、vccorlib120_app.DLL (デバッグをビルドしている場合は vccorlib120d_app.DLL) の読み込みに失敗する試みがいくつか見られます。

QueryOpen   F:\test2\bin\Debug\AppX\vccorlib120d_app.DLL    NAME NOT FOUND
QueryOpen   F:\test2\bin\Debug\AppX\vccorlib120d_app.DLL    NAME NOT FOUND
CreateFile  C:\Windows\SysWOW64\vccorlib120d_app.DLL    NAME NOT FOUND

C:\Windows\SysWOW64 フォルダにこのファイルが存在しないことを確認しました。それが私の問題に関連しているかどうかはわかりません。

test1 を実行すると、さまざまな場所が検索され、ファイルが見つかります。

QueryOpen   F:\test1\bin\Debug\AppX\vccorlib120d_app.DLL    NAME NOT FOUND
CreateFile  C:\Program Files\WindowsApps\Microsoft.VCLibs.120.00.Debug_12.0.20827.3_x86__8wekyb3d8bbwe\vccorlib120d_app.dll SUCCESS

両方のテスト プロジェクトの bin\Debug\AppxManifest.xml を比較したところ、重要な違いが 1 つあります。test1 には次のものがありますが、test2 にはありません。

<Dependencies>
  <PackageDependency Name="Microsoft.VCLibs.120.00.Debug" MinVersion="12.0.20827.3" />
</Dependencies>

これらの 3 行を test2 の生成された出力に追加してアプリを実行すると、機能しますが、もちろんそれは実際の修正ではありません。

誰かがここで何が起こっているのか理解していますか? MyWrtComponent には、どういうわけか伝達されていない依存関係がありますか、それともランタイム コンポーネントと一緒に vccorlib120d_app.DLL をパッケージ化するために何かをすることになっていますか?

前もって感謝します。

4

2 に答える 2

14

さて、ここでいくつかの問題が発生しています。最初の 1 つは、WinRT コンポーネントが C++ を使用しているため、アプリで Microsoft Visual C++ ランタイム パッケージへの参照が必要であるということです。これは、コンポーネントのエンド ユーザー (アプリ開発者) は、アプリのソリューション エクスプローラーで [参照] フォルダーを右クリックし、[Windows] > [拡張機能] に移動して、利用可能な SDK のリストから [Microsoft Visual C++ ランタイム パッケージ] を選択し、 [OK] をクリックします。

第 2 に、このコンポーネントを自分用に保持する場合は、プロジェクトを参照する方が簡単です。配布する場合は、SDK を作成して、すべての部品が一緒にあることを確認する必要があります。 、これは C++ WinRT コンポーネントには必要ですが、C# または VB.NET コンポーネントには必要ないことに注意してください。その理由は、C++ WinRT コンポーネントがメタデータ (WinMD ファイル) と実装 (DLL ファイル) に分割されているためと思われます。 C# と VB.NET では、メタデータとその実装は同じファイル (WinMD) にあります。SDK を作成する場合は、MSDNのこのドキュメントをお読みください。

于 2013-10-28T20:42:19.903 に答える
4

2 番目のビルドはアプリ パッケージの要件に違反しています。ストアに配信するアプリケーション パッケージにすべての依存関係が埋め込まれており、アプリケーション マニフェストにそれらの依存関係がすべてリストされている状態。これは強力な DLL Hell 対策です。Store ユーザーは、遭遇した問題を解決する見込みがありません。

.winmd ファイルへの参照を追加すると、コンパイラは正常に動作し、ソース コードをコンパイルするのに十分な情報が含まれます。しかし、次のステップはうまくいきません。.winmd ファイルは、アプリ パッケージをまとめるのに十分な情報をビルド システムに提供しません。コンポーネントに追加の依存関係があることは、.winmd ファイルだけではわかりません。メイン プロジェクトはマネージド プロジェクトであるため、Microsoft.VCLibs に依存していません。

appxmanifest を自分で維持できないわけではありません。デバッグとリリースのビルドで異なることから始めて、間違えやすい余分な作業です。次の VS の更新で問題が発生します。間違いなく Microsoft.VCLibs の更新が行われるため、マニフェストのバージョン番号を更新する必要があります。

プロジェクト参照を使用すると、常に適切なパッケージを取得する簡単な方法になります。

于 2013-10-28T18:19:16.830 に答える