Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > блокировка сообщения системы (перенаправление выво


Автор: Kim 27.10.2005, 09:00
Народ, подсобите плиз кто чем может... запарился уже...
В общем, есть такая ситуевинка. Имеется мой проект (на дельфи), который принимает исходники других проектов (не важно, каким образом принимает). Например, эти проекты тоже писаны на дельфи. Присылаемые проекты (будем называть их ПП) компилируются и запускаются. Важное условие: исходники ПП не должны меняться! Они запускаются так, как есть... При запуске юзается функция CreateProcess. Но там (в ПП) может быть что угодно. И бывает, что они вылетают с run-time error'ом. В этом случае появляется радостное окошко от "умной" винды о том, что "приложение выполнило ... и должно быть закрыто". А вот этого-то как раз и не надо. Потому как пока руками не будет нажата кнопка Terminate на сообщении процесс ПП не может быть закрыт даже TerminateProcess. А надо, чтобы проект работал корректно... Перенаправление вывода ничего не дает... все равно вываливается это окошко smile
Просьба предложить решение, где не пришлось бы программно искать окошко этого сообщения и программно же нажимать кнопочку... хотелось бы корректное решение...
//вынь 2к3 (в идеале - должно работать на любой выне)
//дельфи7

Автор: _hunter 27.10.2005, 11:45
полностью отключи уведомление об ошибках и программа будет спокойно умирать...

Автор: Kim 27.10.2005, 12:50
какие это опции компилятора?

Автор: _hunter 27.10.2005, 13:21
это опции системы smile

Автор: Kim 27.10.2005, 14:29
смешно... а какие именно?.. ты не мог бы не давать столь туманных объяснений?..
какую конкретно службу необходимо завалить?

Автор: _hunter 27.10.2005, 14:54
ну, батенька, свою систему ( на уровне трех кликов мышой ) надо бы знать...

System Properties->Advanced->Error Reporting

Автор: Kim 27.10.2005, 15:13
Знаешь... фишка вот в чем... отключил эту опцию... а дальше откомпилил и запустил следующий код:
{$APPTYPE CONSOLE}
var
f, g: text;
a, b: longint;
x: real;
begin
a:=1;
b:=0;
x:=a/b;
x:=x;
writeln(x);
end.

и у меня опять вылезла эта фигня... smile

Автор: _hunter 27.10.2005, 15:44
тогда DEBUG_PROCESS к dwCreationFlags добавь

Автор: Kim 27.10.2005, 16:10
То есть мой процесс становится дебаггером этого нового процесса?
а как обрабатывать события? например, возникает это событие... как мне узнать, что именно ран-тайм эррор, а не просто повесилась прога?
если не сложно - пару строк кода...

Автор: _hunter 27.10.2005, 16:37
ого куда мы заехали... smile ( а как мило все начиналось... просто не видеть сообщения об ошибках... )
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/writing_the_debugger_s_main_loop.asp

Автор: Kim 27.10.2005, 16:55
крута. Биг сенкс. Вот это реальная помощь... только остался один вопрос: у меня процессу выделяется не больше определенного интервала времени. И я вызываю WaitForSingleObject. Если он превышает интервал, то приложение снимается. Достаточно ли будет просто заменить эту функцию на WaitForDebugEvent?

и еще в догон: (чтоб понаглеть ;) ) Есть ли возможность ограничить ПП в ресурсах? например, не более определенного объема памяти, доступ - только к определенным к папкам и т.д...?

Автор: _hunter 27.10.2005, 17:12
нет. потому как WaitForDebugEvent может как сработать несколько раз так и не сработать ни разу. так что лучше два потока стартануть ( оно и не особо накладно ).

для ограничения доступа можно использовать CreateProcessAsUser ( и, соответственно, создать пользователя с правом доступа только к определенным папкам )
а вот с объемом памяти все гараздо интереснее: как система должна себя вести при превышении лимита? просто не давать памяти? так программа завернется. самой закрывать? поэтому тут придется самому монитор писать ( еще оди поток, в котором раз в н секунд делаем снимок ( CreateToolhelp32Snapshot ) ) и закрывать программу по превышению лимита

Автор: Darhazer 27.10.2005, 18:05
А почему не пользуете try...except

Код

var
f, g: text;
a, b: longint;
x: real;

begin

a:=1;
b:=0;
try
x:=a/b;
x:=x;
except
exit
end;

writeln(x);

end.

Автор: Kim 27.10.2005, 18:20
Нет, здесь логика работы очень жесткая: превысил ПП лимит времени (т.е. сработал WaitForSingleObject один раз), или вызван эксепшн (т.е. сработал WaitForDebugEvent один раз), или превышен лимит памяти - проект сразу должен быть завален...
И еще... WaitForSingleObject мне и нужен-то был для установления лимита времени. По идее то же самое умеет и WaitForDebugEvent... вот только передаст ли он управление при завершении процесса так же, как и WaitForSingleObject? Если да - то тогда просто тупо его заменить и все...

Автор: Kim 27.10.2005, 18:21
Darhazer, потому, что это проверяющая система. Она смотрит, правильно ли ТЫ написал исходник ;)

Автор: Kim 27.10.2005, 18:23
Хунтер, и если не секрет (сори за оффтоп) - как переводится фраза-подпись с латыни? ;)

Автор: _hunter 27.10.2005, 18:37
Цитата
Нет, здесь логика работы очень жесткая: превысил ПП лимит времени (т.е. сработал WaitForSingleObject один раз), или вызван эксепшн (т.е. сработал WaitForDebugEvent один раз), или превышен лимит памяти - проект сразу должен быть завален...

ну тогда точно монитор запустить и самому валить...

Цитата
И еще... WaitForSingleObject мне и нужен-то был для установления лимита времени. По идее то же самое умеет и WaitForDebugEvent

не совсем то же: если WaitForSingleObject сработает по истечению времени -- это будет говорить о том, что процес еще живет, а если WaitForDebugEvent -- только о том, что отладочных сообщений не было ( как сообщений о завершении процесса так и сообщений об ошибках ) поэтому заменять нельзя.

Цитата
Хунтер, и если не секрет (сори за оффтоп) - как переводится фраза-подпись с латыни? ;)

не сикрет smile
"Времена меняются, и мы меняемся вместе с ними"

Автор: Kim 27.10.2005, 20:09
Цитата(_hunter @ 27.10.2005, 18:37)
не совсем то же: если WaitForSingleObject сработает по истечению времени -- это будет говорить о том, что процес еще живет, а если WaitForDebugEvent -- только о том, что отладочных сообщений не было ( как сообщений о завершении процесса так и сообщений об ошибках )

именно поэтому можно smile
Мой проект должен именно это и отслеживать: один раз выделить (условно) 5 сек на то, чтобы ПП завернулся. Причем тихо-мирно, без ошибок и воплей. А если он не успеет - то я его сам заворачиваю ;) Ведь WaitForDebugEvent не будет ждать все 5 секунд, если ПП завершится раньше, правильно? smile
Получается 3 варианта развития событий:
1. ПП работает время меньше 5 сек и завершается корректно. Все ок.
2. ПП хочет работать больше 5 сек. По истечении таймлимита я его заворачиваю. Сообщение об ошибке генерит мой проект в свой лог.
3. ПП вылетает с эксепшином раньше 5 сек... Сообщение об ошибке генерит мой проект в свой лог.
вот и все...

А насчет памяти... отслежка раз в период - не очень хорошо по двум причинам:
1. ПП может выделить большой объем памяти "на раз" и быстренько его освободить, а я этого не замечу. А заметить надо.
2. Если сильно уменьшу интервал проверки - то мой проект будет кушать много ресурсов. А по задумке как можно больше ресурсов компа должно отдаваться ПП...
как быть?

Автор: Петрович 27.10.2005, 22:14
Цитата(Kim @ 27.10.2005, 21:09)
. ПП может выделить большой объем памяти "на раз" и быстренько его освободить, а я этого не замечу. А заметить надо.

А может тогда стоит перехватить функции распределения памяти и контролировать сам процесс распределения?

Автор: _hunter 28.10.2005, 11:44
для контроля достаточно просто знать выделяла ли программа больше память чем нужно. а для этого можно это:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/about_performance_monitoring.asp
использовать...

Автор: Kim 28.10.2005, 17:09
Хунтер, немного промазал:
http://msdn.microsoft.com/library/en-us/perfmon/base/process_memory_usage_information.asp
http://msdn.microsoft.com/library/en-us/perfmon/base/collecting_memory_usage_information_for_a_process.asp

;)

правда какой из них - не знаю еще, не втыкал конкретно...

Автор: Kim 29.10.2005, 11:37
hunter: можешь еще вот это объяснить?
Юзаю WaitForDebugEvent. В результате наблюдаю такую картинку...

При запуске 32битного приложения (работающего корректно!) получаю такую очередь эвентов:
-ProcessCreate- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -=!EXCEPTION!=- -ProcessExit-
Код возврата: 0

При запуске 32битного приложения (вызывающего деление на 0) - такая очередь:
-ProcessCreate- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!= ... и так до бесконечности

При запуске 16битного приложения (работающего корректно!) - такая очередь:
-ProcessCreate- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -=!EXCEPTION!=- -ThreadCreate- -LoadDLL- -LoadDLL- -OutputSTR- -LoadDLL- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -ThreadCreate- -=!EXCEPTION!=- -ThreadExit- -ThreadExit- -ProcessExit-
Код возврата: 0

При запуске 16битного приложения (вызывающего деление на 0) - такая очередь:
-ProcessCreate- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -=!EXCEPTION!=- -ThreadCreate- -LoadDLL- -LoadDLL- -OutputSTR- -LoadDLL- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -=!EXCEPTION!=- -ThreadCreate- -ThreadExit- -ThreadExit- -ProcessExit-
Код возврата: 200

Так как же мне грамотно определить, в каком случае запускаемый процесс отваливается, а в каком - нормально работает?..

Автор: Kim 29.10.2005, 12:10
Предыдущий вопрос снят... по 32битникам все понятно: надо было более подробно рассматривать эксепшины. Возник другой вопрос: сколько вообще этих эксепшинов бывает? Микрософт публикует всего 5, борланд в своем хелпе - 20. В сумме (разных) получается 21. Где еще можно поискать?

А вот по 16 битникам....

Правильная прога:
-ProcessCreate- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- =!ExBreakpoint!= -ThreadCreate- -LoadDLL- -LoadDLL- -OutputSTR- -LoadDLL- -ThreadCreate- -ThreadExit- -ThreadExit- -ProcessExit-
Код возврата: 0

Неправильная прога:
-ProcessCreate- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- -LoadDLL- =!ExBreakpoint!= -ThreadCreate- -LoadDLL- -LoadDLL- -OutputSTR- -LoadDLL- -ThreadCreate- -ThreadExit- -ThreadExit- -ProcessExit-
Код возврата: 200

Получается, их можно отследить только по коду возврата?.. smile


Автор: _hunter 31.10.2005, 13:25
так 20 их и есть:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/exception_record_str.asp
а остальные ( всякие наследники от Exception ) -- языкозависимы...

а с 16-ти битными -- хз ( я их только в школе писал... )
а зачем, кстати, в 16 бит компилировать ( особенно в делфи )?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)