gpt4 book ai didi

C#:以干净的方式将调试器附加到进程

转载 作者:行者123 更新时间:2023-11-28 05:33:24 25 4
gpt4 key购买 nike

我们正在开发开源 Visual Studio extension用于运行用 C++ 编写的测试 Google Test VS中的框架。用于测试适配器的 VS API 的一部分是可以在附加调试器的情况下运行测试。但是,该 API 不允许获取正在执行的进程的输出:它仅返回进程 ID,而且据我所知,如果进程已经在运行,则无法访问该输出。

因此,我们想启动我们自己的进程,并自行将调试器附加到该进程(遵循 this question 的已接受答案中描述的方法)。到目前为止这是有效的,但我们有一个问题:似乎只有在进程已经运行时才可以附加调试器,从而导致错过断点;原因似乎是在附加调试器之前断点可能已经通过。请注意,我们确实遇到了断点,因此该方法似乎总体上可行,但并不完全可靠。

下面是启动进程的代码(其中 command 是由 Google Test 框架生成的可执行文件):

var processStartInfo = new ProcessStartInfo(command, param)
{
RedirectStandardOutput = true,
RedirectStandardError = false,
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = workingDirectory
};

Process process = new Process { StartInfo = processStartInfo };
process.Start()

DebuggerAttacher.AttachVisualStudioToProcess(vsProcess, vsInstance, process);

下面是附加调试器的实用方法:

internal static void AttachVisualStudioToProcess(Process visualStudioProcess, _DTE visualStudioInstance, Process applicationProcess)
{
//Find the process you want the VS instance to attach to...
DTEProcess processToAttachTo = visualStudioInstance.Debugger.LocalProcesses.Cast<DTEProcess>().FirstOrDefault(process => process.ProcessID == applicationProcess.Id);

//AttachDebugger to the process.
if (processToAttachTo != null)
{
processToAttachTo.Attach();

ShowWindow((int)visualStudioProcess.MainWindowHandle, 3);
SetForegroundWindow(visualStudioProcess.MainWindowHandle);
}
else
{
throw new InvalidOperationException("Visual Studio process cannot find specified application '" + applicationProcess.Id + "'");
}
}

有什么方法可以更可靠地附加调试器吗?例如,是否可以从 C# 启动一个进程,以便该进程在开始执行传递的命令之前等待 1 秒?这会给我们足够的时间来附加调试器(至少在我的机器上 - 我已经通过在 Google Test 可执行文件的 main() 方法中添加 1s 等待时间来测试它,但事实并非如此一个选项,因为我们的用户需要更改他们的测试代码以便能够使用我们的扩展对其进行调试)...或者甚至有一种干净的方法(所描述的方法可能会明显失败,例如在慢速机器上)?

更新:让我们回顾一下问题陈述:我们的用户有一个 C++ 解决方案,包括使用 Google 测试框架编写的测试(这些测试被编译成可执行文件,例如从命令行运行)。我们提供了一个用 C# 编写的 VS 扩展(测试适配器),它发现可执行文件,在 Process 的帮助下运行它,收集测试结果,并将它们显示在 VS 测试资源管理器中。现在,如果我们的用户单击调试测试,我们将启动运行 C++ 可执行文件的进程,然后将调试器附加到该进程。但是,在将调试器附加到进程时,可执行文件已经开始运行,并且已经执行了一些测试,导致这些测试中的断点被遗漏。

因为我们不想强制我们的用户更改他们的 C++ 代码(例如,通过在测试代码的 main() 方法的开头添加一些等待时间,或者使用其中一种方法由下面的 Hans 引用),我们需要一种不同的方式来附加该调试器。事实上,VS 测试框架允许启动一个带有调试器的进程(这种方法不会遇到我们的问题 - 这就是我们现在正在做的),但这种方法不允许获取进程的输出,因为我们得到是已经运行的进程的进程 ID(至少我不知道在这种情况下如何完成 - 我已经对此进行了研究(所以我相信 :-))。获取输出会对我们的扩展有一些显着的好处(我没有在这里列出 - 如果您有兴趣,请在评论中告诉我),因此我们正在寻找一种不同的方式来处理这种情况。

那么我们如何运行可执行文件(包括抓取可执行文件的输出)并立即将调试器附加到它,这样就不会遗漏任何断点?这可能吗?

最佳答案

您可以 PInvoke CreateProcess(参见示例 How to call CreateProcess()...)使用 CREATE_SUSPENDED 创建标志(参见 Creation Flags 了解更多详细信息)启动调试对象,然后 PInvoke ResumeThread 在附加调试器后继续。

您可能需要调整 CreateProcess 的选项,具体取决于您的具体需要,但应该这样做。

更新:一个好得多的选择是使用 IVsDebugger4 接口(interface)来调用 LaunchDebugTargets4,因为您正在编写 VS 扩展。 .该接口(interface)已记录在案,您可以在 GitHub 上找到大量示例(只需搜索 LaunchDebugTargets4)。一旦您附加了 native 调试引擎,此方法将避免 VS 中令人讨厌的中断。

关于C#:以干净的方式将调试器附加到进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38888945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com