Created
December 16, 2019 15:27
-
-
Save nem0/7e3147b0d38bcf52844dd5eb835091d4 to your computer and use it in GitHub Desktop.
detach and attach vs debugger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading; | |
using System.Runtime.InteropServices; | |
using System.Runtime.InteropServices.ComTypes; | |
using System.Text.RegularExpressions; | |
using System.Diagnostics; | |
using EnvDTE; | |
namespace ConsoleApplication1 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
bool attach = System.IO.File.Exists("envdte_detached.txt"); | |
foreach (var p in System.Diagnostics.Process.GetProcesses()) | |
{ | |
if(p.ProcessName.Contains("devenv")) | |
{ | |
DTE d = GetDTE(p.Id, 1000); | |
if (attach) { | |
int to_attach = int.Parse(System.IO.File.ReadAllText("envdte_detached.txt")); | |
System.IO.File.Delete("envdte_detached.txt"); | |
foreach (var lp in d.Debugger.LocalProcesses) { | |
var lpp = lp as EnvDTE.Process; | |
int pid = lpp.ProcessID; | |
if (to_attach == pid) { | |
lpp.Attach(); | |
return; | |
} | |
} | |
} | |
else | |
{ | |
if (d.Debugger.DebuggedProcesses != null) { | |
foreach(var dp in d.Debugger.DebuggedProcesses) { | |
var dpp = dp as EnvDTE.Process; | |
dpp.Detach(); | |
System.IO.File.WriteAllText("envdte_detached.txt", dpp.ProcessID.ToString()); | |
return; | |
} | |
} | |
} | |
} | |
} | |
} | |
private static EnvDTE.DTE GetDTE(int processId, int timeout) | |
{ | |
EnvDTE.DTE res = null; | |
DateTime startTime = DateTime.Now; | |
while (res == null && DateTime.Now.Subtract(startTime).Seconds < timeout) | |
{ | |
System.Threading.Thread.Sleep(1000); | |
res = GetDTE(processId); | |
} | |
return res; | |
} | |
[DllImport("ole32.dll")] | |
private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); | |
private static EnvDTE.DTE GetDTE(int processId) | |
{ | |
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. | |
} | |
Regex monikerRegex = new Regex(@"!VisualStudio.DTE\.\d+\.\d+\:" + processId, RegexOptions.IgnoreCase); | |
if (!string.IsNullOrEmpty(name) && monikerRegex.IsMatch(name)) | |
{ | |
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 runningObject as EnvDTE.DTE; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment