C# 以编程方式分离调试器
我有一个第三方库,它在内部执行一些操作,导致在连接调试器时,即使在发布模式下,它也会大大减慢速度 我已经找到了关于如何在VisualStudio中通过转到C# 以编程方式分离调试器,c#,.net,debugging,C#,.net,Debugging,我有一个第三方库,它在内部执行一些操作,导致在连接调试器时,即使在发布模式下,它也会大大减慢速度 我已经找到了关于如何在VisualStudio中通过转到Debug->detach process手动分离调试器的100种解释。然而,我还没有看到有人提供一个例子,在这个例子中,一个程序可以将任何附加的调试器分离到它自己 基本上有分离版本吗?根据,CLR不支持分离进程。但是VisualStudio可以做到这一点。但是这篇文章已经5年了,所以你可以通过pinvoke使用Windows Api吗 BOO
Debug->detach process
手动分离调试器的100种解释。然而,我还没有看到有人提供一个例子,在这个例子中,一个程序可以将任何附加的调试器分离到它自己
基本上有分离版本吗?根据,CLR不支持分离进程。但是VisualStudio可以做到这一点。但是这篇文章已经5年了,所以你可以通过pinvoke使用Windows Api吗
BOOL WINAPI DebugActiveProcessStop(
__in DWORD dwProcessId
);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DebugActiveProcessStop([In] int Pid );
编辑:刚刚尝试了以下操作:在当前进程上,即使提升了权限,也会拒绝访问
手术室里还有什么东西吗
最后是本文,我想visualstudio就是这么做的 假设您知道哪个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\PublicAssemblys\EnvDTE.dll
这将从VisualStudio实例中分离所有进程,因此,无论出于何种原因,如果VisualStudio附加到除您之外的其他进程,这些进程也将分离。此外,如果打开了多个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<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;
}
}
使用系统;
使用System.Runtime.InteropServices;
使用System.Runtime.InteropServices.ComTypes;
使用EnvDTE;
公开课考试
{
公共静态进程()
{
System.Diagnostics.Process[]procs=System.Diagnostics.Process.getProcessByName(“devenv”);
DTE DTE=null;
foreach(过程中的系统诊断过程开发){
做{
系统线程线程睡眠(2000);
dte=AutomateVS.GetDTE(devenv.Id);
}while(dte==null);
IEnumerable processs=dte.Debugger.DebuggedProcesses.OfType();
如果(!processs.Any)
持续
int currentID=System.Diagnostics.Process.GetCurrentProcess().Id;
processs.Where(p=>p.ProcessID==currentID).ToList.ForEach(p=>p.Detach(false));
元帅发布对象(dte);
}
}
}
///
///该类的来源:http://blogs.msdn.com/b/kirillosenkov/archive/2011/08/10/how-to-get-dte-from-visual-studio-process-id.aspx
///
///
公共类自动机
{
[DllImport(“ole32.dll”)]
私有静态外部int CreateBindCtx(uint保留,out IBindCtx ppbc);
公共静态DTE GetDTE(int processId)
{
字符串progId=“!VisualStudio.DTE.10.0:+processId.ToString();
对象runningObject=null;
IBindCtx bindCtx=null;
IRunningObjectTable rot=null;
IEnumMoniker EnumMoniker=null;
尝试
{
Marshal.throweexceptionforhr(CreateBindCtx(保留:0,ppbc:out bindCtx));
bindCtx.GetRunningObjectTable(out rot);
rot.EnumRunning(耗尽EnumMonikes);
IMoniker[]名字=新IMoniker[1];
IntPtr numberFetched=IntPtr.Zero;
while(EnumMonikes.Next(1,名字对象,numberFetched)==0)
{
IMoniker runningObjectMoniker=名字对象[0];
字符串名称=null;
尝试
{
if(runningObjectMoniker!=null)
{
GetDisplayName(bindCtx,null,out name);
}
}
捕获(未经授权的访问例外)
{
//什么都不做,在腐烂中有我们无法接触到的东西。
}
if(!string.IsNullOrEmpty(name)&&string.Equals(name、progId、StringComparison.Ordinal))
{
Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker,out runningObject));
打破
}
}
}
最后
{
if(枚举名字对象!=null)
{
Marshal.ReleaseComObject(枚举名字对象);
}
如果(rot!=null)
{
元帅释放对象(rot);
}
如果(bindCtx!=null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
返回(DTE)运行对象;
}
}
正如旁注,我认为“为什么不能在互操作调试中分离”一文特别关注互操作调试,即托管代码和本机代码都在工作。看起来纯粹的托管调试总是支持分离(通过saidICoreDebug::detach
)。这是我从未尝试过的。不过我现在会的。