0

所以我一直在尝试使用 Visual Studio 测试环境对我的解决方案进行测试。设置如下所示:

Third party native library --> Managed C++ wrapper DLL --> C# project being tested
                                        ^                        ^
Foundation C# Projects -----------------|------------------------|

有两个理论上可互换的第三方库和相应的包装器。我需要能够同时支持两者。

所以,当我运行我的测试项目时,会发生以下情况:

  1. 被测项目加载成功
  2. 成功加载基础 C# 项目
  3. 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 中运行。所以我的理论是以下情况正在发生:

  1. 包装器 A 尝试加载沙盒应用程序域。
  2. 发生了一些事情让系统认为 Wrapper A 没有成功加载
  3. 系统尝试在默认的 appdomain 中加载 Wrapper A。在此 appdomain 中,未加载 C# DLL,因此它尝试加载它们但失败。

那么,什么给了?第 2 步可能会发生什么?包装器 B 会成功加载而包装器 A 不会加载的一些可能原因是什么?

如果您想知道包装器 A 和包装器 B 有何不同:它们的项目具有相同的设置,并且它们支持相同的接口;否则它们是完全不同的。但我想知道哪些差异导致这种情况。

我应该补充一点,如果我将 DLL 添加到 GAC 或将它们复制到 VSTestHost 目录,包装器 A 会找到 DLL 并成功加载。但是,我仍然想了解发生了什么问题。

4

1 回答 1

0

也许您的 Wrapper A 正在创建一个本机线程,该线程稍后开始运行托管代码。如果是这样,那么试试这个 API

msclr::call_in_appdomain(appDomainId, func, object);

这允许您指定线程func应在哪个 AppDomain 中运行。否则,当本机线程尝试运行托管代码时,线程将使用进程认为默认 AppDomain 的任何内容,这将解释您的 #1 和 #3 点问题。因此,如果您的代码卡在错误的 AppDomain 中,它将找不到任何相关的 DLL/程序集,因为当前工作目录可能与您想要的不同。

编辑:运行 ProcessMonitor 并设置一个过滤器来监视 Wrapper A 及其所有依赖项,这将有助于确保在运行测试项目时所有这些都实际加载。

于 2011-04-04T19:16:34.933 回答