Getting instances of Visual Studio 2010 and joining a process programmatically?

I have a WinForms application (.net 3.5) that displays a list of processes.

I would like to be able to connect to one of these processes. I have several instances of Visual Studio 2010, and I would like to create a list / drop-down list where I select one of these instances and then attach a debugger to it.

Getting instances of VS2010 should not be too complicated, but I don’t know how to invoke the attach to process command. I want to avoid SendKeys-Type solutions, so I'm just wondering if there is a way to do this?

edit: To clarify: I want to use a specific VS2010 launch to debug an external application.

+3
source share
2 answers

One approach is to use EnvDTE, which is the COM automation interface for Visual Studio:

http://msdn.microsoft.com/en-us/library/envdte(VS.100).aspx

You can get automation interfaces for running Visual Studio instances by catching in the Running Objects (ROT) table. Once you have an instance of the interface, you can then automate the selected instance of Visual Studio to join the desired process.

Below is a basic example of how to do this. You will need to add a link to your project in EnvDTE. This assembly is in the following location on my machine:

C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ PublicAssemblies \ EnvDTE.dll

Update

Updated to give an example of getting the Visual Studio instance automation interface by process ID.

using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using EnvDTE; namespace VS2010EnvDte { internal class Program { [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); private static void Main() { //ProcessId of the VS instance - hard-coded here. int visualStudioProcessId = 5520; _DTE visualStudioInstance; if (TryGetVSInstance(visualStudioProcessId, out visualStudioInstance)) { Process processToAttachTo = null; //Find the process you want the VS instance to attach to... foreach (Process process in visualStudioInstance.Debugger.LocalProcesses) { if (process.Name == @"C:\Users\chibacity\AppData\Local\Google\Chrome\Application\chrome.exe") { processToAttachTo = process; break; } } //Attach to the process. if (processToAttachTo != null) { processToAttachTo.Attach(); } } } private static bool TryGetVSInstance(int processId, out _DTE instance) { IntPtr numFetched = IntPtr.Zero; IRunningObjectTable runningObjectTable; IEnumMoniker monikerEnumerator; IMoniker[] monikers = new IMoniker[1]; GetRunningObjectTable(0, out runningObjectTable); runningObjectTable.EnumRunning(out monikerEnumerator); monikerEnumerator.Reset(); while (monikerEnumerator.Next(1, monikers, numFetched) == 0) { IBindCtx ctx; CreateBindCtx(0, out ctx); string runningObjectName; monikers[0].GetDisplayName(ctx, null, out runningObjectName); object runningObjectVal; runningObjectTable.GetObject(monikers[0], out runningObjectVal); if (runningObjectVal is _DTE && runningObjectName.StartsWith("!VisualStudio")) { int currentProcessId = int.Parse(runningObjectName.Split(':')[1]); if (currentProcessId == processId) { instance = (_DTE)runningObjectVal; return true; } } } instance = null; return false; } } } 
+6
source

Tim Lloyd's answer works great. Here's a small modification that makes a console program that attaches a debugger to a program specified as a case-insensitive regular expression on the command line. This is quite simple, so only one instance of Visual Studio is assumed, and only one instance of the process that you want to connect to.

 using System; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Text.RegularExpressions; using EnvDTE; namespace VstAttach { internal static class Program { [DllImport("ole32.dll")] static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot); [DllImport("ole32.dll")] static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); private static void Main(string[] args) { if (args.Length == 0) throw new Exception("Syntax: VstAttach ProcessName (case insensitive regex)"); var vst = System.Diagnostics.Process.GetProcessesByName("devenv").FirstOrDefault(); if (vst == null) throw new Exception("Visual Studio not found."); var visualStudioProcessId = vst.Id; _DTE visualStudioInstance; if (TryGetVsInstance(visualStudioProcessId, out visualStudioInstance)) { var processToAttachTo = visualStudioInstance.Debugger.LocalProcesses .Cast<Process>() .FirstOrDefault(process => Regex.IsMatch(process.Name, args[0], RegexOptions.IgnoreCase)); if (processToAttachTo != null) { processToAttachTo.Attach(); } } } private static bool TryGetVsInstance(int processId, out _DTE instance) { var numFetched = IntPtr.Zero; IRunningObjectTable runningObjectTable; IEnumMoniker monikerEnumerator; var monikers = new IMoniker[1]; GetRunningObjectTable(0, out runningObjectTable); runningObjectTable.EnumRunning(out monikerEnumerator); monikerEnumerator.Reset(); while (monikerEnumerator.Next(1, monikers, numFetched) == 0) { IBindCtx ctx; CreateBindCtx(0, out ctx); string runningObjectName; monikers[0].GetDisplayName(ctx, null, out runningObjectName); object runningObjectVal; runningObjectTable.GetObject(monikers[0], out runningObjectVal); if (runningObjectVal is _DTE && runningObjectName.StartsWith("!VisualStudio")) { int currentProcessId = int.Parse(runningObjectName.Split(':')[1]); if (currentProcessId == processId) { instance = (_DTE)runningObjectVal; return true; } } } instance = null; return false; } } } 
+1
source

Source: https://habr.com/ru/post/918747/


All Articles