8

我正在尝试在结合了托管代码和本机代码的 MSTest 场景中解决 EEFileLoadException。

我的应用程序由几十个 DLL 组成:一些本机(非托管)C++、一些 C++/CLI 和一些 C#。所有 DLL 都在同一个目录中。在正常操作中,主要可执行文件是本机 C++。本机 DLL 之一(我们称之为 Native.DLL)链接到 C++/CLI DLL,后者又引用了一个 C# 程序集,并且一切正常。

现在我正在尝试用 MSTest 编写测试。代码结构由 C# 单元测试组成,这些测试引用了一个 C++/CLI 程序集,该程序集调用了前面提到的 Native.DLL。但是,当我尝试运行测试时,我在 Native.DLL 调用它使用的第一个 C++/CLI 程序集时收到 EEFileLoadException。

我使用 Fusion 日志查看器尝试调试程序集加载问题。以下是日志的节选:

*** 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.

所以对我来说很清楚 AppBase 已设置为 QTAgent32.exe 的位置,并且它正在那里搜索托管程序集,而不是在我所有 DLL 实际所在的目录中。找到所有单元测试直接引用的程序集,并且找到非托管 DLL 没有问题,但是当非托管 DLL 尝试加载其他托管程序集时它会失败(尽管移动对单元测试的引用表明这是一个红鲱鱼;请参阅我的注释在“我尝试过的事情”下)。

我在 Visual Studio 2010 中完成所有这些工作。单元测试主要是生成的代码;它们实际上是用 SpecFlow 编写的验收测试。

如果还不清楚,我的问题是:为什么我的程序集无法加载,我该如何解决?

这是我已经尝试过的:

  • 禁用部署(没有这个,我什至无法做到这一点)
  • 将我的应用程序的路径添加到 LocalTestRun.testrunco​​nfig (作为“要加载的程序集的根文件夹”和“运行测试时使用的文件夹”)
  • 添加AppDomain.CurrentDomain.SetData("APPBASE", TheDirectoryThatMyDLLsAreIn);到我的单元测试中
  • 从我的单元测试代码中引用托管程序集,并在调用本机 C++ 之前向其中添加虚拟调用,以尝试预加载程序集,以便在 C++ 需要它们时它们已经存在。这产生了令人惊讶的结果:当 JIT 编译调用我的 C++/CLI 程序集的方法时,会发生相同的 EEFileLoadException。
  • 为问题程序集添加了强名称。这没有效果。
  • 添加了未能加载到 GAC 的程序集。执行此操作后,程序集加载仍然失败,但没有 Fusion 日志解释原因,并且测试结果包含消息“ The same bind was seen before, and was failed with hr = 0x80070002.”。无论如何,我不认为长期使用 GAC 是该项目可接受的解决方案。

这是运行测试时 MSTest 给出的错误:

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
4

0 回答 0