我正在构建一个内部开发工具来管理我们的开发环境中常用的不同进程。该工具显示受监视进程的列表,指示其运行状态,并允许启动或停止每个进程。
我想添加从我的工具将调试器附加到受监视进程的功能,而不是进入 Debug - > 在Visual Studio中附加到进程并查找进程。
我的目标是使用Debugger.Launch()
之类的内容来显示可用的Visual Studio列表。我无法使用Debugger.Launch()
,因为它会在进行调用的进程上启动调试器。我需要像Debugger.Launch(processId)
这样的东西。
如何实现此功能?
解决方案可能是在每个受监视进程中实现一个命令,以便在从监视工具收到命令时调用Debugger.Launch()
,但我更喜欢不需要修改受监视进程代码的内容。
附带问题:
使用Debugger.Launch()
时,未列出已附加调试程序的Visual Studio实例。 Visual Studio不限于一个附加的调试器,使用调试→附加到进程时,可以在多个进程上附加。
使用Debugger.Launch()
或替代方法时,如何绕过此限制?
答案 0 :(得分:15)
一位同事最终使用DTE解决方案,我在PasteBin上发布了代码。
感兴趣的方法是AttachVisualStudioToProcess
和TryGetVsInstance
public static void AttachVisualStudioToProcess(Process visualStudioProcess, Process applicationProcess)
{
_DTE visualStudioInstance;
if (TryGetVsInstance(visualStudioProcess.Id, out visualStudioInstance))
{
//Find the process you want the Visual Studio instance to attach to...
DTEProcess processToAttachTo = visualStudioInstance.Debugger.LocalProcesses.Cast<DTEProcess>().FirstOrDefault(process => process.ProcessID == applicationProcess.Id);
// Attach to the process.
if (processToAttachTo != null)
{
processToAttachTo.Attach();
ShowWindow((int)visualStudioProcess.MainWindowHandle, 3);
SetForegroundWindow(visualStudioProcess.MainWindowHandle);
}
else
{
throw new InvalidOperationException("Visual Studio process cannot find specified application '" + applicationProcess.Id + "'");
}
}
}
private static bool TryGetVsInstance(int processId, out _DTE instance)
{
IntPtr numFetched = IntPtr.Zero;
IRunningObjectTable runningObjectTable;
IEnumMoniker monikerEnumerator;
IMoniker[] monikers = new IMoniker[1];
GetRunningObjectTable(0, out runningObjectTable);
runningObjectTable.EnumRunning(out monikerEnumerator);
monikerEnumerator.Reset();
while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
{
IBindCtx ctx;
CreateBindCtx(0, out ctx);
string runningObjectName;
monikers[0].GetDisplayName(ctx, null, out runningObjectName);
object runningObjectVal;
runningObjectTable.GetObject(monikers[0], out runningObjectVal);
if (runningObjectVal is _DTE && runningObjectName.StartsWith("!VisualStudio"))
{
int currentProcessId = int.Parse(runningObjectName.Split(':')[1]);
if (currentProcessId == processId)
{
instance = (_DTE)runningObjectVal;
return true;
}
}
}
instance = null;
return false;
}
答案 1 :(得分:12)
WinDbg默认为本机代码进行链调试。如果要启动另一个Visual Studio实例,请在MSDN上查看Launch the Debugger Automatically:
要自动化现有调试器,请使用Marshal.GetActiveObject获取当前的EnvDTE.Debugger,然后将其附加到刚刚创建的进程。
有时,您可能需要调试由另一个进程启动的应用程序的启动代码。示例包括服务和自定义设置操作。在这些情况下,您可以启动调试器并在应用程序启动时自动附加。
设置应用程序以自动启动调试程序
启动注册表编辑器(regedit)。
在注册表编辑器中,打开HKEY_LOCAL_MACHINE文件夹。
导航至HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Windows NT \ currentversion \ image文件执行选项。
在映像文件执行选项文件夹中,找到要调试的应用程序的名称,例如myapp.exe。如果找不到要调试的应用程序:
一个。右键单击图像文件执行选项文件夹,然后在快捷菜单上单击新密钥。
湾右键单击新密钥,然后在快捷菜单上单击重命名。
℃。编辑应用程序名称的密钥名称; myapp.exe,在此示例中。
右键单击 myapp.exe 文件夹,然后在快捷菜单上单击新字符串值。
右键单击新字符串值,然后在快捷菜单上单击重命名。
将名称更改为
debugger
。右键单击新字符串值,然后在快捷菜单上单击修改。 将出现编辑字符串对话框。
在值数据框中,键入 vsjitdebugger.exe 。
点击确定。
在注册表菜单中,点击退出。
- 醇>
包含vsjitdebugger.exe的目录必须位于系统路径中。要将其添加到系统路径,请按照下列步骤操作:
一个。在经典视图中打开控制面板,然后双击系统。
湾点击高级系统设置。
℃。在系统属性中,点击高级标签。
d。在高级标签上,点击环境变量。
即在环境变量对话框的系统变量下,选择路径,然后点击修改按钮。
F。在编辑系统变量对话框中,将目录添加到变量值框中。使用分号将其与列表中的其他条目分开。
克。点击确定以关闭编辑系统变量对话框。
小时。点击确定以关闭环境变量对话框。
我。点击确定关闭系统属性对话框。
现在,使用任何方法启动您的应用程序。 Visual Studio将启动并加载应用程序。
答案 2 :(得分:6)
以下是有关如何以编程方式将调试器附加到多个进程的一些信息: