如何通过System.Diagnostics.Process获取Visual Studio解决方案的EnvDTE.DTE接口
背景:
我正在开发一款应用,支持用户打开Visual Studio解决方案文件(.sln)。用户可以通过应用的UI编辑已打开项目的特定内容,无需手动修改代码。为避免混淆,这里以Visual Studio为例说明,但实际会用TwinCatXAEShell打开和操作该文件,二者本质逻辑一致。
问题:
我用System.Diagnostics.Process.Start()打开解决方案文件,但要向运行中的项目发送命令,需要获取该项目的EnvDTE.DTE接口引用。
以下是我用于打开文件的代码:
// get TwinCAT application string applicationPath = getTwinCatInstallPath(); if (!File.Exists(applicationPath)) return; // start TwinCAT with provided file System.Diagnostics.Process fileopener = new System.Diagnostics.Process(); fileopener.StartInfo = new ProcessStartInfo() { FileName = applicationPath, Arguments = $"\"{solutionPath}\"", WindowStyle = ProcessWindowStyle.Minimized }; fileopener.Start();
现有方案:
方案一:
目前我通过遍历Windows运行对象表(Running Object Table),在运行对象名称中匹配进程ID来获取接口。但我觉得应该可以直接通过System.Diagnostics.Process实例来访问...
以下是遍历Windows运行对象表的代码:
(显然并非完全由我编写 ^^)
static DTE ProcessToDte(System.Diagnostics.Process process) { // get list of windows processes IRunningObjectTable runningObjectTable; GetRunningObjectTable(0, out runningObjectTable); // get enumerator for the list runningObjectTable.EnumRunning(out IEnumMoniker monikerEnumerator); monikerEnumerator.Reset(); // iterate over list and crate a subset with fitting processes IMoniker[] monikers = new IMoniker[1]; while (monikerEnumerator.Next(1, monikers, IntPtr.Zero) == 0) { CreateBindCtx(0, out IBindCtx ctx); monikers[0].GetDisplayName(ctx, null, out string runningObjectName); if (!runningObjectName.Contains("TcXaeShell")) continue; if (runningObjectName.Contains(process.Id.ToString())) { runningObjectTable.GetObject(monikers[0], out object runningObjectData); DTE ide; try { ide = runningObjectData as DTE; } catch { continue; } return ide; } } return null; } [DllImport("ole32.dll")] static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable rot); // needed for ProcessToDte() [DllImport("ole32.dll")] static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); // needed for ProcessToDte()
方案二:
我还发现另一种解决思路——完全不用System.Diagnostics.Process,而是通过以下代码打开解决方案文件,但process.Start()的写法对后续代码审查来说更直观易懂。
Type t = Type.GetTypeFromProgID("TcXaeShell.DTE.15.0"); if (t == null) return; DTE dte; dte = (DTE)Activator.CreateInstance(t); dte.SuppressUI = false; dte.MainWindow.Visible = true; dte.MainWindow.WindowState = vsWindowState.vsWindowStateMinimize; dte.UserControl = true;
内容的提问来源于stack exchange,提问作者Conradict
相关产品推荐
相关产品推荐

