运行Visual Studio 2010实例并以编程方式附加到进程?

Mic*_*tum 3 .net debugging remoting visual-studio-2010

我有一个WinForms应用程序(.net 3.5),它显示进程列表.

我希望能够附加其中一个进程.我有多个运行的Visual Studio 2010实例,我想创建一个List/Dropdown,我在其中选择其中一个实例,然后将调试器附加到它.

获取VS2010实例应该不会太难,但我不知道如何调用"附加到进程"命令.我想避免使用SendKeys-Type解决方案,所以我只是想知道是否有某种方法可以做到这一点?

编辑:澄清:我想使用特定的运行VS2010来调试外部应用程序.

Tim*_*oyd 6

一种方法是使用EnvDTE,这是Visual Studio的COM自动化接口:

http://msdn.microsoft.com/en-us/library/envdte(VS.100).aspx

您可以通过在运行对象表(ROT)中捕获来获取运行Visual Studio实例的自动化接口.一旦有了接口实例,就可以自动选择Visual Studio实例来附加到您想要的进程.

以下是如何执行此操作的基本示例.您需要向EnvDTE添加对项目的引用.该程序集位于我的机器上的以下位置:

C:\ Program Files(x86)\ Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\EnvDTE.dll

更新

更新以提供按进程ID获取Visual Studio实例自动化接口的示例.

using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using EnvDTE;

namespace VS2010EnvDte
{
internal class Program
{
    [DllImport("ole32.dll")]
    public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

    [DllImport("ole32.dll")]
    public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);

    private static void Main()
    {
        //ProcessId of the VS instance - hard-coded here.
        int visualStudioProcessId = 5520;

        _DTE visualStudioInstance;

        if (TryGetVSInstance(visualStudioProcessId, out visualStudioInstance))
        {
            Process processToAttachTo = null;

            //Find the process you want the VS instance to attach to...
            foreach (Process process in visualStudioInstance.Debugger.LocalProcesses)
            {
                if (process.Name == @"C:\Users\chibacity\AppData\Local\Google\Chrome\Application\chrome.exe")
                {
                    processToAttachTo = process;
                    break;
                }
            }

            //Attach to the process.
            if (processToAttachTo != null)
            {
                processToAttachTo.Attach();
            }
        }
    }

    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)