目录
- 打开解决方案
- 运行解决方案
- 常用对象和方法
- 具体步骤
- 参考链接
最近工作中想做一个小工具,希望能在Vistual Studio外部运行指定的解决方案。经过调试完成了以下Demo。
打开解决方案
打开解决方案其实本事只是打开一个文件,所以需要启动一个进程,使用默认程序打开文件。
- Process 类:
System.Diagnostics.Process
类提供了启动和停止系统进程的方法。它可以用来启动外部应用程序或文件。 - ProcessStartInfo 类:
ProcessStartInfo
类用于指定启动进程时的参数。通过设置FileName
属性,可以指定要启动的文件或应用程序的路径。-
UseShellExecute 属性:布尔类型的属性,用于决定启动进程的方式。
-
使用操作系统的外壳程序:
如果
UseShellExecute
设置为true
,启动进程时会使用操作系统的外壳程序(例如 Windows Explorer)。外壳程序会根据文件类型选择合适的应用程序来打开文件。通常用于启动非可执行文件(如文档、URL 等)。 -
直接启动进程
如果
UseShellExecute
设置为false
,则直接启动指定的可执行文件,而不使用外壳程序,通常用于启动可执行文件(如 .exe 文件)。
-
- 启动外部程序:通过调用
Process.Start
方法并传入ProcessStartInfo
对象,可以启动指定的外部程序或打开指定的文件。
// 创建一个 ProcessStartInfo 对象,用于启动一个新进程
Process.Start(new ProcessStartInfo
{// 设置要启动的文件路径FileName = FilePath,// 指定是否使用操作系统的外壳程序来启动进程UseShellExecute = true
});
运行解决方案
想要对Visual Studio 进行自动化操作,不可避免需要了解一下DTE2,
DTE2 是指 Development Tools Environment 2。
它允许开发者通过编程方式控制和扩展 Visual Studio 的功能。例如:
- 项目管理:创建、打开、关闭和保存项目。
- 代码操作:编辑、格式化和重构代码。
- 调试支持:启动和控制调试会话,设置断点,监视变量等。
常用对象和方法
- DTE2.Solution:管理解决方案。
- DTE2.SolutionBuild:解决方案级别构建自动化模型
具体步骤
- 安装EnvDTE80
EnvDTE80 是 Visual Studio 的自动化对象模型的一部分,允许开发者通过编程方式控制和扩展 Visual Studio 的功能。
- 获取 DTE 对象
思路: 通过指定的名称在运行对象表(ROT)中查找并返回一个 DTE2
对象。
其中涉及主要内容,GetRunningObjectTable
方法: 运行对象表(ROT) 是一个系统级的表格,包含了当前正在运行的所有 COM 对象。通过 ROT,可以枚举和访问这些对象。
public static DTE2 GetDteByName(string name)
{// 分配内存用于存储获取的对象数量uint numFetchedUInt = (uint)Marshal.SizeOf(numFetched);// 声明运行对象表和枚举器,以及用于存储枚举到的单个对象的数组。IRunningObjectTable runningObjectTable;IEnumMoniker monikerEnumerator;IMoniker[] monikers = new IMoniker[1];// 创建绑定上下文IBindCtx bindCtx;Marshal.ThrowExceptionForHR(CreateBindCtx(reserved: 0, ppbc: out bindCtx));// 获取运行对象表 通过绑定上下文获取当前的运行对象表。bindCtx.GetRunningObjectTable(out runningObjectTable);// 枚举运行对象runningObjectTable.EnumRunning(out monikerEnumerator);monikerEnumerator.Reset();// 遍历所有运行对象while (monikerEnumerator.Next(1, monikers, out numFetchedUInt) == 0){// 为每个对象创建新的绑定上下文IBindCtx ctx;CreateBindCtx(0, out ctx);// 获取运行对象的显示名称string runningObjectName;monikers[0].GetDisplayName(ctx, null, out runningObjectName);// 检查显示名称是否包含指定的名称if (runningObjectName.Contains(name)){// 获取运行对象object runningObjectVal;runningObjectTable.GetObject(monikers[0], out runningObjectVal);// 将运行对象转换为DTE2类型并返回DTE2 dte = (DTE2)runningObjectVal;return (dte);}}// 如果没有找到匹配的对象,返回nullreturn null;
}
- 使用
dte.Solution.SolutionBuild
调试运行
// 获取所有名为 "VisualStudio.DTE" 的 DTE 对象
var dtes = CsFile.GetDtesByName("VisualStudio.DTE");// 初始化一个标志变量,表示是否找到并打开了解决方案
bool isOpened = false;// 遍历所有 DTE 对象
foreach (DTE2 dte in dtes)
{// 如果当前 DTE 对象的解决方案文件名与指定的文件路径匹配if (dte.Solution.FileName == FilePath){// 启动调试dte.Solution.SolutionBuild.Debug();// 设置标志变量为 true,表示已找到并打开了解决方案isOpened = true;// 退出循环break;}
}// 如果没有找到并打开任何匹配的解决方案
if (!isOpened)
{// 显示消息框,提示用户先打开指定的解决方案MessageBox.Show($"未找到打开的{FilePath}解决方案,请先打开该解决方案!");
}
- 停止
public static void CloseSolution(string solutionPath)
{var dtes = CsFile.GetDtesByName("VisualStudio.DTE");foreach (DTE2 dte in dtes){if (dte.Solution.FileName == solutionPath){dte.Debugger.Stop();break;}}
}
参考链接
- 在Visual Studio IDE之外获得EnvDTE.DTE实例 - IT宝库 (itbaoku.cn)
- DTE2 Interface (EnvDTE80) | Microsoft Learn