We are developing an open source Visual Studio extension for running tests written with the C++ Google Test framework within VS. Part of the VS API for test adapters is the possibility to run tests with a debugger attached. However, that API does not allow to grab the output of the executing process: It only returns the process id, and afaik, there's no way to access that output if the process is already running.
Thus, we'd like to launch our own process, and attach a debugger to that process on our own (following the approach described in the accepted answer of this question). This works so far, but we have one issue: It seems that attaching a debugger is only possible if the process already runs, resulting in missed breakpoints; the reason seems to be that the breakpoints might already be passed until the debugger is attached. Note that we indeed hit breakpoints, so the approach seems to work in general, but it's not exactly reliable.
Here's the code for launching the process (where command
is the executable produced by the Google Test framework):
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);
And here's the utility method for attaching the debugger:
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 + "'");
}
}
Is there any way to attach a debugger in a more reliable manner? For instance, is it possible to launch a process from C# such that the process will wait for, say, 1s before starting to execute the passed command? That would give us enough time to attach the debugger (at least on my machine - I've tested this by adding a 1s wait period at the main()
method of the Google Test executable, but that's not an option, since our users would need to change their test code in order to be able to debug it with our extension)... Or is there even a clean way (the described way might obviously fail e.g. on slow machines)?
Update: Let's recap the problem statement: Our users have a C++ solution including tests written with the Google Test framework (which are compiled into an executable to be run e.g. from the command line). We provide a VS extension written in C# (a test adapter) which discovers the executable, runs it with the help of a Process
, collects the test results, and displays them within the VS test explorer. Now, if our users click Debug tests, we are starting the process running the C++ executable and then attach a debugger to that process. However, by the time it takes to attach the debugger to the process, the executable has already started running, and some tests have already been executed, resulting in breakpoints within those tests being missed.
Since we do not want to force our users to change their C++ code (e.g. by adding some waiting period at the begin of main()
method of the test code, or with one of the approaches referenced by Hans below), we need a different way to attach that debugger. In fact, the VS test framework allows to launch a process with a debugger attached (and that approach does not suffer from our problem - that's what we are doing now), but that approach does not allow grabbing the process' output since all we get is the process id of an already running process (at least I don't know how that can be done in this case - I have done my research on that (so I believe :-) ). Grabbing the output would have some significant benefits to our extension (which I do not list here - let me know in the comments if you are interested), so we are looking for a different way to handle such situations.
So how can we run the executable (including grabbing the executable's output) and immediately attach a debugger to it, such that no breakpoints are missed? Is that possible at all?