2015-11-17 2 views
1

J'essaie de joindre un processus à VS en utilisant ce code:Comment attacher automatiquement un processus à une instance spécifique de VS?

DTE dte = (DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.11.0"); 
EnvDTE.Processes pro = dte.Debugger.LocalProcesses; 

foreach (EnvDTE.Process p in pro) 
{ 
    if (p.ProcessID == num) 
    { 
     p.Attach(); 
     return; 
    } 
    else 
    { 
     continue; 
    } 
} 

Mon problème est que je ne peux pas contrôler à quelle instance de VS, il obtient attacher. est généralement la première fenêtre VS que j'ai ouverte. Comment puis-je obtenir une liste de toutes les instances VS ouvertes? Merci beaucoup d'avance!

Répondre

2

La seule façon de distinguer les instances VS en cours consiste à les sélectionner en fonction de la solution qu'elles ont chargée. Comme la chance l'aurait (n'était pas la chance), VS expose également l'objet EnvDTE.Solution dans la table d'objets en cours d'exécution. Vous pouvez utiliser Roman's RotView-Win32.exe utility pour voir à quoi cela ressemble.

Quelques exemples de code qui itère le ROT et retourne toutes les solutions actives:

using System; 
using System.Collections.Generic; 
using System.Runtime.InteropServices; 
using System.Runtime.InteropServices.ComTypes; 

public class VSSolution { 
    public string Name { get; set; } 
    public EnvDTE.Solution Solution { get; set; } 
} 

public static class VSAutomation { 
    public static List<VSSolution> GetRunningSolutions() { 
     var instances = new List<VSSolution>(); 
     // Get running object table reference iterator 
     IRunningObjectTable Rot; 
     int hr = GetRunningObjectTable(0, out Rot); 
     if (hr < 0) throw new COMException("No rot?", hr); 
     IEnumMoniker monikerEnumerator; 
     Rot.EnumRunning(out monikerEnumerator); 

     // And iterate 
     IntPtr pNumFetched = new IntPtr(); 
     IMoniker[] monikers = new IMoniker[1]; 
     while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0) { 
      IBindCtx bindCtx; 
      int hr2 = CreateBindCtx(0, out bindCtx); 
      if (hr < 0) continue; 
      // Check if display ends with ".sln" 
      string displayName; 
      monikers[0].GetDisplayName(bindCtx, null, out displayName); 
      if (displayName.EndsWith(".sln", StringComparison.CurrentCultureIgnoreCase)) { 
       object obj; 
       Rot.GetObject(monikers[0], out obj); 
       if (obj is EnvDTE.Solution) { 
        instances.Add(new VSSolution { Name = displayName, Solution = (EnvDTE.Solution)obj }); 
       } 
       else Marshal.ReleaseComObject(obj); 
      } 
     } 
     return instances; 
    } 
    [DllImport("ole32.dll")] 
    private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); 
    [DllImport("ole32.dll")] 
    private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); 
} 

Exemple d'utilisation comme testé:

foreach (var sln in GetRunningSolutions()) { 
     if (sln.Name.EndsWith("ConsoleApplication1.sln")) { 
      var dte = sln.Solution.DTE; 
      // etc... 
     } 
    }