0

そのため、VisualStudioのテスト環境を使用してソリューションのテストをセットアップしようとしています。セットアップは次のようになります。

Third party native library --> Managed C++ wrapper DLL --> C# project being tested
                                        ^                        ^
Foundation C# Projects -----------------|------------------------|

対応するラッパーを持つ2つの理論的に交換可能なサードパーティライブラリがあります。両方をサポートできる必要があります。

したがって、テストプロジェクトを実行すると、次のようになります。

  1. テスト対象のプロジェクトが正常に読み込まれます
  2. 基盤のC#プロジェクトが正常に読み込まれる
  3. C++ラッパーAはロードに失敗します。ラッパーBを使用すれば、すべて問題ありません。

ラッパーAの例外コールスタックは次のとおりです。

mscorlib.dll!System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(int errorCode) + 0x23 bytes 
msvcm90d.dll!<CrtImplementationDetails>::DoCallBackInDefaultDomain(int* function = 0x1018E1D0, bool cookie = false) Line 451    C++
[Native to Managed Transition]  
[Managed to Native Transition]  
Wrapper.dll!<CrtImplementationDetails>::DefaultDomain::Initialize() Line 284    C++
Wrapper.dll!<CrtImplementationDetails>::LanguageSupport::InitializeDefaultAppDomain() Line 519  C++
Wrapper.dll!<CrtImplementationDetails>::LanguageSupport::_Initialize() Line 730 C++
Wrapper.dll!<CrtImplementationDetails>::LanguageSupport::Initialize() Line 876  C++
Wrapper.dll!?.cctor@@$$FYMXXZ() Line 922 + 0x9 bytes    C++
[Native to Managed Transition]  
[Managed to Native Transition]  
TestProject.dll!TestProject.TestProjectBase.TestProjectBase() Line 44 + 0x8 bytes   C#
[Native to Managed Transition]  
[Managed to Native Transition]  
TestProject.dll!TestProject.Test.Test() Line 17 + 0x8 bytes C#
[Native to Managed Transition]  
[Managed to Native Transition]  
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.CreateTestClassInstance() + 0x174 bytes  

私はこれをオンラインで検索しましたが、同じコールスタックについて質問する人がたくさんいて、応答がほとんどありませんでした。

私はProcMonで何が起こっているのかを見ました。ラッパーAとラッパーBをロードするとどうなるかを比較しました。ラッパーBのロードが完了するまで、状況はほぼ同じように見えます。同じ時点で、ラッパーAは不可解なことに再度ロードを開始します。今回は、テストプロジェクトによって既にロードされているC#ファンデーションDLLをロードしようとします。ただし、DLL検索パスにテストフォルダが含まれていないため、これらのDLLは見つかりません(GACおよびVSTestHostディレクトリでDLLを検索します)。

私が気付いたもう1つのことは、C#コードがデフォルトのappdomainで実行されていないことです。だから私の理論は、次のことが起こっているということです:

  1. ラッパーAは、サンドボックス化されたアプリドメインにロードしようとします。
  2. ラッパーAが正常にロードされなかったとシステムに思わせる何かが発生しました
  3. システムは、デフォルトのappdomainにラッパーAをロードしようとします。このアプリドメインでは、C#DLLが読み込まれないため、読み込みを試みて失敗します。

それで、何が得られますか?ステップ2で何が起こっている可能性がありますか?ラッパーBが正常にロードされ、ラッパーAがロードされない理由として考えられるものは何ですか?

ラッパーAとラッパーBがどのように異なるのか疑問に思われる場合:それらのプロジェクトは同じ設定を持ち、同じインターフェースをサポートします。そうでなければ、それらは完全に異なります。しかし、どのような違いこの状況につながる可能性があるのか​​知りたいです。

DLLをGACに追加するか、VSTestHostディレクトリにコピーすると、ラッパーAがDLLを検出し、正常にロードされることを追加する必要があります。しかし、私はまだ何が悪いのかを理解したいと思います。

4

1 に答える 1

0

おそらく、ラッパーAは、後でマネージコードの実行を開始するネイティブスレッドを作成しています。もしそうなら、このAPIを試してください:

msclr::call_in_appdomain(appDomainId, func, object);

これにより、スレッドを実行するAppDomainを指定できますfunc。それ以外の場合、ネイティブスレッドがマネージコードを実行しようとすると、スレッドはプロセスがデフォルトのAppDomainと見なすものを使用します。これにより、スレッドの#1と#3のポイントが説明されます。質問。したがって、コードが間違ったAppDomainでスタックした場合、現在の作業ディレクトリはおそらく必要なものとは異なるため、依存するDLL/アセンブリは見つかりません。

編集: ProcessMonitorを実行し、ラッパーAとそのすべての依存関係を監視するフィルターを設定します。これにより、テストプロジェクトの実行時にこれらすべてが実際に読み込まれるようになります。

于 2011-04-04T19:16:34.933 に答える