Мы разрабатываем открытый исходный код Visual Studio extension для запуска тестов, написанных на основе C++ Google Test в VS. Часть VS API для тестовых адаптеров - это возможность запуска тестов с прикрепленным отладчиком. Однако этот API не позволяет захватить вывод исполняемого процесса: он возвращает только идентификатор процесса и afaik, нет способа получить доступ к этому выводу, если процесс уже запущен.C#: Приложить отладчик для обработки чистым способом
Таким образом, мы хотели бы запустить наш собственный процесс и приложить отладчик к этому процессу самостоятельно (следуя подходу, описанному в принятом ответе this question). Это работает до сих пор, но у нас есть одна проблема: похоже, что добавление отладчика возможно только в том случае, если процесс уже выполняется, что приводит к пропущенным точкам останова; причина в том, что точки останова могут быть уже пройдены до тех пор, пока не будет присоединен отладчик. Обратите внимание, что мы действительно попали в точки останова, поэтому подход, похоже, работает в целом, но он не совсем надежный.
Вот код для запуска процесса (где command
является исполняемым производится в рамках тестирования Google):
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 + "'");
}
}
Is есть ли способ прикрепить отладчик более надежным способом? Например, можно ли запустить процесс с C# таким образом, что процесс будет ждать, скажем, 1 с, прежде чем приступить к выполнению переданной команды? Это даст нам достаточно времени, чтобы прикрепить отладчик (по крайней мере, на моей машине - я протестировал это, добавив период ожидания 1 с методом main()
исполняемого файла Google Test, но это не вариант, так как нашим пользователям необходимо будет измените свой тестовый код, чтобы иметь возможность отлаживать его с помощью нашего расширения) ... Или есть даже чистый способ (описанный способ, очевидно, может не работать, например, на медленных машинах)?
Обновление: Перейдем к описанию проблемы. Наши пользователи имеют решение на C++, включая тесты, написанные на платформе Google Test (которые скомпилированы в исполняемый файл, который будет запущен, например, из командной строки). Мы предоставляем расширение VS, написанное на C# (тестовом адаптере), которое обнаруживает исполняемый файл, запускает его с помощью Process
, собирает результаты тестирования и отображает их в тестовом проводнике VS. Теперь, если наши пользователи нажмут Отладочные тесты, мы запускаем процесс выполнения исполняемого файла C++ и присоединяем отладчик к этому процессу. Однако к тому моменту, когда требуется приложить отладчик к процессу, исполняемый файл уже запущен, а некоторые тесты уже выполнены, в результате чего точки останова в этих пропущенных тестах отсутствуют.
Поскольку мы не хотим заставить наших пользователей изменять свой код на C++ (например, добавив некоторый период ожидания в начале метода тестового кода main()
или с помощью одного из подходов, на который ссылается Ганс ниже), нам нужно другой способ подключить этот отладчик. Фактически, среда тестирования VS позволяет запускать процесс с прикрепленным отладчиком (и этот подход не страдает от нашей проблемы - это то, что мы делаем сейчас), но этот подход не позволяет захватить процесс, поскольку все, что мы получаем это идентификатор процесса уже запущенного процесса (по крайней мере, я не знаю, как это можно сделать в этом случае - я сделал свое исследование по этому поводу (так что я верю :-)). Привлечение вывода будет иметь некоторые существенные преимущества для нашего расширения (которое я не перечисляю здесь - дайте мне знать в комментариях, если вы заинтересованы), поэтому мы ищем другой способ справиться с такими ситуациями.
Итак, как мы можем запустить исполняемый файл (включая захват вывода исполняемого файла) и немедленно приложить к нему отладчик, чтобы не было пропущено точек останова? Возможно ли это вообще?
http://stackoverflow.com/a/3575068/17034 –
Я не понимаю, как вещи, упомянутые в вашей ссылке, решат нашу проблему. Mutex и __debugbreak() потребуют модификации тестируемого кода, который не является вариантом, как я сказал (хотя и более чистым, чем ожидание в тестируемом коде в течение фиксированного времени). Я сомневаюсь, что я могу приложить отладчик быстрее, чем наш код может :-) (вариант 1 вашего ответа), и даже если бы я мог, это стало бы способом для многих пользователей. Другие ваши варианты совсем не подходят для нашей проблемы. Или я чего-то не хватает? Является ли мое описание проблемы недостаточным? – csoltenborn
@csoltenborn, как насчет использования свойства Debugger.IsAttached? Это может помочь нам проверить, подключен ли отладчик к одному процессу, например, если вам нужно запустить другие действия перед его подключением, вы можете остановить его во-первых. Или используйте контрольную точку условия, чтобы обрабатывать недостающий удаленный доступ в качестве обходного пути: https://msdn.microsoft.com/en-us/library/7sye83ce(v=vs.100).aspx –