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 at automation interfaces for running instances of Visual Studio by fishing around in the Running Objects Table (ROT). Once you have an instance of the interface you can then automate a selected instance of Visual Studio to attach to a process you desire.
Below is a basic example of how to do this. You will need to add a reference to your project to EnvDTE. This assembly is at the following location on my machine:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\EnvDTE.dll
Updated
Updated to give example of getting 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;
}
}
}