代码之家  ›  专栏  ›  技术社区  ›  Jeff Cyr

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

  •  14
  • Jeff Cyr  · 技术社区  · 16 年前

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

    调试 -> 附加到进程 在Visual Studio中查找进程。

    我的目标是拥有这样的东西 Debugger.Launch() 这将显示可用Visual Studio的列表。我不能用 ,因为它在发出调用的进程上启动调试器。我需要这样的东西 Debugger.Launch(processId) .

    如何实现此功能?

    调试器。启动() 当从监控工具收到命令时,但我更喜欢不需要修改被监控进程代码的东西。

    附带问题:

    使用时 调试器。启动() 调试 附加到进程 .

    调试器。启动() 还是另一种选择?

    3 回复  |  直到 8 年前
        1
  •  14
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    AttachVisualStudioToProcess TryGetVsInstance

    Source Code

    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;
    }
    
        2
  •  12
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

    默认情况下,Winchester会对本机代码进行链式调试。如果要启动Visual Studio的另一个实例,请选中 Launch the Debugger Automatically

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

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

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

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

    3. 图像文件执行选项

      a.右键单击 图像文件执行选项 文件夹,然后在快捷菜单上单击 新钥匙 .

      重命名 .

    4. 右键单击 myapp.exe 文件夹,然后在快捷菜单上单击 .

    5. 重命名 .

    6. 将名称更改为 debugger .

    7. . 这

    8. vsjitdebugger.exe .

    9. 好的 .

    10. 退出 .

    11. a.打开 控制面板 在“经典”视图中,然后双击 .

      b.点击 高级系统设置 .

      系统属性 ,单击 选项卡。

      d.在 高级 .

      e.在 环境变量 对话框,在 系统变量 ,选择“路径”,然后单击 编辑 按钮。

      编辑系统变量 对话框中,将目录添加到 可变值

      g.点击 好的 编辑系统变量 对话框。

      好的 关闭 环境变量 对话框。

      i.点击 好的 关闭 系统属性 对话框。

        3
  •  6
  •   Peter Mortensen Pieter Jan Bonestroo    8 年前

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