您可以使用 Concord,这是 Visual Studio 附带的调试引擎(从 2012 版开始)。它可以通过一个很好的托管 API 进行扩展(并且可以使用 vsix 技术进行部署),但它没有完整的文档记录。
Concord 有调试监视器的概念,我们可以使用 IDkmDebugMonitorExceptionNotification Interface 挂钩
很酷的是这个接口可以监控所有的异常抛出。它还可以“抑制”任何检测到的异常事件,这正是我们所需要的。
我的建议是从 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;
// we're being called!
public void OnDebugMonitorException(DkmExceptionInformation exception, DkmWorkList workList, DkmEventDescriptorS eventDescriptor)
{
if (_unhandledDetected)
{
// this will cause the program to terminate
eventDescriptor.Suppress();
return;
}
if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Unhandled))
{
_unhandledDetected = true;
}
else if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Thrown))
{
if (SuppressException(exception))
{
eventDescriptor.Suppress();
}
}
}
// should we suppress a thrown (1st chance) exception?
private bool SuppressException(DkmExceptionInformation exception)
{
// implement any custom logic in here, for example use the exception's name
if (exception.Name == typeof(ArgumentOutOfRangeException).FullName)
{
// for example, use the module (assembly) name
var clrAddress = (DkmClrInstructionAddress)exception.InstructionAddress;
var clrModule = clrAddress.ModuleInstance;
if (clrModule.Name == "TheUglyOne.dll")
return true; // we don't want this one!
}
return false;
}
}
当您运行项目时,您应该会看到 所有 异常被监控(无论您的“只是我的代码”和/或异常触发器设置如何),所以您只需要实现一些逻辑来压制你真的不想看到的那些。我没有检查过,但我想您可以使用自定义属性来构建您的逻辑,因为 Dkm 类提供了相当多的 .NET 元数据信息。
注意:如您所见,有一些技巧可以确保程序正常终止。