Programmatically detach debugger

前端 未结 2 501
礼貌的吻别
礼貌的吻别 2021-01-18 02:35

I have a 3rd party library that is doing something internally that causes it to slow down greatly when the debugger is attached, even in release mode.

I have found 1

2条回答
  •  心在旅途
    2021-01-18 03:09

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

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

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

    This will dettach ALL processes from that instance of Visual Studio, so if, for whatever reason, Visual Studio was attached to other processes in addition to yours, those processes would also become detached. Furthermore, you may get unexpected results if you have more than one instance of Visual Studio opened.

    To be careful to only detach the current proccess and only the right 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 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;
        }
    
    }
    

提交回复
热议问题