如何动态地将调试器附加到特定进程

Jef*_*Cyr 12 debugging visual-studio

我正在构建一个内部开发工具来管理我们的开发环境中常用的不同进程.该工具显示受监视进程的列表,指示其运行状态,并允许启动或停止每个进程.

我想添加从我的工具将调试器附加到受监视进程的功能,而不是在调试 - > 附加到 Visual Studio中的进程并查找进程.

我的目标是让这样的东西Debugger.Launch()显示可用的Visual Studio列表.我无法使用Debugger.Launch(),因为它会在进行调用的进程上启动调试器.我需要类似的东西Debugger.Launch(processId).

我如何实现此功能?

解决方案可能是在每个受监视进程中实现一个命令,以便Debugger.Launch()在从监视工具收到命令时调用,但我更喜欢不需要修改受监视进程代码的东西.

问题:

使用时Debugger.Launch(),未列出已附加调试器的Visual Studio实例.Visual Studio不限于一个附加的调试器,使用DebugAttach to process时可以在多个进程上附加.

使用Debugger.Launch()或替代时如何绕过此限制?

Jef*_*Cyr 15

一位同事最终得到了使用DTE的解决方案,我在PasteBin上发布了代码.

感兴趣的方法是AttachVisualStudioToProcessTryGetVsInstance

源代码

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;
}
Run Code Online (Sandbox Code Playgroud)


She*_* 蒋晟 12

WinDbg默认为本机代码进行链调试.如果要启动另一个Visual Studio实例,请选中在MSDN上自动启动调试器:

要自动化现有的调试器,请使用Marshal.GetActiveObject获取当前的EnvDTE.Debugger,然后将其附加到刚刚创建的进程.

有时,您可能需要调试由另一个进程启动的应用程序的启动代码.示例包括服务和自定义设置操作.在这些情况下,您可以启动调试器并在应用程序启动时自动附加.

设置应用程序以自动启动调试器

  1. 启动注册表编辑器(regedit).

  2. 在注册表编辑器中,打开HKEY_LOCAL_MACHINE文件夹.

  3. 导航到HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\currentversion\image文件执行选项.

  4. 在" 映像文件执行选项"文件夹中,找到要调试的应用程序的名称,例如myapp.exe.如果找不到要调试的应用程序:

    一个.右键单击" 图像文件执行选项"文件夹,然后在快捷菜单上单击" 新建密钥".

    湾 右键单击新密钥,然后在快捷菜单上单击" 重命名".

    C.编辑应用程序名称的密钥名称; myapp.exe,在此示例中.

  5. 右键单击myapp.exe文件夹,然后在快捷菜单上单击" 新建字符串值".

  6. 右键单击新字符串值,然后在快捷菜单上单击" 重命名".

  7. 将名称更改为debugger.

  8. 右键单击新的字符串值,然后在快捷菜单上单击" 修改".将出现" 编辑字符串"对话框.

  9. 在" 数值数据"框中,键入vsjitdebugger.exe.

  10. 单击确定.

  11. 注册表菜单中,单击退出.

  12. 包含vsjitdebugger.exe的目录必须位于系统路径中.要将其添加到系统路径,请按照下列步骤操作:

    一个.在"经典"视图中打开" 控制面板",然后双击" 系统".

    湾 单击高级系统设置.

    C.在" 系统属性"中单击" 高级"选项卡.

    d.在" 高级"选项卡上,单击" 环境变量".

    即 在" 环境变量"对话框的" 系统变量"下,选择"路径",然后单击" 编辑"按钮.

    F.在" 编辑系统变量"对话框中,将目录添加到" 变量值"框中.使用分号将其与列表中的其他条目分开.

    G.单击" 确定"关闭" 编辑系统变量"对话框.

    H.单击" 确定"关闭" 环境变量"对话框.

    一世.单击" 确定"关闭" 系统属性"对话框.

现在,使用任何方法启动您的应用程序.Visual Studio将启动并加载应用程序.


Vil*_*las 6

以下是有关如何以编程方式将调试器附加到多个进程的一些信息: