Открытие файла 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 экземпляра запущенного процесса, в котором открыто два процесса