You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:23:27