你可以使用 Visual Studio(从2012版开始)内置的调试引擎
Concord。它通过一个很好的托管API(并且可以使用vsix技术部署),可以进行扩展,但是没有完全记录。
Concord有调试监视器的概念,我们可以使用
IDkmDebugMonitorExceptionNotification接口来挂钩。
这个接口可以监视抛出的
所有异常。它还可以“抑制”检测到的任何异常事件,这正是我们需要的。
我建议从
Hello World示例开始:下载并确保它按预期运行。
现在,只需像这样修改
HelloWorld.vsdconfigxml
:
<!--TODO: If you copy the sample, ensure to regenerate the GUID in this file -->
<!-- 1. change component level to something higher than 40500 -->
<ManagedComponent
ComponentId="51736b11-9fb4-4b6d-8aca-a10a2b7ae768"
ComponentLevel="40501"
AssemblyName="HelloWorld">
<!-- 2. change class full name to HelloWorld.ExceptionHandler, for example -->
<Class Name="HelloWorld.ExceptionHandler">
<Implements>
<InterfaceGroup>
<NoFilter/>
<!-- 3. change supported interface -->
<Interface Name="IDkmDebugMonitorExceptionNotification"/>
</InterfaceGroup>
</Implements>
</Class>
</ManagedComponent>
然后,只需创建一个名为
ExceptionHandler.cs
的类,并在其中放置以下内容:
public class ExceptionHandler : IDkmDebugMonitorExceptionNotification
{
private bool _unhandledDetected;
public void OnDebugMonitorException(DkmExceptionInformation exception, DkmWorkList workList, DkmEventDescriptorS eventDescriptor)
{
if (_unhandledDetected)
{
eventDescriptor.Suppress();
return;
}
if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Unhandled))
{
_unhandledDetected = true;
}
else if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Thrown))
{
if (SuppressException(exception))
{
eventDescriptor.Suppress();
}
}
}
private bool SuppressException(DkmExceptionInformation exception)
{
if (exception.Name == typeof(ArgumentOutOfRangeException).FullName)
{
var clrAddress = (DkmClrInstructionAddress)exception.InstructionAddress;
var clrModule = clrAddress.ModuleInstance;
if (clrModule.Name == "TheUglyOne.dll")
return true;
}
return false;
}
}
当您运行项目时,您应该看到
所有异常都被监视(不管您的“仅限我的代码”和/或异常触发器设置如何),所以您需要做的就是实现一些逻辑来抑制您真正不想看到的异常。我没有检查过,但我认为您可以使用自定义属性构建逻辑,因为Dkm类提供了相当多的.NET元数据信息。
注意:正如您所看到的,有一些技巧可以确保程序正常终止。
DebuggerStepThrough
属性应该是你的好朋友。然而,看起来你可能无法直接修改第三方库... - Dirk Vollmar