Обработка системных сообщений в консольной программе
Модератор: Модераторы
Обработка системных сообщений в консольной программе
Господа, никто не сталкивался с подобной проблемой? Есть веб-сервер (основная идея взята отсюда https://wiki.lazarus.freepascal.org/fpWeb_Tutorial/ru). При запуске открывается консольное окно и мне надо управлять (в частности, на текущий момент) минимизацией и восстановлением этого окна. Хэндл я получил, сообщения посылаются нормально, но вот как и где их отловить, никак не могу найти. Подозреваю, что проблема эта того же порядка, что и проблема обработки закрытия этого окна (с помощью функции SetConsoleCtrlHandler), но уверенности нет... 
Сейчас мне немного в лом искать но на форуме есть куча информации по консольным приложениям .
https://clck.ru/rgEKf
https://clck.ru/rgE2e
https://clck.ru/rgEKf
https://clck.ru/rgE2e
Вводные немного странные - как правило веб-сервера пишут лог не в консольное окно, а в файл. Теоретически можно заставить писать в поток (не тот, который фрипаскалевский, а тот который в Юниксе c | работает).S_Gur писал(а):Господа, никто не сталкивался с подобной проблемой? Есть веб-сервер (основная идея взята отсюда https://wiki.lazarus.freepascal.org/fpWeb_Tutorial/ru). При запуске открывается консольное окно и мне надо управлять (в частности, на текущий момент) минимизацией и восстановлением этого окна. Хэндл я получил, сообщения посылаются нормально, но вот как и где их отловить, никак не могу найти. Подозреваю, что проблема эта того же порядка, что и проблема обработки закрытия этого окна (с помощью функции SetConsoleCtrlHandler), но уверенности нет...
Если у вас веб-сервер консольный самописный, то он может писать лог в stdout или stderr чтобы администратор сам потом определял, куда его сохранять следующим макаром
webserver > log.txt &
webserver > log.txt 2>&1 & (для склейки stdout stderr в единый поток)
при этом вывод может быть отдан другой программе через конвейер
webserver | log-analyzer > log.txt &
а та программа может выполнять разумную обработку, записывать или куда-то пересылать. Например в стандартный rsyslog, который отошлет потом дальше в централизованные системы сбора логов предприятия. причем вам в своем приложении не придётся даже особо с этим возиться:
webserver | nc -u 127.0.0.1 514
Shleps, простите, мне сейчас абсолютно неважно, куда пишется лог. Проблема совсем не в этом. Веб-сервер запускается в обычном системном командном окне. Это окно можно минимизировать, максимизировать, перетащить, изменить размер или просто закрыть крестиком. Именно эти системные сообщения (Hide, Restore, Minimize и прочие) мне надо отловить и обработать. При том, что хендл приложения я достаю и могу сам отправить ему команду на минимизацию. Вопрос в том, как к консольному приложению прицепить обработчик этих сообщений. Я сейчас играюсь с примером, описанным по этой ссылке:
http://delphimaster.net/view/1-25748/all
Пока зарегистрировать обработчик для моего приложения у меня не получается, к сожалению
http://delphimaster.net/view/1-25748/all
Пока зарегистрировать обработчик для моего приложения у меня не получается, к сожалению
Желательно найти цикл самого приложения и запросы делать оттуда. А вообще для этого создавали хуки. В Delphi это было популярное решение.S_Gur писал(а):При том, что хендл приложения я достаю и могу сам отправить ему команду на минимизацию.
С консолью наверно не будет работать. У него не оконное приложение.Seenkao писал(а):Желательно найти цикл самого приложения и запросы делать оттуда. А вообще для этого создавали хуки. В Delphi это было популярное решение.
Вообще странная задача. Ибо недолго оно работать будет. Не под каждой ОС, и до ближайшего обновления ОС. Пока кто то не решит что технология устарела и надо выпендрится.S_Gur писал(а):Shleps, простите, мне сейчас абсолютно неважно, куда пишется лог. Проблема совсем не в этом. Веб-сервер запускается в обычном системном командном окне. Это окно можно минимизировать, максимизировать, перетащить, изменить размер или просто закрыть крестиком. Именно эти системные сообщения (Hide, Restore, Minimize и прочие) мне надо отловить и обработать. При том, что хендл приложения я достаю и могу сам отправить ему команду на минимизацию. Вопрос в том, как к консольному приложению прицепить обработчик этих сообщений. Я сейчас играюсь с примером, описанным по этой ссылке:
https://delphicode.ru/publ/delphi/prim/ ... /4-1-0-116
Sharfik, на Linux возможно не будет. На Windows это обычное окно, потому события перехватываются.
Так в том-то и дело, что если веб-сервер является консольным приложением, то он _не_запускается_в_ окне_. он запускается из шелла, который может быть в окне терминала. А может быть из шелла, не принадлежащего окну терминала вообще. (в случае операционной системы без графической оболочки или с доступом по ssh или в режиме сервиса)S_Gur писал(а):Проблема совсем не в этом. Веб-сервер запускается в обычном системном командном окне. Это окно можно минимизировать, максимизировать, перетащить, изменить размер или просто закрыть крестиком. Именно эти системные сообщения (Hide, Restore, Minimize и прочие) мне надо отловить и обработать. При том, что хендл приложения я достаю и могу сам отправить ему команду на минимизацию. Вопрос в том, как к консольному приложению прицепить обработчик этих сообщений. Я сейчас играюсь с примером, описанным по этой ссылке:
сообщения (Hide, Restore, Minimize и прочие) направлены оконному менеджеру, а не приложению. и учитывая, что оконных менеджеров вагон и маленькая тележка, то это ещё и может быть реализовано по разному. В Gnome2 - metacity, в KDE - уже другой, но вроде все работают по DBUS, а в Astra Linux графическое окружение вообще своё, не похожее ни на GNOME, ни на KDE, ни на LXDE, ни на XFCE.
Добавлено спустя 10 минут 5 секунд:
Если же речь идет сугубо про Windows, то что будет делать консольный вебсервер если пользователь стартует его из оболочки типа FAR, запущенной в окне cmd или powershell (имеет право!)?
это окно будет связано с Far'ом, а не с веб-сервером. Это все к тому, что выбранная архитектура всей системы и вытекающая из неё задача по перехвату сообщений - не совсем здоровые. ну никто так в индустрии не делает - ни апач, ни нгинкс, ни плон.Веб-сервер запускается в обычном системном командном окне. Это окно можно минимизировать, максимизировать, перетащить,
Мне это и надо только для Windows. Задача, собственно, следующая - хочу это окошко минимизировать в трей. В проекте есть датамодуль, на нем сидит трейикон и прекрасно работает, иконка в трее создается. Получается, что у меня есть на текущий момент две задачи: при минимизации окна спрятать его из таскбара, а по щелчку на иконку в трее восстанавливать его. На самом деле это больше не необходимость, а эксперименты. Если программа запускается в фаре, то команды на принудительную минимизацию и восстановление будут просто игнорироваться, но обычное cmd-окно я прекрасно минимизирую, используя sendmessage. Просто хочется разобраться, можно ли такому окну обрабатывать сообщения, и если можно, то как... Меня шибко ломает, почему перехват закрытия окна разными способами, включая Ctrl+C у меня прекрасно работает, а как перехватывать системные сообщения - никак не могу найтиSeenkao писал(а):Linux возможно не будет. На Windows это обычное окно, потому события перехватываются.
Кстати неочевидно, что происходит при нажатии Ctrl+C. то ли приложению отдается сообщение о клавиатурном событии, то ли происходит аналог kill -15(или -9) <ProcessID>, инициированный процессом cmd. Если такое приложение будут снимать через диспетчер задач, то в трее тоже произойдет что-то непредсказуемое.S_Gur писал(а):Меня шибко ломает, почему перехват закрытия окна разными способами, включая Ctrl+C у меня прекрасно работает
В общем-то комбинировать трей, который имеет место быть в графической сессии исключительно и службу/сервис, коим является веб-сервер, которые как правило работают в "безголовом" режиме (машины без мониторов, без графических сессий итд) - это тоже нездоровая идея. Если это какой-то совсем хитрый вебсервер, который например управляет железом или в чьи настройки надо влезать в графическом режиме по локоть для отладки - делают отдельное графическое приложение, которое общается с сервером по отдельному протоколу, и уже оно может иметь трееподобные функции. Так было с толстым клиентом VMWare GSX/ESX или MS IIS.
Shleps, в данном случае дело не в том, что конкретно происходит при нажатии Ctrl+C, а в том, что я прекрасно ловлю это событие. И никак не могу понять, как организовать ловлю других событий
Дело именно в этом. Если Ctrl-C порождает что-то наподобие UNIX-ного сигнала kill -9 - то у приложения нет и не было возможности его ловить. оно просто снимается с исполнения. как при убийстве из диспетчера задач кнопкой "удалить процесс".S_Gur писал(а):Shleps, в данном случае дело не в том, что конкретно происходит при нажатии Ctrl+C, а в том, что я прекрасно ловлю это событие. И никак не могу понять, как организовать ловлю других событий
В отличие от kill -15, где приложению говорят "закрывайся по хорошему: освобождай память, закрывай сокеты, файлы итд" и оно ещё может потрепыхаться
И поскольку подсистема "UNIX для Windows" (точнее POSIX) теперь стала нативной частью винды - отмахаться от архитектуры операционной системы, спрятавшись за своим компилятором теперь не удастся.
