为什么我无法调试动态加载的程序集?
Why am I unable to debug a dynamically loaded assembly?
我正在开发一个 Web API 项目,该项目使用内部模拟框架来拦截和修改来自控制器的响应。它使用 MEF 加载一个程序集,该程序集包含在某些先决条件匹配时执行的代码。
我知道这工作正常,因为我可以在响应中看到模拟已执行,但由于某种原因我无法调试动态加载程序集中的代码。虽然断点看起来很活跃,但执行永远不会在那里中断。
我试过调用 Debugger.Break();
,它确实中断了,但调用堆栈似乎是空的,Visual Studio 只显示这条消息:
我可以看到程序集及其符号已加载到模块中 window:
我可以在调用动态加载的程序集(behavior
参数)之前中断,它看起来像这样:
private HttpResponseMessage ApplyBehavior(
IMockBehavior behavior,
string controller, string action,
HttpRequestMessage request,
HttpResponseMessage mockedResponse)
{
return behavior.Apply(controller, action, request, mockedResponse);
}
如果我尝试检查 window 中的 behavior
变量,Visual Studio 会显示以下异常:
behavior.GetType()
'behavior.GetType()' threw an exception of type 'System.IO.FileNotFoundException'
Data: {System.Collections.ListDictionaryInternal}
FileName: null
FusionLog: null
HResult: -2147024894
HelpLink: null
InnerException: null
Message: "Cannot load assembly 'SuperMam.WebAPI.Mocking'."
Source: null
StackTrace: null
TargetSite: null
这是一个相当大的应用程序的一部分,我无法提取相关部分。我试图收集尽可能多的信息,但仍然不知道为什么会这样。
我该怎么做才能解决这个问题?
编辑 1
只是为了确定,如果我从我的控制器调用代码,我能够正常进入它:
var behaviourType = AppDomain.CurrentDomain.GetAssemblies()
.First(a => a.FullName.Contains("SuperMam.WebAPI.Mocking"))
.GetType("SuperMam.WebAPI.Mocking.MyBehaviour");
var behavior = (IMockBehavior)Activator.CreateInstance(behaviourType);
// I can step into this, and view the behaviour variable in the watch
behavior.Apply("dummy", "dummy", Request, null);
但即使我这样做,当模拟框架调用相同的方法时,我也无法进入它。
编辑 2
我还注意到同一个程序集(全名相同)被加载了两次。两个实例之间的区别在于它们的 CodeBase
和 Location
属性:
- 其中一个的 CodeBase 等于我的应用程序的 bin 目录,Location 等于
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...
- 另一个的CodeBase等于第一个的Location(
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...
),而Location是一个空字符串。
这可能是问题的原因吗?
您尝试动态加载的程序集是在您的系统上编译的吗?
为了调试动态加载的程序集,您需要一个 PDB 文件和 DLL。该文件包含 Visual Studio 所需的有关程序集的调试信息。在调试模式下编译程序集时,会在项目的 ./bin/Debug/
文件夹中自动创建 PDB。如果您已将 DLL 移动到另一个位置,请尝试将 PDB 也移动到同一位置。
应该是加载程序集的方法问题。
我想你正在使用:
Assembly.LoadFrom ...
尝试使用
Assembly.Load
Your app has entered a break state, but no code is currently executing that is supported by the selected debug engine.
我之前也遇到过这个错误信息:
如果可能,您可以检查一下是否与调试options/settings或VS设置有关。
(1) VS2015 的最新更新是更新 3.
(2) Enable Use Managed Compatibility Mode 将是解决此问题的目录。
原来原因是程序集没有像我想的那样被MEF加载。它正在使用 Assembly.Load(File.ReadAllBytes(mockDllPath))
加载。由于程序集是从字节数组加载的,因此调试器没有可用的调试信息。
我正在开发一个 Web API 项目,该项目使用内部模拟框架来拦截和修改来自控制器的响应。它使用 MEF 加载一个程序集,该程序集包含在某些先决条件匹配时执行的代码。
我知道这工作正常,因为我可以在响应中看到模拟已执行,但由于某种原因我无法调试动态加载程序集中的代码。虽然断点看起来很活跃,但执行永远不会在那里中断。
我试过调用 Debugger.Break();
,它确实中断了,但调用堆栈似乎是空的,Visual Studio 只显示这条消息:
我可以看到程序集及其符号已加载到模块中 window:
我可以在调用动态加载的程序集(behavior
参数)之前中断,它看起来像这样:
private HttpResponseMessage ApplyBehavior(
IMockBehavior behavior,
string controller, string action,
HttpRequestMessage request,
HttpResponseMessage mockedResponse)
{
return behavior.Apply(controller, action, request, mockedResponse);
}
如果我尝试检查 window 中的 behavior
变量,Visual Studio 会显示以下异常:
behavior.GetType()
'behavior.GetType()' threw an exception of type 'System.IO.FileNotFoundException'
Data: {System.Collections.ListDictionaryInternal}
FileName: null
FusionLog: null
HResult: -2147024894
HelpLink: null
InnerException: null
Message: "Cannot load assembly 'SuperMam.WebAPI.Mocking'."
Source: null
StackTrace: null
TargetSite: null
这是一个相当大的应用程序的一部分,我无法提取相关部分。我试图收集尽可能多的信息,但仍然不知道为什么会这样。
我该怎么做才能解决这个问题?
编辑 1
只是为了确定,如果我从我的控制器调用代码,我能够正常进入它:
var behaviourType = AppDomain.CurrentDomain.GetAssemblies()
.First(a => a.FullName.Contains("SuperMam.WebAPI.Mocking"))
.GetType("SuperMam.WebAPI.Mocking.MyBehaviour");
var behavior = (IMockBehavior)Activator.CreateInstance(behaviourType);
// I can step into this, and view the behaviour variable in the watch
behavior.Apply("dummy", "dummy", Request, null);
但即使我这样做,当模拟框架调用相同的方法时,我也无法进入它。
编辑 2
我还注意到同一个程序集(全名相同)被加载了两次。两个实例之间的区别在于它们的 CodeBase
和 Location
属性:
- 其中一个的 CodeBase 等于我的应用程序的 bin 目录,Location 等于
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...
- 另一个的CodeBase等于第一个的Location(
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\...
),而Location是一个空字符串。
这可能是问题的原因吗?
您尝试动态加载的程序集是在您的系统上编译的吗?
为了调试动态加载的程序集,您需要一个 PDB 文件和 DLL。该文件包含 Visual Studio 所需的有关程序集的调试信息。在调试模式下编译程序集时,会在项目的 ./bin/Debug/
文件夹中自动创建 PDB。如果您已将 DLL 移动到另一个位置,请尝试将 PDB 也移动到同一位置。
应该是加载程序集的方法问题。
我想你正在使用:
Assembly.LoadFrom ...
尝试使用
Assembly.Load
Your app has entered a break state, but no code is currently executing that is supported by the selected debug engine.
我之前也遇到过这个错误信息:
如果可能,您可以检查一下是否与调试options/settings或VS设置有关。
(1) VS2015 的最新更新是更新 3.
(2) Enable Use Managed Compatibility Mode 将是解决此问题的目录。
原来原因是程序集没有像我想的那样被MEF加载。它正在使用 Assembly.Load(File.ReadAllBytes(mockDllPath))
加载。由于程序集是从字节数组加载的,因此调试器没有可用的调试信息。