![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ловим сообщения программы [D7, XP]
cruiser © (2008-09-30 17:06:00)Здравствуйте уважаемые Мастера! Вопрос:
Как можно реализовать на Delphi отлов сообщений некоторой программы, которые она выдает в окно командной строки после её запуска из командной строки? Например, в окне cmd пишется: удаление произведено. А как мне отловить это сообщение и например поместить в showmessage моей программы?
cruiser (2008-10-01 13:48:00) [21]А как же тогда будет верно остановить его (дочернего процесса) работу и выкинуть из памяти, если это очень нужно?
Сергей М. (2008-10-01 13:42:00) [22]
> в любой момент прибивался бы дочерний процесс
Это, мягко говоря, не есть гуд.
Если процесс жив и нормально реагирует на ожидаемые события ввода, "прибивать" его не только нехорошо, но и в отдельных случаях чревато опасными последствиями.
cruiser (2008-10-01 13:37:00) [23]Реализовал уже :) Я просто отвечал вот на это:
> завершение
> > приложения ведет к автоматическому уничтожению порожденного
>
> > процесса cmd.exe, если на этот момент он еще активен.
а closequery, так, попало в цитату :) Сегодня вечером проверю предложенный Вами код.
Сергей М. (2008-10-01 13:30:00) [24]
> мне нужно что бы моё приложение не закрывалось, а по нажатию
> на кнопку стоп в любой момент прибивался бы дочерний процесс
И что тебе мешает реализовать такую логику ?
cruiser (2008-10-01 12:41:00) [25]Спасибо. Дома попробую этот код.
> Никаких обработчиков OnCloseQuery не требуется - завершение
> приложения ведет к автоматическому уничтожению порожденного
> процесса cmd.exe, если на этот момент он еще активен.
А мне нужно что бы моё приложение не закрывалось, а по нажатию на кнопку стоп в любой момент прибивался бы дочерний процесс.
Сергей М. (2008-10-01 10:08:00) [26]
> окно консоли видно, но в нём ничего не пишется
Видно его или не видно, но писаться в нем ничего и не должно, потому что станд.вывод консоли тобой перехвачен.
Вот этот чуть подкорректированный код чудесно работает и в точности выполняет поставленную тобой задачу:
var
Security: TSecurityAttributes;
ReadPipe, WritePipe: THandle;
Start: TStartupInfo;
ProcessInfo: TProcessInformation;
Buffer: PChar;
Apprunning: Cardinal;
BytesRead: Cardinal;
procedure RunDosInMemo(CmdLine: string; AMemo: TMemo);
const
ReadBuffer = 2400;
begin
with Security do
begin
nlength := SizeOf(TSecurityAttributes);
binherithandle := true;
lpsecuritydescriptor := nil;
end;
if Createpipe(ReadPipe, WritePipe,
@Security, 0) then
begin
Buffer := AllocMem(ReadBuffer + 1);
FillChar(Start, Sizeof(Start), #0);
start.cb := SizeOf(start);
start.hStdOutput := WritePipe;
start.hStdInput := ReadPipe;
start.dwFlags := STARTF_USESTDHANDLES +
STARTF_USESHOWWINDOW;
start.wShowWindow := SW_HIDE;
if CreateProcess(nil,
PChar(CmdLine),
@Security,
@Security,
true,
NORMAL_PRIORITY_CLASS,
nil,
nil,
start,
ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
while not Application.Terminated do begin
Apprunning := WaitForSingleObject
(ProcessInfo.hProcess, 10);
if Apprunning <> WAIT_TIMEOUT then Break;
ReadFile(ReadPipe, Buffer[0],
ReadBuffer, BytesRead, nil);
Buffer[BytesRead] := #0;
OemToAnsi(Buffer, Buffer);
AMemo.Text := AMemo.text + string(Buffer);
Application.ProcessMessages;
end;
end;
FreeMem(Buffer);
if Apprunning = WAIT_TIMEOUT then TerminateProcess(ProcessInfo.hProcess, 0);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ReadPipe);
CloseHandle(WritePipe);
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
RunDosInMemo('ping 127.0.0.1 -t', Memo);
end;
Никаких обработчиков OnCloseQuery не требуется - завершение приложения ведет к автоматическому уничтожению порожденного процесса cmd.exe, если на этот момент он еще активен.
cruiser (2008-10-01 09:42:00) [27]В листинге наверху видно что, например, 'ping 127.0.0.1 -t'
Заметил еще вот что. При запуске дочернего процесса с параметром sw_hide, то она не отрабатывает свою функциональность. А вот если с параметром sw_normal, то окно консоли видно, но в нём ничего не пишется (я так понимаю и должно быть). Но при этом код не отрабатывает запись в memo1.
Пробовал вот сюда:
repeat
Apprunning := WaitForSingleObject
(ProcessInfo.hProcess, 10);
ReadFile(ReadPipe, Buffer[0],
ReadBuffer, BytesRead, nil);
Buffer[BytesRead] := #0;
OemToAnsi(Buffer, Buffer);
AMemo.Text := AMemo.text + string(Buffer);
Application.ProcessMessages;
until (Apprunning <> WAIT_TIMEOUT);
вместо AMemo.Text := AMemo.text + string(Buffer) ставить showmessage string(buffer) и думал что сообщение будет выдаваться при каждом новом выводи консольной программы. А ннееет - выдается только в конце по завршению процесса консольной проги и несколько раз, пока всё не покажет... Странно как-то. Сегодня буду пробовать другой код, найденный на просторах инета...
Сергей М. (2008-10-01 09:06:00) [28]
> cruiser © (01.10.08 00:57) [26]
Чему у тебя равен параметр CmdLine при вызове процедуры ?
cruiser (2008-10-01 00:57:00) [29]Опытным путем определил что висяку способствует параметр start.dwFlags. Если его закоментить, то дочерняя прога запускается и отрабатывает, правда наша программа не видит момента закрытия консольного приложения и тупо висит. + в этом случае так же не идет перехват того, что программа выдает в консоль.
Германн (2008-10-01 00:54:00) [30]
> Подскажите, на что обратить внимание?
Нет это я ошибся в арифметике. :(
cruiser (2008-10-01 00:44:00) [31]Подскажите, на что обратить внимание? Где очепяток?
Германн (2008-10-01 00:33:00) [32]
> if CreateProcess(nil,
> PChar(CmdLine),
> @Security,
> @Security,
> true,
> NORMAL_PRIORITY_CLASS,
> nil,
> nil,
> start,
> ProcessInfo) then
>
Тут нет очепяток?
cruiser (2008-10-01 00:17:00) [33]
> Естесственно. Ключик -t это "Отправка пакетов на указанный
> узел до команды прерывания. Для вывода статистики и продолжения
> нажмите <Ctrl>+<Break>, для прекращения - <Ctrl>+<C>."
Это то здесь причем?
> Запустите ее под DOSом. Если не обругается - то это DOS-
> программа.
Не знаю что и делать. Запускаемая программа ругается в лог файле на неправильную конфигурацию программы. Странно. Может какая-то защита стоит или недоработка, что программу нельзя запускать как дочерний процесс?
turbouser (2008-10-01 00:12:00) [34]
> cruiser © (30.09.08 23:12) [12]
>
> спасибо. попробую.
> еще вопрос. при запуске любого приложения, вместо 'ping
> 127.0.0.1 -t' приложение приходит в ступор
Естесственно. Ключик -t это "Отправка пакетов на указанный узел до команды прерывания. Для вывода статистики и продолжения нажмите <Ctrl>+<Break>, для прекращения - <Ctrl>+<C>."
cruiser (2008-10-01 00:01:00) [35]Написано в описании проги: this program cannot be run in dos mode
Юрий Зотов (2008-09-30 23:57:00) [36]> cruiser © (30.09.08 23:55) [18]
Запустите ее под DOSом. Если не обругается - то это DOS-программа.
cruiser (2008-09-30 23:55:00) [37]Это exe файл, который при запуске с опр. параметрами пишет отчет совей работы в окно консоли. Может в это проблема?
Юрий Зотов (2008-09-30 23:51:00) [38]Обратил внимание на название процедуры - там есть слово DOS. Если это DOS-программа (а не консольная Windows-программа), то она может выводить не в stdout, а напрямую в видеобуфер ($B800).
cruiser (2008-09-30 23:45:00) [39]есть предположение, что консольная прога выводит свои данные в окно консоли каким-то другим способом, отличным от того что мы пытаемся перехватить...
cruiser (2008-09-30 23:41:00) [40]В том то и дело что консольное. Т.е. это самое консольное приложение не просит никаких нажатий, а просто делает свою работу :( Куда копать?