我可以以编程方式将正在运行的 .NET 6 进程附加到正在运行的 Visual Studio 调试器实例吗?

nos*_*tio 6 .net c# debugging visual-studio .net-6.0

我正在调试 IPC 逻辑,其中一个 .NET 6 进程正在启动另一个进程,但我无法在同一个 Visual Studio 2022 实例中调试这两个进程。

当子进程点击时DebugBreak(true)如下:


    [Conditional("ATTACH_DEBUGGER")]
    public static void DebugBreak(bool condition)
    {
        if (condition)
        {
            if (!System.Diagnostics.Debugger.IsAttached)
            {
                System.Diagnostics.Debugger.Launch();
                System.Diagnostics.Debugger.Break();
            }
        }
    }

Run Code Online (Sandbox Code Playgroud)

系统提示我启动 VS2022 的新实例来调试它:

VS 2022附加调试器

但是,如果我已经在调试父进程,我想在现有的 VS 实例中调试它。

这可能吗?是否有我可能缺少的 VS 配置设置?

当前的解决方法:手动附加,同时使用以下命令将子进程置于等待状态WaitForDebugger()

    [Conditional("ATTACH_DEBUGGER")]
    public static void WaitForDebugger()
    {
        using var process = Process.GetCurrentProcess();
        Console.WriteLine($"Waiting for debugger, process: {process.ProcessName}, id: {process.Id}, Assembly: {Assembly.GetExecutingAssembly().Location}");

        while (!System.Diagnostics.Debugger.IsAttached)
        {
            // hit Esc to continue without debugger
            if (Console.KeyAvailable && Console.ReadKey(intercept: true).KeyChar == 27)
            {
                break;
            }
            Thread.Sleep(TimeSpan.FromSeconds(1));
            Console.Beep(frequency: 1000, duration: 50);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Nei*_*l T 4

我有一个非常相似的设置,其中以下步骤可以实现此目的。但是,这是针对.NET Framework的,因此我不能保证它能够与 .NET Core 一起使用。(更新:请参阅下文了解 .NET Core 方法;请参阅末尾以获取 GitHub 上完整代码示例的链接。)

首先,在第一个进程中确定一个点(例如,FirstProcess),您要将调试器附加到第二个进程(SecondProcess)。显然SecondProcess此时需要运行(例如SecondProcess.exe)。

打开解决方案资源管理器并导航ReferencesFirstProcess. 右键单击,搜索“env”并添加两个引用,EnvDTE (v.8.0.0.0)然后EnvDTE80 (v.8.0.0.0).

将以下方法添加到FirstProcess要附加的类中:

private static void Attach(DTE2 dte)
{
    var processName = "SecondProcess.exe";
    var processes = dte.Debugger.LocalProcesses;
    
    // Note: Depending on your setup, consider whether an exact match is required instead of using .IndexOf()
    foreach (var proc in processes.Cast<EnvDTE.Process>().Where(proc => proc.Name.IndexOf(processName) != -1))
    {
        proc.Attach();
    }
}

private static DTE2 GetCurrent()
{
    // Note: "16.0" is for Visual Studio 2019; you might need to tweak this for VS2022.
    var dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.16.0");
    return dte2;
}
Run Code Online (Sandbox Code Playgroud)

Visual Studio 现在应该提示您将以下引用添加到您的类中:

using System.Runtime.InteropServices;
using EnvDTE80;
Run Code Online (Sandbox Code Playgroud)

FirstProcess最后,在您希望将调试器附加到的位置插入以下行SecondProcess

Attach(GetCurrent());
Run Code Online (Sandbox Code Playgroud)

如果您设法使其正常工作,请随时编辑此答案并进行 .NET Core 环境所需的任何更改。

更新 - 对于 .NET Core:

对于 .NET Core 有两个问题需要克服:

  1. DTE 引用在 .NET Core 中不可用。但是,它们可以作为 NuGet 包添加。您需要将两个 NuGet 包 envdte添加envdte80FirstProcess.
  2. 该方法Marshal.GetActiveObject()在 .NET Core 中不可用。要解决此问题,您可以从 Microsoft 获取源代码(此处)并手动添加;这已在下面的代码示例中完成

以下是完整的 .NET Core 工作代码示例FirstProcess这会在启动后以编程方式正确附加SecondProcess

private static void Attach(DTE2 dte)
{
    var processName = "SecondProcess.exe";
    var processes = dte.Debugger.LocalProcesses;
    
    // Note: Depending on your setup, consider whether an exact match is required instead of using .IndexOf()
    foreach (var proc in processes.Cast<EnvDTE.Process>().Where(proc => proc.Name.IndexOf(processName) != -1))
    {
        proc.Attach();
    }
}

private static DTE2 GetCurrent()
{
    // Note: "16.0" is for Visual Studio 2019; you might need to tweak this for VS2022.
    var dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.16.0");
    return dte2;
}
Run Code Online (Sandbox Code Playgroud)

注 1:这适用于Visual Studio 2019 和 .NET Core 5。我希望这适用于 VS2022 和 .NET Core 6,只需对上面注释的 Visual Studio 版本进行一次更改即可。

注 2:您只需要打开一个 Visual Studio 实例(尽管如果不可能,代码可能很容易修复)。

可下载演示

.NET Framework (v4.7.2) 和 .NET Core (v5.0) 的完整工作示例可在 GitHub 上找到: https: //github.com/NeilTalbott/VisualStudioAutoAttacher