所以我一直在尝试使用 Visual Studio 测试环境对我的解决方案进行测试。设置如下所示:
Third party native library --> Managed C++ wrapper DLL --> C# project being tested
^ ^
Foundation C# Projects -----------------|------------------------|
有两个理论上可互换的第三方库和相应的包装器。我需要能够同时支持两者。
所以,当我运行我的测试项目时,会发生以下情况:
- 被测项目加载成功
- 成功加载基础 C# 项目
- 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)。
我注意到的另一件事是 C# 代码没有在默认的 appdomain 中运行。所以我的理论是以下情况正在发生:
- 包装器 A 尝试加载沙盒应用程序域。
- 发生了一些事情让系统认为 Wrapper A 没有成功加载
- 系统尝试在默认的 appdomain 中加载 Wrapper A。在此 appdomain 中,未加载 C# DLL,因此它尝试加载它们但失败。
那么,什么给了?第 2 步可能会发生什么?包装器 B 会成功加载而包装器 A 不会加载的一些可能原因是什么?
如果您想知道包装器 A 和包装器 B 有何不同:它们的项目具有相同的设置,并且它们支持相同的接口;否则它们是完全不同的。但我想知道哪些差异会导致这种情况。
我应该补充一点,如果我将 DLL 添加到 GAC 或将它们复制到 VSTestHost 目录,包装器 A 会找到 DLL 并成功加载。但是,我仍然想了解发生了什么问题。