2016-12-29 12 views
0

У меня есть приложение для анализа кода C#, которое открывает C# с помощью ProcessStartInfo и Process Start. Это почти работает.Открытие файла C# с ProcessStartInfo открывается неправильно Visual studio Instance

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

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

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

Что именно входит в переменный файл? – rene

+0

«Something.CS» => Существующий файл C#. .CS ассоциируется с Visual Studio на моей системе –

ответ

1

С помощью стандартного открытого метода вы не сможете контролировать, какой экземпляр запуска будет использоваться. Под капотом он использует DDE, и это undetermined, экземпляр которого будет обрабатывать 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); 

чтение фона: How to use Marshal.getActiveObject() to get 2 instance of of a running process that has two processes open

+0

Ну, это получает только имя EXE ассоциации. Какой экземпляр - вопрос? А затем как связать открытую операцию с этим экземпляром? Таким образом, это не будет в моей оценке решить проблему, из которой экземпляр должен открыть ее. –

+0

Я не хочу, чтобы каждый экземпляр Visual Studio каждый раз вызывал, –

+0

Тогда ваш вопрос немного неясен. Насколько я понял, вы не хотите, чтобы этот файл отображался в текущем экземпляре VS. Это оставляет вас с открытием его в новом. – rene