使用ProcessStartInfo打开C#文件会打开错误的Visual Studio实例

时间:2016-12-29 15:00:42

标签: c# shellexecute processstartinfo

我有一个C#代码分析应用程序,它使用ProcessStartInfo和Process Start打开C#。它几乎可以工作。

我想使用VS的两个实例来执行分析:一个用于调试Analysis应用程序,另一个用于具有在其相应解决方案中指定的File。

目前,C#文件始终在Analysis App调试会话中打开,而不是分析应用程序解决方案。如何在Process.Start(ProcessStartInfo)上指定要使用的实例?

private void OpenFileExecute(string file)
{
    ProcessStartInfo psi = new ProcessStartInfo(file);   
    psi.UseShellExecute = true;
    Process.Start(psi);
}

1 个答案:

答案 0 :(得分:1)

使用标准的open方法,您将无法控制将使用哪个正在运行的实例。它使用DDE,undetermined实例将处理DDE请求。

使用Activator.GetObject时也是如此。

幸运的是,在ole32.dll中,我们可以调用GetRunningObjectTable并从那里枚举所有实例,以查找所有已注册的OLE服务器,包括所有Visual Studio进程。

一旦我们找到一个你可以获得一个实例到它的OLE自动化接口,EnvDTE并使用它来深入检查这是否是正确的实例进行交互,如果是,执行任何命令我们&# 39;重新感兴趣,例如加载文件。

private void OpenFileExecute(string file)
{
    IRunningObjectTable ir;
    // get all OLE/COM Automation servers
    GetRunningObjectTable(0, out ir);
    if (ir != null)
    {
        IEnumMoniker moniker;
        // Get an enumerator to iterate over them
        ir.EnumRunning(out moniker);
        if (moniker != null)
        {
            moniker.Reset();
            IMoniker[] results = new IMoniker[1];
            // iterate
            while (moniker.Next(1, results, IntPtr.Zero) == 0)
            {
                // we need a Bind Context
                IBindCtx bindCtx;
                CreateBindCtx(0, out bindCtx);
                // what is the name of the OLE/COM Server
                string objName;
                results[0].GetDisplayName(bindCtx, null, out objName);
                // what have we got ...
                Trace.WriteLine(objName);
                // I test with VS2010 instances, 
                // but feel free to get rid of the .10
                if (objName.StartsWith("!VisualStudio.DTE.10"))
                {
                    object dteObj; //
                    ir.GetObject(results[0], out dteObj);
                    // now we have an OLE automation interface 
                    // to the correct instance
                    DTE dteTry = (DTE)dteObj;
                    // determine if this is indeed
                    // the one you need
                    // my naive approach is to check if
                    // there is a Document loaded
                    if (dteTry.Documents.Count == 1)
                    {
                        dteTry.ExecuteCommand(
                            "File.OpenFile",
                            String.Format("\"{0}\"", file));
                    }
                }
                bindCtx.ReleaseBoundObjects();
            }
        }
    }
}

[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);

背景阅读:How to use Marshal.getActiveObject() to get 2 instance of of a running process that has two processes open