Открытие файла C# с ProcessStartInfo открывает неправильный экземпляр Visual Studio

У меня есть приложение анализа кода C#, которое открывает C# с помощью ProcessStartInfo И процесс запуска. Это почти работает.

Я хочу использовать два экземпляра VS для выполнения анализа: один для отладки приложения анализа, а другой - для файла, указанного в соответствующем решении.

В настоящее время файл C# всегда открывается в сеансе отладки приложения для анализа, а не в решении для анализируемого приложения. Как я могу указать, какой экземпляр использовать при Process.Start(ProcessStartInfo)?

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

1 ответ

При использовании стандартного метода open вы не сможете контролировать, какой запущенный экземпляр будет использоваться. Под капотом он использует DDE и не определен, какой экземпляр будет обрабатывать запросы DDE.

То же самое касается, когда вы используете Activator.GetObject,

К счастью, в ole32.dll мы можем вызвать GetRunningObjectTable и оттуда перечислить все экземпляры, чтобы найти все зарегистрированные OLE-серверы для каждого экземпляра, включая все процессы Visual Studio.

Найдя его, вы можете получить экземпляр в его интерфейсе OLE Automation, 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);

Фоновое чтение: Как использовать Marshal.getActiveObject(), чтобы получить 2 экземпляра запущенного процесса, в котором открыто два процесса

Другие вопросы по тегам