78

I'm looking for a way in .NET (2.0, C# in particular) for source code to trigger a debugging break as if a breakpoint was set at that point, without having to remember to set a specific breakpoint there in the debugger, and without interfering with production runtime.

Our code needs to swallow exceptions in production so we don't disrupt a client application that links to us, but I'm trying to set it up so that such errors will pop up to be analyzed if it happens to be running in a debugger, and otherwise will be safely ignored.

My attempt to use Debug.Assert(false) has been less than ideal, and I assume that Debug.Fail() would behave the same way. It should theoretically have no effect in production, and it does successfully stop when debugging, but by design there is (as far as I can tell) no way to continue execution if you want to ignore that error, like you could with an actual breakpoint, and like it would do in production where we swallow the error. It also apparently breaks evaluation of variable state because the debugger actually stops down in native system code and not in ours, so it's debugging help is limited. (Maybe I'm missing some way of getting back into things to look at the variables and so on where it happened. ???)

I was hoping for something like Debug.Break(), but it doesn't seem to exist (unless maybe in a later version of .NET?), and no other Debug methods seem applicable, either.

Update: While ctacke's answer is the best match for what I was looking for, I have since also discovered a trick with Debug.Assert()--when running in the debugger--Pause the debugger, go to the code for the Debug.Assert call pending (highlighted in green because it is down in the framework code) and hit Step-Out (shift-F11), then hit Ignore in the assert dialog box. This will leave the debugger paused upon the return of the assert (and able to continue execution as if it hadn't occurred, because it was ignored). There may be other ways to do much the same thing (does hitting Retry do this more directly?), but this way was intuitive.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Rob Parker
  • 4,078
  • 1
  • 25
  • 26

7 Answers7

141

You probably are after something like this:

if(System.Diagnostics.Debugger.IsAttached)
  System.Diagnostics.Debugger.Break();

Of course that will still get compiled in a Release build. If you want it to behave more like the Debug object where the code simply doesn't exist in a Release build, then you could do something like this:

    // Conditional("Debug") means that calls to DebugBreak will only be
    // compiled when Debug is defined. DebugBreak will still be compiled
    // even in release mode, but the #if eliminates the code within it.
    // DebuggerHidden is so that, when the break happens, the call stack
    // is at the caller rather than inside of DebugBreak.
    [DebuggerHidden]
    [Conditional("DEBUG")] 
    void DebugBreak()
    {
        if(System.Diagnostics.Debugger.IsAttached)
            System.Diagnostics.Debugger.Break();
    }

Then add a call to it in your code.

ctacke
  • 66,480
  • 18
  • 94
  • 155
  • 2
    you can also use #if DEBUG ... #endif instead – Steven A. Lowe Dec 12 '08 at 02:52
  • 11
    Sure, but it's way more ugly than a conditional because you have to wrap every call to the method with the precompiler directive too. – ctacke Dec 12 '08 at 04:24
  • 2
    To clarify, from the MSDN: `When a method marked as conditional is called, the presence or absence of the specified preprocessing symbol determines whether the call is included or omitted. If the symbol is defined, the call is included; otherwise, the call is omitted.` as well as `A conditional method must be a method in a class or struct declaration and must have a return type of void.` – Kiruse Jul 18 '17 at 20:50
14

I ran into a situation once where this didn't work

System.Diagnostics.Debugger.Break();

but this did

System.Diagnostics.Debugger.Launch();
CheGueVerra
  • 7,849
  • 4
  • 37
  • 49
  • If the Debugger is not attached then you first need to attach it with Debugger.Launch() then you can use Debugger.Break(). This is necessary if you want to debug a solution where one process starts another process and you want to debug both. – Andy B. Feb 05 '15 at 09:37
13

System.Diagnostics.Debugger.Break?

Kenny Evitt
  • 9,291
  • 5
  • 65
  • 93
shahkalpesh
  • 33,172
  • 3
  • 63
  • 88
  • (Originally replied back in Dec '08 as another answer before I knew that I could comment on answers to my own question): Ahhh, thanks, shahkalpesh. System.Diagnostics.Debugger.Break() is a good start! That's what I was missing, under Debugger instead of Debug. It looks like that will interrupt and ask to attach a debugger, which I might want to avoid. But it looks like... if (Debugger.IsAttached) Debugger.Break(); ...does what I'm looking for, as ctacke suggested. Debugger.Launch() might work for slightly different sitations, where you want a debugger if there wasn't one already. – Rob Parker Dec 07 '11 at 20:52
11

If you want to have only one line of code instead of 4, wrap

#if DEBUG
       if (Debugger.IsAttached)
            Debugger.Break();
#endif

into

public static class DebugHelper
{
    [DebuggerHidden]
    [Conditional("DEBUG")]
    public static void Stop()
    {
       if (Debugger.IsAttached)
            Debugger.Break();
    }
}

and use

DebugHelper.Stop();

DebuggerHiddenAttribute has been added to prevent the debugger from stopping on the inner code of the Stop method and from stepping into the method with F11.

Serg
  • 6,742
  • 4
  • 36
  • 54
  • +1 for the `[DebuggerHidden]` suggestion and explanation; that would make the conditionally-compiled method even more handy. Do you know how long that attribute has been supported? Is it somewhat new, or does it even go back to .NET 2.0 and VS 2010 or so? – Rob Parker Jun 05 '17 at 19:04
  • I guess it's been from version 1.1 https://msdn.microsoft.com/en-us/library/3a4d38ze(v=vs.71).aspx – Serg Jun 06 '17 at 19:50
  • Or even from 1.0 - earlier than Debugger.Break() was introduced. https://msdn.microsoft.com/library/system.diagnostics.debugger.break(v=vs.110).aspx It is worth noting that behaviour of method Break() has been changed from version 4.0 for cases when debugger is not attached. – Serg Jun 06 '17 at 20:09
  • Even with `[DebuggerHidden]` (which does prevent you to step in), the `Debugger.Break` still bypass it and stop, well, right there sadly. – jeromej Oct 04 '18 at 08:16
4

How about just configuring Visual Studio to pop up with the debugger even if you swallow it?

Do this:

  • Go to Debug->Exceptions...
  • Find the right exception, or add it if it's your own
  • Check the "Thrown" checkbox for the exception

This will stop Visual Studio on the location that exception is thrown, not just if it isn't handled.

You can see more information here.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • That's a trick worth mentioning. It's particularly helpful in identifying where the problem first occurs (and still get member state, not just exception stack trace?). But in this case I'd like the source to alert us to exceptions we aren't specifically expecting to occur and can't be set up for. – Rob Parker Dec 12 '08 at 16:13
4

A nice trick I found is putting Debugger.Break() in the ctor of your Exception.

Jonathan C Dickinson
  • 7,181
  • 4
  • 35
  • 46
  • Cool trick. No good for system exceptions, of course, but we might try that with our own Exception types, conditional on a static member or two so we can turn it on and off, along with checking Debugger.IsAttached; one setting could Break()/Launch() even without IsAttached, another only if it is. – Rob Parker Dec 12 '08 at 15:54
1

In Visual Studio 2010, hitting Retry on a Debug.Assert dialog takes you to the failed debug assertion, just as if you had a breakpoint.

Aren Cambre
  • 6,540
  • 9
  • 30
  • 36
  • Hmmm, thanks. I'll have to try that next time I hit an assert while in the debugger. I've never been clear on what "Retry" was supposed to mean. Maybe that's a holdover from a past usage of that dialog. – Rob Parker Dec 07 '11 at 21:06
  • 1
    It's a poorly-worded dialog for sure. – Aren Cambre Dec 08 '11 at 01:23