お互いを参照するC#プロジェクトとC++/CLIプロジェクトの両方で大きな.NETソリューションがあります。 私たちはまた、いくつかのユニットテストプロジェクトを持っています。私たちは最近、Visual Studio 2010 & .NET 4.0からVisual Studio 4.5 & .NET 4.5にアップグレードしました。ユニットテストを実行しようとすると、テスト中にいくつかのDLLがロードされているようです。新しいAppDomainで混在C#とC++/CLI dllをロードしようとすると、間違ったAppplicationBaseからDLLがロードされる
この問題は、単体テストが別のAppDomainで実行されるために発生します。ユニットテストプロセス(たとえばnunit-agent.exe)は、AppBaseをテストプロジェクトの場所に設定して新しいAppDomainを作成しますが、Fusion Logによれば、DLLのいくつかは、AppDomainのAppBaseではなくAppBaseとしてnunitの実行可能ディレクトリ。
私は簡単なシナリオで問題を再現することができました。これにより、新しいAppDomainが作成され、テストがそこで実行されます。ここでは(私は無実を保護するためにユニットテストクラス、メソッド、およびDLLの場所の名称を変更)、それがどのように見えるかです:
class Program
{
static void Main(string[] args)
{
var setup = new AppDomainSetup {
ApplicationBase = "C:\\DirectoryOfMyUnitTestDll\\"
};
AppDomain domain = AppDomain.CreateDomain("MyDomain", null, setup);
ObjectHandle handle = Activator.CreateInstanceFrom(domain, typeof(TestRunner).Assembly.CodeBase, typeof(TestRunner).FullName);
TestRunner runner = (TestRunner)handle.Unwrap();
runner.Run();
AppDomain.Unload(domain);
}
}
public class TestRunner : MarshalByRefObject
{
public void Run()
{
try
{
HtmlTransformerUnitTest test = new HtmlTransformerUnitTest();
test.SetUp();
test.Transform_HttpEquiv_Refresh_Timeout();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
これは、ユニットテストを実行しようとしたとき、私が得る例外です。
System.TypeInitializationException: The type initializer for '' threw an exception. ---> .ModuleLoadExceptionHandlerException: A nested exception occurred after the primary exception that caused the C++ module to fail to load. ---> System.TypeInitializationException: The type initializer for '' threw an exception. ---> .ModuleLoadException: The C++ module failed to load during vtable initialization. ---> System.IO.FileNotFoundException: Could not load file or assembly 'CSharpDll, Version=8.80.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. at [email protected]@[email protected]@[email protected]@@YMXXZ() at _initterm_m((fnptr)* pfbegin, (fnptr)* pfend) in f:\dd\vctools\crt_bld\self_x86\crt\src\puremsilcode.cpp:line 219 at .LanguageSupport.InitializeVtables(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 331 at .LanguageSupport._Initialize(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 491 at .LanguageSupport.Initialize(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 702 --- End of inner exception stack trace --- at .ThrowModuleLoadException(String errorMessage, Exception innerException) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 194 at .LanguageSupport.Initialize(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 712 at .cctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 754 --- End of inner exception stack trace --- at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode) at .DoCallBackInDefaultDomain(IntPtr function, Void* cookie) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 406 at .DefaultDomain.Initialize() in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 277 at .LanguageSupport.InitializeDefaultAppDomain(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 342 at .LanguageSupport._Initialize(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 539 at .LanguageSupport.Initialize(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 702 --- End of inner exception stack trace --- at .ThrowNestedModuleLoadException(Exception innerException, Exception nestedException) in f:\dd\vctools\crt_bld\self_x86\crt\src\minternal.h:line 184 at .LanguageSupport.Cleanup(LanguageSupport* , Exception innerException) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 662 at .LanguageSupport.Initialize(LanguageSupport*) in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 710 at .cctor() in f:\dd\vctools\crt_bld\self_x86\crt\src\mstartup.cpp:line 754 --- End of inner exception stack trace ---
これは私が見ているものです:あなたが見ることができるように、問題はC++のdllが初期化されて起こるとC#のDLLをロードしよう(私はCPlusPlusDllとCSharpDllに関与するDLLの名前を変更しました) Fusionのログに(私ではなく、元のSomeDLL.dllするDLLの名前を変更した):
*** Assembly Binder Log Entry (8/1/2013 @ 01:47:48 PM) *** The operation failed. Bind result: hr = 0x80070002. The system cannot find the file specified. Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable c:\users\yshany\documents\visual studio 2012\Projects\MyTester\MyTester\bin\Debug\MyTester.exe --- A detailed error log follows. === Pre-bind state information === LOG: User = WF-IL\yshany LOG: DisplayName = SomeDLL, Version=8.80.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///c:/users/yshany/documents/visual studio 2012/Projects/MyTester/MyTester/bin/Debug/ LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache Base = NULL LOG: AppName = MyTester.exe Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: c:\users\yshany\documents\visual studio 2012\Projects\MyTester\MyTester\bin\Debug\MyTester.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///c:/users/yshany/documents/visual studio 2012/Projects/MyTester/MyTester/bin/Debug/SomeDLL.DLL. LOG: Attempting download of new URL file:///c:/users/yshany/documents/visual studio 2012/Projects/MyTester/MyTester/bin/Debug/SomeDLL/SomeDLL.DLL. LOG: Attempting download of new URL file:///c:/users/yshany/documents/visual studio 2012/Projects/MyTester/MyTester/bin/Debug/SomeDLL.EXE. LOG: Attempting download of new URL file:///c:/users/yshany/documents/visual studio 2012/Projects/MyTester/MyTester/bin/Debug/SomeDLL/SomeDLL.EXE. LOG: All probing URLs attempted and failed.
あなたが見ることができるように、問題はMyTester.exeが存在する場所のappBaseではなく、ということですSomeDLL.dllが存在する場所(これは、単体テストdllと同じ場所です)。これは、上記の例外で言及した両方のDLLを含むいくつかのDLLで発生します。
私はまた、より単純な単体テストプロジェクト(3つのプロジェクト - 別のC#プロジェクトを参照するC++/CLIプロジェクトを参照するC#プロジェクトの小さなVS2012ソリューション)で再現しようとしましたが、問題は再現せず、機能しました完璧。以前に述べたように、VS2012 & .NET 4.5にアップグレードする前に単体テストは正常でした。
どうすればよいですか? ありがとう!
はそれだけでNUnitの-テストランナーで発生していunamanaged C++クラスからコンストラクタを削除することができますか?あなたはMSTestでそれを再現できますか? –
NUnit、MSTest、そしてここで書いたTesterプログラムでも起こります。 –
この難読化は私たちがあなたを助けるのに役立つものではありません。 "CSharpDll"と "SomeDLL"の関係は何ですか? –