Skip to content

Tips for debugging extensions

Gregg Miskelly edited this page Jun 6, 2019 · 18 revisions

This page contains tips for better debugging of Concord extensions in particular, and, to some degree at least, Visual Studio all up.

Debugging extensions loaded into msvsmon.exe processes

Extensions will load into an msvsmon.exe process if either: (1) they are configured to load into a worker process -or- (2) they are monitor components (components with a component level less than 100,000) and the target process is 64-bit.

The best way to debug these:

  1. Install the Microsoft Child Process Debugging Power Tool into Visual Studio using the Extension Manager.
  2. Configure your startup project (example: vsix.csproj) to use either native-only or native+managed (interop) debugging. If your startup project is already a VC project (.vcxproj), this is the default. If your startup project is a C# project, see below.
  3. Open 'Debug->Other Debug Targets->Child Process Debugging Settings' to configure the child process debugger.
  4. Check the checkbox to 'Enable Child Process Debugging'
  5. Set the '<All other processes>' action to 'Do not debug'
  6. Click the blank row in the process list, and add an entry for msvsmon.exe
  7. Set the 'Debugger Type' value to what is appropriate for your extension (example: 'Managed (v4.6, v4.5, v4.0)' if your extension is implemented in managed code). You may want to enable 'Managed + Native' debugging to prevent msvsmon from timing out.
  8. Hit F5 to start debugging

Msvsmon timeout while debugging

If you debug the devenv.exe process with a native debugger and either don't debug msvsmon.exe, or you debug msvsmon.exe with a non-native debugger, and if you sit in break state for more than three minutes msvsmon will timeout and abort. You can work around this problem be either:

  1. In child process debug settings, enable 'Managed + Native' debugging for msvsmon.exe instead of managed-only debugging

-or-

  1. If you are in break state for msvsmon, but you are only attaching to devenv.exe for use by the child process debugger than you can work around this problem by going to Tools->Options->Debugging->General, uncheck 'Break all processes when one process breaks'. This will keep the debugger from breaking into the devenv.exe process when the debugger is stopped for managed debugging msvsmon.exe.

Enabling native debugging if you have a .csproj as your startup project

If you have a .csproj as your startup project it is still sometimes useful to launch Visual Studio with native debugging enabled. There are three ways to do this:

Option #1: Enable both managed and native debugging at the same time

Right click on your startup project and bring up project properties. Then switch to the 'Debug' tab and check the 'Enable native code debugging' checkbox. This setting is probably the best option as long as the performance of Visual Studio is acceptable in this mode. Note that if you find things are running too slow, two things that might help in addition to the other options here:

  • Review your Just My Code settings
  • If your target VS is doing something very intensive (example: loading a large .vcxproj) consider if there are ways to avoid this such as opening the build executable an an exe project instead of the real project.

Option #2: Hand edit your .csproj to enable native-only debugging

  • Right click on the startup project and unload it
  • Right click again and edit it
  • Inside a <PropertyGroup> add:
<!-- Enable native-only debugging -->
<DebugEngines>{3B476D35-A401-11D2-AAD4-00C04F990171}</DebugEngines>
  • Right click on your project and reload it + set it as the startup project

This approach is best as long as you don't need to debug any managed code running in devenv.exe, and you aren't frequently wanting to switch back and forth between managed-only and native-only debugging.

Option #3: Add a dummy .vcxproj to your solution just for debugging

  • Add a new C++ console app to your solution. Call it something like 'NativeDebugDevenv'.
  • Right click on your new project, and go to Build Dependencies->Project Dependencies, and make your new project dependent on your current startup project (ex: vsix.csproj). This will make it so your real project will build as part of F5.
  • Right click on the project again and open project properties. Go to the 'Debugging' tab, and make these changes:
    • Change 'Command' to $(DevEnvDir)devenv.exe
    • Change 'Command arguments' to /rootsuffix Exp
    • Change 'Working directory' to $(DevEnvDir)
  • Make this new project your startup project.

Now you can quickly toggle between managed-only debugging and native-only debugging just by switching your startup project.

Configuring Just My Code

If your are managed debugging, there are two Tools->Options->Debugging->General settings that can have a pretty significant impact on debugging experience:

  • Enable Just My Code
  • Suppress JIT optimizations on module load (Managed only)

For best performance, you want to leave these in the default state -- Just My Code (JMC) checked, suppress JIT optimizations unchecked. This will also break, by default, if your code raises an exceptions to Visual Studio. This isn't always what you want -- sometimes your extension is probably supposed to throw an exception. But it is usually a good default and you can configure the specific exception types that you don't want to stop on, such as maybe 'NotImplementedException' to stop breaking when the exception is 'User Unhandled'.

If your are investigating a failure that is happening in some other part of Visual Studio it can be useful to temporarily change both of these -- uncheck JMC and check suppress JIT optimizations. Now the output window will show you all the exceptions raised, and you can configure the debugger to break on ones that you think might be causing your problem.

Logs

If you haven't already looked at method logs you might want to do so. For some problems, like understanding why your component isn't getting called, logs are better than debugging.

Clone this wiki locally