Abbiamo una soluzione .NET di grandi dimensioni con progetti C# e C++/CLI che fanno riferimento l'un l'altro. Abbiamo anche diversi progetti di test unitari. Di recente abbiamo eseguito l'aggiornamento da Visual Studio 2010 & .NET 4.0 a Visual Studio 4.5 & .NET 4.5 e ora, quando proviamo a eseguire i test delle unità, sembra che ci sia un problema durante il caricamento di alcune DLL durante il test.DLL caricate da AppplicationBase errato durante il tentativo di caricare DLL miste C# e C++/CLI in un nuovo AppDomain
Il problema sembra verificarsi perché il test dell'unità viene eseguito su un AppDomain separato. Il processo di test delle unità (ad esempio nunit-agent.exe) crea un nuovo AppDomain con AppBase impostato sull'ubicazione del progetto di test, ma in base al Fusion Log, alcune DLL sono caricate con la directory dell'eseguibile di nunit come AppBase invece dell'AppBase di AppDomain .
Sono riuscito a riprodurre il problema con uno scenario più semplice, che crea un nuovo AppDomain e tenta di eseguire il test lì. Ecco come appare (ho cambiato i nomi delle classi di unit test, i metodi e la posizione del dll per proteggere gli innocenti):
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);
}
}
}
questa è l'eccezione che ottengo quando si cerca di eseguire il test di unità. Come si può vedere, il problema si verifica la dll C++ viene inizializzato e cerca di caricare il C# dll (ho cambiato i nomi delle DLL coinvolti di CPlusPlusDll e CSharpDll):
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 ---
Questo è quello che sto vedendo nella fusione Log (ho cambiato il nome della DLL per SomeDLL.dll al posto dell'originale):
*** 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.
Come si può vedere, il problema è che l'AppBase è dove risiede MyTester.exe, invece di dove risiede SomeDLL.dll (che è la stessa posizione dell'unità dll test di unità). Questo accade per diverse DLL, incluse entrambe le DLL menzionate nell'eccezione sopra.
Ho anche provato a riprodurre con un progetto di test unitario più semplice (una piccola soluzione VS2012 con 3 progetti - un progetto C# che fa riferimento a un progetto C++/CLI che fa riferimento a un altro progetto C#), ma il problema non si è riprodotto e ha funzionato perfecty. Come ho detto prima, i test unitari erano ok prima di passare a VS2012 & .NET 4.5.
Cosa posso fare? Grazie!
accade solo con il NUnit-TestRunner? Puoi anche riproporlo con MSTest? –
Succede in NUnit, MSTest e anche nel programma Tester che ho scritto qui. –
Questa offuscazione non aiuta noi ad aiutarti. Qual è la relazione tra "CSharpDll" e "SomeDLL"? –