2016-08-11 2 views
0

Мы разрабатываем открытый исходный код 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 позволяет запускать процесс с прикрепленным отладчиком (и этот подход не страдает от нашей проблемы - это то, что мы делаем сейчас), но этот подход не позволяет захватить процесс, поскольку все, что мы получаем это идентификатор процесса уже запущенного процесса (по крайней мере, я не знаю, как это можно сделать в этом случае - я сделал свое исследование по этому поводу (так что я верю :-)). Привлечение вывода будет иметь некоторые существенные преимущества для нашего расширения (которое я не перечисляю здесь - дайте мне знать в комментариях, если вы заинтересованы), поэтому мы ищем другой способ справиться с такими ситуациями.

Итак, как мы можем запустить исполняемый файл (включая захват вывода исполняемого файла) и немедленно приложить к нему отладчик, чтобы не было пропущено точек останова? Возможно ли это вообще?

+0

http://stackoverflow.com/a/3575068/17034 –

+0

Я не понимаю, как вещи, упомянутые в вашей ссылке, решат нашу проблему. Mutex и __debugbreak() потребуют модификации тестируемого кода, который не является вариантом, как я сказал (хотя и более чистым, чем ожидание в тестируемом коде в течение фиксированного времени). Я сомневаюсь, что я могу приложить отладчик быстрее, чем наш код может :-) (вариант 1 вашего ответа), и даже если бы я мог, это стало бы способом для многих пользователей. Другие ваши варианты совсем не подходят для нашей проблемы. Или я чего-то не хватает? Является ли мое описание проблемы недостаточным? – csoltenborn

+0

@csoltenborn, как насчет использования свойства Debugger.IsAttached? Это может помочь нам проверить, подключен ли отладчик к одному процессу, например, если вам нужно запустить другие действия перед его подключением, вы можете остановить его во-первых. Или используйте контрольную точку условия, чтобы обрабатывать недостающий удаленный доступ в качестве обходного пути: https://msdn.microsoft.com/en-us/library/7sye83ce(v=vs.100).aspx –

ответ

1

Вы можете PInvoke CreateProcess (смотри пример How to call CreateProcess()...) для запуска отлаживаемый с помощью флага создания CREATE_SUSPENDED (см Creation Flags для более подробно), а затем PInvoke ResumeThread продолжить, как только ваш отладчик прилагается.

Возможно, вам потребуется настроить параметры CreateProcess, в зависимости от ваших конкретных потребностей, но это должно сделать это.

Update: гораздо лучший вариант, так как вы пишете расширение VS, чтобы использовать интерфейс IVsDebugger4 для вызова LaunchDebugTargets4. Интерфейс документирован, и вы можете найти множество примеров на GitHub (просто выполните поиск LaunchDebugTargets4). Этот метод позволит избежать этого досадного разрыва в VS, как только вы присоедините его с помощью собственного механизма отладки.

+0

Работает вообще, спасибо еще раз. Остается одна проблема (с которой мы можем жить): VS показывает, что «exe запустило окно точки останова», прежде чем запускать первую точку останова или даже если точка останова не установлена ​​(скорее всего, потому что процесс приостанавливается в момент присоединения VS отладчик). Я приму свой ответ, как только мы будем уверены, что это путь. – csoltenborn

Смежные вопросы