"Тихий" запуск служебного подпроцесса

  • Автор темы evan
  • Дата начала
Статус
Закрыто для дальнейших ответов.
E

evan

Здравствуйте.
В общем, стоит такая задача: создать систему автоматического тестирования для некоей сложной функции, находящейся в Win32 unmanaged DLL. Система тестирования должна вызывать эту функцию много раз с разными входными данными, сохраняя результат вызова в логах. Исходников DLL нет (имеет место нечто вроде аутсорсинговой разработки).
Для решения задачи решено сделать на c# два модуля: маленький консольный wrapper принимает во входных параметрах примерно то же самое, что надо передать в функцию, делает LoadLibrary/GetProcAddress, вызывает функцию, и результаты через сокет передает второму модулю, который рисует GUI и ведет логи. Если wrapper умирает, второй модуль отмечает этот факт в логах, перезапускает wrapper и продолжает тестирование. Исключения, которые выбрасываются из DLLки, ловятся в try/catch во wrapper'е, и пишутся в логи.
Теперь собственно проблема: в DLLке могут быть ошибки выделения памяти и другие неприятные вещи, которые в этом дотнетовском wrapper'е кончаются тем, что try/catch никаких исключений не видит, но после завершения функции main() вдруг вываливается исключение, сообщение о котором выводится, как положено, в MessageBox'е. Вот этот эффект (вывод MessageBox с сообщением об ошибке) необходимо побороть, т.е. сделать так, чтобы процесс просто молча умирал. Можно также скрыть и консоль wrapper'а, но это не обязательно. Добиваться этого можно как модификацией самого wrapper'а, так и запускающего его модуля.
Приветствуются идеи любой степени смутности :rolleyes:
 
M

mr_ST

1) ИМХО, лучше бы писать враппер на обычных плюсах (С++) бо там простор для маневра больше, плюс вожности системы по отлову нестандартных ситуаций.

2) Врапперу, после окончания тестировани произвести самоубийство, а не просто выходить из мэйна :rolleyes: То бишь TerminateProcess(self, uExitCode)


Да, и посмотри что пишут в msdn на тему SEH вообще и SetUnhandledExceptionFilter функции в частности.
 
E

evan

1) Такой вариант (с wrapper'ом на с++) тоже пробовали, разницы особой нет.
2) С TerminateProcess щас попробую, спасибо.
 
E

evan

Для: mr_ST
Вдохновившись твоими советами, нашел сразу две интересных вещи. Во-первых, вариант с TerminateProcess (точнее, с дотнетовским System.Diagnostics.Process.GetCurrentProcess().Kill() ) срабатывает, хотя я пока не понимаю почему :rolleyes:
Во-вторых, Win32'шные SetErrorMode и SetUnhandledExceptionFilter - вообще прям то что доктор прописал. К сожалению, перевод всего враппера на win32 нужно согласовывать с заказчиком, и еще неизвестно чем это кончится. В принципе, SetErrorMode нормально отрабатывает и когда я его вызываю из c#, но с SetUnhandledExceptionFilter я так извращаться не стал.
Не знаешь, нет ли дотнетовских аналогов у этих функций? У AppDomain есть event UnhandledException, но это лишь дает возможность добавить свой обработчик, как загасить с его помощью MessageBox, генерируемый дефолтовым обработчиком, я не нашел. Да и при GP fault он почему-то не вызывается, видимо, чисто под System.Exception заточен.
 
M

mr_ST

Для: mr_ST
Вдохновившись твоими советами, нашел сразу две интересных вещи. Во-первых, вариант с TerminateProcess (точнее, с дотнетовским System.Diagnostics.Process.GetCurrentProcess().Kill() ) срабатывает, хотя я пока не понимаю почему :)

Все дело в волшебных пузырьках :rolleyes: Дело в том, что когда выходишь из main, там может выполняться еще куча кода, типа деструкции статических обьектов, провека хипа на консистентность и т.п. При самоубийстве этого не происходит, т.е. code flow уходит в TerminateProcess и уже не возвращается. Как это работает в .NET затрудняюсь ответить, но, видимо, в DLL просто не вызывается код отвечающий за окнчание работы оной.

Во-вторых, Win32'шные SetErrorMode и SetUnhandledExceptionFilter - вообще прям то что доктор прописал. К сожалению, перевод всего враппера на win32 нужно согласовывать с заказчиком, и еще неизвестно чем это кончится. В принципе, SetErrorMode нормально отрабатывает и когда я его вызываю из c#, но с SetUnhandledExceptionFilter я так извращаться не стал.
Не знаешь, нет ли дотнетовских аналогов у этих функций? У AppDomain есть event UnhandledException, но это лишь дает возможность добавить свой обработчик, как загасить с его помощью MessageBox, генерируемый дефолтовым обработчиком, я не нашел. Да и при GP fault он почему-то не вызывается, видимо, чисто под System.Exception заточен.

Скорее всего нет, т.к. это сильно платформозависимые вещи. А у домена только обработка .NET исключений.
 
K

karlito

try
{

}
catch(Exception ex)
{

}
catch
{
// здесь перехватываются исключения не производные от System.Exception
// смотри класс System.Runtime.InteropServices.Marshal,
// там найдёшь некоторые функции для работы c неуправляемым кодом
}
 
E

evan

Для: karlito
Спасибо за неравнодушие, но это всё я и так знаю. Исключение возникает после выхода из main.
 
E

evan

Проблема решена путем перехода на win32 (VC++ 6.0) и использования функций SetErrorMode и SetUnhandledExceptionFilter. Для надежности вызываю TerminateProcess из UnhandledExceptionFilter.
Спасибо всем ответившим.
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!