Assembly fails to load (EEFileLoadException) under MSTest

7

I am trying to resolve an EEFileLoadException in an MSTest scenario that combines managed and native code.

My application consists of a couple dozen DLLs: some native (unmanaged) C++, some C++/CLI, and some C#. All DLLs are in the same directory. In normal operation, the main executable is native C++. One of the native DLLs (let's call it Native.DLL) links against a C++/CLI DLL, which in turn references one of the C# assemblies, and everything works fine.

Now I'm trying to write tests with MSTest. The code structure consists of C# unit tests, which reference a C++/CLI assembly, which calls into the aforementioned Native.DLL. When I attempt to run the tests, though, I get EEFileLoadException at the point where Native.DLL calls into the first C++/CLI assembly that it uses.

I've used the Fusion log viewer to try to debug the assembly load issue. Here's an abridged extract from the log:

*** Assembly Binder Log Entry  (9/12/2012 @ 2:51:14 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:\VS2010\Common7\IDE\QTAgent32.exe

LOG: Appbase = file:///C:/VS2010/Common7/IDE/
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\VS2010\Common7\IDE\QTAgent32.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:/VS2010/Common7/IDE/My.Managed.Assembly.DLL
(...)
LOG: All probing URLs attempted and failed.

So it seems clear to me that the AppBase has been set to the location of QTAgent32.exe, and it's searching for the managed assemblies there, instead of in the directory that all my DLLs are actually located in. It has no problem finding all the assemblies directly referenced by the unit tests, and it has no problem finding the unmanaged DLLs, but it fails when the unmanaged DLLs try to load additional managed assemblies (though moving the reference to the unit tests suggests this is a red herring; see my note below under "things I tried").

I'm doing all this in Visual Studio 2010. The unit tests are largely generated code; they're actually acceptance tests written with SpecFlow.

My question, if it is not yet clear, is: Why is my assembly failing to load, and how can I fix that?

Here's what I've tried already:

  • Disabled deployment (without this, I couldn't even get this far)
  • Added the path to my application to LocalTestRun.testrunconfig (as both "Root folder for the assemblies to be loaded" and "Folders to use when the tests are run")
  • Added AppDomain.CurrentDomain.SetData("APPBASE", TheDirectoryThatMyDLLsAreIn); to my unit test
  • Referenced the managed assemblies from my unit test code and adding dummy calls into them before calling the native C++, in an attempt to pre-load the assemblies so that they're already present when the C++ needs them. This had a surprising result: the same EEFileLoadException occurs when the JIT compiles the method that calls my C++/CLI assembly.
  • Added strong names to the problem assemblies. This had no effect.
  • Added the assemblies that were failing to load to the GAC. After doing this, assembly load still failed, but there was no Fusion log explaining why, and the test results included the message "The same bind was seen before, and was failed with hr = 0x80070002.". I don't think using the GAC is an acceptable solution for this project long-term anyway.

Here's the error that MSTest gives when running the test:

Test method MyTestAssembly.MyTestMethod threw exception: 
System.TypeInitializationException: The type initializer for '<Module>' threw an exception. ---> <CrtImplementationDetails>.ModuleLoadExceptionHandlerException: A nested exception occurred after the primary exception that caused the C++ module to fail to load.
 ---> System.TypeInitializationException: The type initializer for '<Module>' threw an exception. ---> <CrtImplementationDetails>.ModuleLoadException: The C++ module failed to load during process initialization.
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'MyNamespace.MyCPlusPlusCLIModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1478252538103a9d' or one of its dependencies. 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:\VS2010\Common7\IDE\QTAgent32.exe
.net
visual-studio-2010
c++-cli
mstest
asked on Stack Overflow Sep 13, 2012 by dshpak

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0