C# 代码启动解决方案、调试运行或关闭项目(VS2022)

发布于:2024-10-15 ⋅ 阅读:(119) ⋅ 点赞:(0)


最近工作中想做一个小工具,希望能在Vistual Studio外部运行指定的解决方案。经过调试完成了以下Demo。

打开解决方案

打开解决方案其实本事只是打开一个文件,所以需要启动一个进程,使用默认程序打开文件。

  1. Process 类System.Diagnostics.Process 类提供了启动和停止系统进程的方法。它可以用来启动外部应用程序或文件。
  2. ProcessStartInfo 类ProcessStartInfo 类用于指定启动进程时的参数。通过设置 FileName 属性,可以指定要启动的文件或应用程序的路径。
    • UseShellExecute 属性:布尔类型的属性,用于决定启动进程的方式。

    • 使用操作系统的外壳程序

      如果 UseShellExecute 设置为 true,启动进程时会使用操作系统的外壳程序(例如 Windows Explorer)。外壳程序会根据文件类型选择合适的应用程序来打开文件。通常用于启动非可执行文件(如文档、URL 等)。

    • 直接启动进程

      如果 UseShellExecute 设置为 false,则直接启动指定的可执行文件,而不使用外壳程序,通常用于启动可执行文件(如 .exe 文件)。

  3. 启动外部程序:通过调用 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);
        }
    }
    // 如果没有找到匹配的对象,返回null
    return 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;
        }
    }
}

参考链接

  1. 在Visual Studio IDE之外获得EnvDTE.DTE实例 - IT宝库 (itbaoku.cn)
  2. DTE2 Interface (EnvDTE80) | Microsoft Learn

网站公告

今日签到

点亮在社区的每一天
去签到