本文介绍了如何将调试器动态地附加到特定进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我想添加附加调试器的功能一个来自我的工具的监视进程,而不是进入可视化工作室的Debug-> Attach to process,并找到该过程。



我的目标是像Debugger这样的东西。 Launch()将显示可用的视觉工作室的列表。我不能使用Debugger.Launch(),因为它可以调用进程调用调试器。我需要像Debugger.Launch(processId)这样的东西。



有没有人知道如何实现这个功能?



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

侧面问题:
当使用Debugger.Launch()时,没有列出已经安装了调试器的Visual Studio实例。 Visual Studio不限于一个连接的调试器,您可以在使用调试 - >附加到进程时附加多个进程。



任何人都知道如何绕过此限制使用Debugger.Launch()或替代方案?

解决方案

一个同事最终使用DTE解决方案,我发布了代码PasteBin。



感兴趣的方法是 AttachVisualStudioToProcess TryGetVsInstance



  public static void AttachVisualStudioToProcess(Process visualStudioProcess,Process applicationProcess)
{
_DTE visualStudioInstance;

if(TryGetVsInstance(visualStudioProcess.Id,out visualStudioInstance))
{
//查找您希望VS实例附加到的进程...
DTEProcess processToAttachTo = visualStudioInstance.Debugger.LocalProcesses.Cast&DTEProcess>()。FirstOrDefault(process => process.ProcessID == applicationProcess.Id);

//附加到进程。
if(processToAttachTo!= null)
{
processToAttachTo.Attach();

ShowWindow((int)visualStudioProcess.MainWindowHandle,3);
SetForegroundWindow(visualStudioProcess.MainWindowHandle);
}
else
{
抛出新的InvalidOperationException(Visual Studio进程找不到指定的应用程序+ 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);

对象runningObjectVal;
runningObjectTable.GetObject(monikers [0],out runningObjectVal);

if(runningObjectVal为_DTE&& runObjectName.StartsWith(!VisualStudio))
{
int currentProcessId = int.Parse(runningObjectName.Split(' )[1]);

if(currentProcessId == processId)
{
instance =(_DTE)runningObjectVal;
返回true;
}
}
}

instance = null;
返回false;
}


I am building an internal dev tool to manage different processes commonly used in our development environment. The tool show the list the monitored processes, indicate their running state and allow to start or stop each process.

I'd like to add the functionality of attaching a debugger to a monitored process from my tool instead of going in 'Debug->Attach to process' in visual studio and finding the process.

My goal is to have something like Debugger.Launch() that would show a list of the available visual studio. I can't use Debugger.Launch() because it lauches the debugger on the process that make the call. I would need something like Debugger.Launch(processId).

Does anyone know how to acheive this functionality?

A solution could be to implement a command in each monitored process to call Debugger.Launch() when the command is received from the monitoring tool, but I would prefer something that does not require to modify the code of the monitored processes.

Side question:When using Debugger.Launch(), instances of Visual Studio that already have a debugger attached are not listed. Visual Studio is not limited to one attached debugger, you can attach on multiple process when using 'Debug -> Attach to process'.

Anyone know how to bypass this limitation when using Debugger.Launch() or an alternative?

解决方案

A coworker ended up with a solution using DTE, I posted the code on PasteBin.

The methods of interest are AttachVisualStudioToProcess and 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 VS 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;
}

这篇关于如何将调试器动态地附加到特定进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 11:10