以编程方式分离调试器

我有一个第三方库在内部执行某些操作会导致它在连接调试器时大大减慢,即使在发布模式下也是如此。

我已经找到了100个关于如何通过Debug -> Detach process在Visual Studio中手动分离调试器的解释。 但是,我还没有看到任何人提供一个示例,其中程序可以将任何附加的调试器分离给自己。

基本上是Debugger.Launch()的分离版本?

根据你为什么不能在interop-debugging中分离? ,CLR不支持分离进程。 但Visual Studio可以做到这一点。 但这篇文章已有 5年历史了, 可以通过pinvoke使用Windows Api中的DebugActiveProcessStop吗?

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

编辑:试过这个:在当前进程中,即使提升,它也会拒绝访问。

CLR Managed Debugger(mdbg)Sample 2006或2011版本中也有任何内容

最后,本文解释了使用ICorDebug :: Detach需要做什么 ,我想visual studio确实可以做到这一点。

假设您知道Visual Studio的哪个实例/版本附加到您的进程,您可以按如下方式分离它:

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

“12”适用于Visual Studio的2013版。 对于其他版本,请相应更改。 这需要引用EnvDTE,它通常位于C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ PublicAssemblies \ EnvDTE.dll

这将从Visual Studio的实例中删除所有进程,因此,无论出于何种原因,除了您的Visual Studio之外,Visual Studio还附加到其他进程,这些进程也将分离。 此外,如果您打开了多个Visual Studio实例,则可能会出现意外结果。

要小心只分离当前进程和仅Visual Studio的正确实例,请使用以下代码:

 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 processes = dte.Debugger.DebuggedProcesses.OfType(); 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); } } } ///  /// Source to this class: http://blogs.msdn.com/b/kirillosenkov/archive/2011/08/10/how-to-get-dte-from-visual-studio-process-id.aspx ///  ///  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; } }