Is there a way to prevent Visual Studio from breaking on exceptions in a specific method?

后端 未结 3 1682
暖寄归人
暖寄归人 2021-02-07 19:55

I know I can control the way Visual Studio handles exceptions according to their type and to the fact that they\'re eventually caught using the \"Exception\" dialog.

How

相关标签:
3条回答
  • 2021-02-07 20:17

    What you can do is use Concord, the debug engine that ships with Visual Studio (starting with version 2012). It's quite extensible through a nice managed API (and deployable using vsix technology), but it's not fully documented.

    Concord has the concept of debug monitors, that we can hook using the IDkmDebugMonitorExceptionNotification Interface

    The cool thing is this interface can monitor all exceptions thrown. It can also "suppress" any detected exception event, which is exactly what we need.

    What I suggest is to start with the Hello World sample: . Download it, and make sure it runs as expected for you.

    Now, just modify HelloWorld.vsdconfigxml like this:

    <!--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>
    

    Then, just create an ExceptionHandler.cs class and put something like this in there:

    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;
        }
    }
    

    When you run the project, you should see all exceptions being monitored (regardless of your 'just my code' and/or exception triggers settings), so what you just need to do is implement some logic to suppress the ones you really don't want to see. I've not checked but I suppose you could build your logic using custom attributes as the Dkm classes provide quite a lot of .NET metadata information.

    Note: as you can see, there is some trickery to make sure the program will terminate normally.

    0 讨论(0)
  • 2021-02-07 20:20

    I don't want to enable "just my code" debugging

    Yeah, stop there right now. That is exactly the feature you need to not get the unwanted debugger breaks. If you don't want to know about somebody else's crappy code then flip that checkbox back on.

    This invariably goes off the rails when programmers use exceptions for flow control. A very common crime. It takes two of them to turn that into a mess that turns a debugging session into a very tedious click nightmare. When you need the debugger feature that breaks on the first-chance exception then you basically lost if somebody else needed that as well.

    Everybody hopes that they can magically use the [DebuggerNonUserCode] or [DebuggerHidden] or [DebuggerStepThrough] attributes to make that problem disappear. It doesn't. The other programmer did not think his code was unimportant enough to deserve those attributes. And, well, it wasn't because there's always a bug hidden in code that uses try/catch-em-all code. Pokémon code.

    So Microsoft had to find another way to help programmers deal with crappy library code. They did. Tick that checkbox, bam, solved. Nothing you can do about that crappy code anyway, other than sending a nasty-gram to the author. Don't let us or Microsoft slow you down doing that as well, y'all have to get along to create a product that people like to use.

    0 讨论(0)
  • 2021-02-07 20:38

    I think it's not possible in visual studio but it certainly is in WinDbg. See for example http://blogs.msdn.com/b/alejacma/archive/2009/08/24/managed-debugging-with-windbg-breaking-on-an-exception-part-1.aspx

    On a side note it seems that starting with visual studio 2010 you can load and use WinDbg extension DLLs directly providing aditional functionality (including possibly the one that you need) but I haven't tried this yet - see for example http://www.dotnetcurry.com/ShowArticle.aspx?ID=648

    0 讨论(0)
提交回复
热议问题