【问题标题】:Opening a C# File with ProcessStartInfo opens wrong Visual studio Instance使用 ProcessStartInfo 打开 C# 文件会打开错误的 Visual Studio 实例
【发布时间】:2016-12-29 15:00:42
【问题描述】:

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

我想使用两个 VS 实例来执行分析:一个用于调试分析应用程序,另一个用于在其适当的解决方案中指定文件。

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

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

【问题讨论】:

  • 文件变量中究竟包含了什么?
  • "Something.CS"=> 一个现有的 C# 文件。 .CS 与我系统上的 Visual Studio 相关联

标签: c# shellexecute processstartinfo


【解决方案1】:

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

使用Activator.GetObject 时也是如此。

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

一旦我们找到了一个实例,您就可以获得其 OLE 自动化接口 EnvDTE 的实例,并使用它来深入检查这是否是与之交互的正确实例,如果是,则执行我们感兴趣的任何命令例如加载一个文件。

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

【讨论】:

  • 好吧,这只是获取协会的 EXE 名称。哪个实例是问题?然后如何将打开操作与该实例相关联?所以我估计这不会解决在哪个实例中打开它的问题。
  • 我不希望每次调用时都有一个新的 Visual Studio 实例,
  • 那你的问题有点不清楚。据我了解,您不希望该文件显示在当前的 VS 实例中。那种让你在一个新的打开它。
  • 是什么让 VS 实例与众不同,那么应该选择哪个?如果您有 2 个实例正在运行,哪个应该获取您提供的文件?
  • 我有两个当前实例 1) 分析应用程序正在运行调试和构建。 2)正在分析的带有.sln的实例(125 .csproj)我希望点击从一个从2打开实例中的csfile。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-29
  • 2010-10-18
  • 1970-01-01
  • 2010-10-27
  • 2018-10-24
  • 1970-01-01
  • 2011-11-19
相关资源
最近更新 更多