понедельник, 21 марта 2016 г.

Как писать в EventLog?

Админы ко мне тут как-то подходят, окружают, к стенке слегка прижимают с разных сторон и, пристально глядя в глаза, тихим голосом объясняют, что они теперь отвечают за ту программку, которая на старом компе крутится - а там то свет выключат, то ещё что, и им очень неудобно бегать туда и кнопки нажимать для того, чтобы включить комп и залогиниться. Опять же - не сразу им о неприятностях сообщают, а только когда эти неприятности уже прямо неприятными становятся. Это плохо. Раз уж на админов это дело повесили (кто-то наконец догадался это сделать), то админы хотят, чтобы для всего этого не приложение работало, а служба, которая без логина, которая на кластере и вообще гораздо лучше. - Могёшь? - спрашивают. Я говорю, что в принципе-то вроде как есть возможность, не пробовал только ещё... - Вот! - говорят, - Заодно и скилы прокачаешь! Да, прямо так и сказали про скилы. И про логи, я ещё запомнил, что-то говорили.

Ну, службу создать - это как нефиг делать: File|New|Other - Service Application, и вот у меня модуль с наследником от TService, у которого даже есть метод LogMessage - писать в журнал. Только непонятно как.

Недолго погуглив, нахожу я кучу клонов перевода 2005 г. статьи 2002 г. неизвестного автора с "FMI Solutions". Там и знаков в примерах кода не хватает, и вообще Delphi тогда была ещё не юникодная - страшно брать такое.

А вот "Создание служб Windows в Delphi с использованием VCL" Алексеева Александра от 21-05-2008 мне понравилась, хотя там говорилось, что про категории сообщений знать мне ещё рано, т.к. "Для простых служб, которые вы будете писать в начале, это явно излишнее, поэтому разбирательство с категориями можно отложить на потом.

Отложив категории на потом, я выяснил, что прописанные в примере идентификаторы сообщений при передаче в LogMessage не работают. Дело в том, что пример содержит модификаторы номеров сообщений - Severity, Facility, которые вместе с заданным номером сообщения и образуют идентификатор, который надо отдавать в LogMessage. Ещё одно - сообщения, созданные мной просто в редакторе Delphi, отказывались отображаться нормально в Журнале Событий - кодировка Ansi, установленная в редакторе Delphi по умолчанию,  почему-то не пошла. И тут я выяснил, что и не всякая юникодная кодировка подходит, а нужна UTF-16LE. Вот это, пожалуй, главное, что я выяснил сам, не найдя прямых указаний в текстах.

А что же категории? В конце своей статьи Александр дал список ссылок, среди которых нашлась  статья "Пример использования Private Object Security в Delphi" товарища Набережных С. Н., в которой хоть про EventLog нет ничего, зато есть список литературы, в котором указана книга 
  1. Дж.Рихтер, Дж.Кларк, "Программирование серверных приложений для Microsoft Windows 2000", "Питер", ИТД "Русская редакция", 2001 г.
Очень рекомендую эту книжку. Понятным языком там и про категории, и про параметры, и про символьные имена идентификаторов и про то, что читать события из EventLog - это несколько сложнее, чем два байта переслать.

И вот я подумал - а почему бы не показывать события моей службы штатными средствами, с помощью c:\windows\eventvwr.exe, которому какой-то там запрос или имя канала передать надо в командной строке. Я даже нашёл чудную программу C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\ECMangen.exe - Manifest Generator Tool, которая предоставляет графический интерфейс как для создания шаблонов трассировочных сообщений, так и для запросов по Журналу Событий!

Воодушевлённый успехами пошёл я к админам, чтобы блеснуть эрудицией и поинтересоваться тем, как они настраивают перенаправление событий с локальной машины на администраторскую или как они запросы составляют или как каналы сообщений используют. Тут, понятно, выдумывать ничего не надо, а надо спросить у людей, чем они пользуются, и себе куда-нибудь в OnClick вставить ShellExecute с соответствующими параметрами.

- Что?! - Что ты, что ты?! - замахали на меня админы руками - Какой Журнал Событий? Ну его к Лешему, не надо! Пиши просто в файл, и будет нам счастье! А с этим EventLog вообще лучше не связываться!

...

Вот я вам что скажу: если вы вдруг задались вопросом "Как писать в EventLog?", пойдите к  тем, кто этот EventLog по-идее должен читать, и спросите - а надо ли им это?