1

In managed .NET debugging with Visual Studio 2017, is there any way to detect whether your code is being called by the debugger context, i.e. when stopped at a breakpoint?

I believe this is known as the func-eval context (more here), and it happens when you stop a breakpoint and the debugger automatically calls your code in order to display ToString() results (if enabled) on property values in the Locals, Autos, Watch, etc. windows, and also to evaluate arbitrary functions you enter while stopped.

Note that I'm aware of Debugger.IsAttached, but this is not the same; it indicates if the process is being debugged, regardless of whether the debugger is stopped or running at the time of the call. This question seeks a more specific case: Debugger.IsAttached must be true, but that's not enough because it doesn't say whether you're in the debugger's func-eval context.

Since this should be just a simple global bool value somewhere, I'm hoping the solution doesn't involve COM calls (i.e. to ICorDebugAppDomain).

Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
  • What I know is that we often use the Conditional Breakpoint to check that whether the VS debugger is stopped at a breakpoint: https://blogs.msdn.microsoft.com/devops/2014/10/06/new-breakpoint-configuration-experience-in-visual-studio-2015/ – Jack Zhai Nov 28 '17 at 08:43

1 Answers1

1

No. The code can't tell if it's being invoked by a func-eval. In general, we don't really want code behaving differently under a debugger vs. normally... that leads to horribly hard problems to debug.

If you're trying to avoid func-evals, you could use the DebuggerDisplay attribute. You could use Debugger.NotifyOfCrossThreadDependency() to signal the debugger to abort a func-eval. (see https://blogs.msdn.microsoft.com/eliofek/2012/12/12/why-do-we-get-the-function-evaluation-requires-all-threads-to-run/ for more details)

Mike S
  • 3,058
  • 1
  • 22
  • 12
  • Thanks for this info. Not sure the justification that 'providing such detection would "lead to horribly hard problems to debug" (for ***debugger*** developers, presumably)' is warranted, since the lone use case here is for the ***application*** developer to work around *debugger* bugs! For example, the myriad problems debugging value-type designs/scenarios that are inherently ruined by boxing and/or remoting (especially since for these, `DebuggerTypeProxy` only makes matters worse). – Glenn Slayden Nov 28 '17 at 19:38
  • I was talking about *Application* developers. If the app behaves differently when run under the debugger, it can be harder for the application developer to debug a production issue. We called these "heisenbugs". – Mike S Nov 28 '17 at 21:37
  • Ah, I see; thanks for the clarification, and I certainly agree with that consensus. But then the point remains from my comment above; namely that the lack of an easy way to detect *func-eval* makes it hard for the app developer to work around *bona-fide*, legitimate, and well-understood debugger issues or limitations. Ironically (or perversely), the lack of a simple indicator here may unnecessarily cause added complexity and sprawl to the requisite eventual app-level debugger workarounds, making it *harder to keep such contamination entirely out* of the production build. – Glenn Slayden Nov 28 '17 at 22:13
  • Func-eval only happens under a debugger - so it's not going to be an issue for a production server. And even when it does happen, there are best-practices to avoid func-evals. IE, use DebuggerDisplay. – Mike S Nov 28 '17 at 23:45
  • Yes, clearly *func-eval* only happens under a debugger, but I allude to debugger-workaround code that exists in the app. Sure, debugger- and/or debugging-specific code can be `#if`'d out of the app or skipped at runtime, or separated to reduce clutter, etc. But *by your own "heisenbug" principle*, all such code should be eliminated--or at least kept to a minimum--and the best way to do exactly that--**given a situation which requires *func-eval* detection**--is to expose it in the most trivial/simple way possible--so the app won't bloat with debug "heisencode" by trying to fetch it from COM. – Glenn Slayden Nov 29 '17 at 00:44
  • 1
    My use case is "don't throw a timeout exception if I'm in the middle of debugging something else"... – Benjol Apr 21 '21 at 09:58