Programmatically separate the debugger

I have a third-party library that does something internally, which is why it slows down significantly when the debugger is connected, even in release mode.

I found 100 explanations of how to separate the debugger manually in Visual Studio by going to Debug -> Detach process . However, I have not yet seen anyone present an example in which a program could disable any attached debuggers.

Basically there is a tear-off version of Debugger.Launch () ?

+6
source share
2 answers

According to Why can't you disconnect when interop-debugging? CLR does not support shutdown processes. However, Visual Studio can do this. But the article is 5 years old, so are you using DebugActiveProcessStop from Windows Api via pinvoke?

 BOOL WINAPI DebugActiveProcessStop( __in DWORD dwProcessId ); [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DebugActiveProcessStop([In] int Pid ); 

Edit: just tried this: in the current process, it gives access denial, even if it is promoted.

There is also something in the CLR Managed Debugger (mdbg) Sample 2006 or Version 2011

Finally, this article explains what you need to do to use ICorDebug :: Detach , and I believe that visual studio does this.

+6
source

Assuming you know which instance / version of Visual Studio is connected to your process, you can detach it as follows:

 object dt = Marshal.GetActiveObject("VisualStudio.DTE.12.0") DTE dte = (DTE)dt; dte.Debugger.DetachAll(); 

"12" for version 2013 of Visual Studio. For a different version, change accordingly. This requires a link to EnvDTE, which is usually located in the C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ PublicAssemblies \ EnvDTE.dll folder

This will disconnect ALL processes from this instance of Visual Studio, so if for any reason Visual Studio will be attached to other processes in addition to yours, these processes will also be disabled. In addition, you may get unexpected results if you have multiple instances of Visual Studio open.

To be careful only to separate the current process and only the correct instance of Visual Studio, use the following code:

 using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using EnvDTE; public class Test { public static void DetachCurrentProcesses() { System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcessesByName("devenv"); DTE dte = null; foreach (System.Diagnostics.Process devenv in procs) { do { System.Threading.Thread.Sleep(2000); dte = AutomateVS.GetDTE(devenv.Id); } while (dte == null); IEnumerable<Process> processes = dte.Debugger.DebuggedProcesses.OfType<Process>(); if (!processes.Any) continue; int currentID = System.Diagnostics.Process.GetCurrentProcess().Id; processes.Where(p => p.ProcessID == currentID).ToList.ForEach(p => p.Detach(false)); Marshal.ReleaseComObject(dte); } } } /// <summary> /// Source to this class: http://blogs.msdn.com/b/kirillosenkov/archive/2011/08/10/how-to-get-dte-from-visual-studio-process-id.aspx /// </summary> /// <remarks></remarks> public class AutomateVS { [DllImport("ole32.dll")] private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); public static DTE GetDTE(int processId) { string progId = "!VisualStudio.DTE.10.0:" + processId.ToString(); object runningObject = null; IBindCtx bindCtx = null; IRunningObjectTable rot = null; IEnumMoniker enumMonikers = null; try { Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0, ppbc: out bindCtx)); bindCtx.GetRunningObjectTable(out rot); rot.EnumRunning(out enumMonikers); IMoniker[] moniker = new IMoniker[1]; IntPtr numberFetched = IntPtr.Zero; while (enumMonikers.Next(1, moniker, numberFetched) == 0) { IMoniker runningObjectMoniker = moniker[0]; string name = null; try { if (runningObjectMoniker != null) { runningObjectMoniker.GetDisplayName(bindCtx, null, out name); } } catch (UnauthorizedAccessException) { // Do nothing, there is something in the ROT that we do not have access to. } if (!string.IsNullOrEmpty(name) && string.Equals(name, progId, StringComparison.Ordinal)) { Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker, out runningObject)); break; } } } finally { if (enumMonikers != null) { Marshal.ReleaseComObject(enumMonikers); } if (rot != null) { Marshal.ReleaseComObject(rot); } if (bindCtx != null) { Marshal.ReleaseComObject(bindCtx); } } return (DTE)runningObject; } } 
+2
source

Source: https://habr.com/ru/post/897657/


All Articles