45832 (Программирование служб: подробности), страница 3

2016-07-31СтудИзба

Описание файла

Документ из архива "Программирование служб: подробности", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "рефераты, доклады и презентации", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "45832"

Текст 3 страницы из документа "45832"

В ключе реестра HKLM\System\CurrentControlSet\Services\Eventlog\Application\ нужно создать ключ с любым именем (это имя будет именем источника сообщений), в этом ключе создать строковый параметр EventMessageFile и записать в него полный путь к файлу сообщений.

Имя источника сообщений отображается Event Viewer-ом в колонке «Source», оно же используется для получения описателя (handle) при записи в Event Log.

Запись

Для начала нужно получить описатель.

ПРИМЕЧАНИЕ

На вопрос «описатель чего?» я ответить не могу. Просто описатель.… В MSDN сказано так: «If the function succeeds, the return value is a handle that can be used with the ReportEvent function.»

Эту операцию выполняет функция RegisterEventSource. Она выглядит так:

HANDLE RegisterEventSource(

LPCTSTR lpUNCServerName,

LPCTSTR lpSourceName

);

Параметры:

lpUNCServerName

Имя сервера, на котором находится лог. Для записи в лог текущей машины передавайте NULL.

lpSourceName

Имя зарегистрированного источника сообщений.

Для закрытия описателя используется функция DeregisterEventSource.

BOOL DeregisterEventSource(

HANDLE hEventLog

);

Запись сообщения производит функция ReportEvent.

BOOL ReportEvent(

HANDLE hEventLog,

WORD wType,

WORD wCategory,

DWORD dwEventId,

PSID pUserSid,

WORD wNumOfStrings,

DWORD dwDataSize,

LPCTSTR* pStrings,

LPVOID pRawData

);

Параметры:

hEventLog

Описатель, полученный от RegisterEventSource.

wType

Тип сообщения, должен совпадать с типом, записанным в файле сообщений. Варианты: EVENTLOG_SUCCESS, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, EVENTLOG_ERROR_TYPE.

wCategory

Передавайте 0.

dwEventId

Идентификатор сообщения. Не равен «MessageId». Берётся из создаваемого mc.exe заголовочного файла.

pUserSid

Передавайте NULL.

wNumOfStrings

Количество передаваемых строк.

dwDataSize

Размер передаваемых данных.

pStrings

Массив строк. Если строк меньше, чем позиций, в лишних позициях будет «%n», где n – номер позиции.

pRawData

Данные, прикрепляемые к сообщению.

Unicode

Unicode – кодировка, в которой одному символу соответствуют два байта. В результате получается 65536 различных символов. Использовать Unicode в программах для Windows NT/2000/XP полезно и просто. Полезно потому, что, во-первых, это повышает производительность (почему – ниже), во-вторых, позволяет вывести на экран или в файл именно то, что вы хотите, независимо от локализации ОС пользователя и, в-третьих, иногда это гораздо удобнее. А просто потому, что вся необходимая поддержка обеспечена.

Большинство API-функций, принимающих в качестве параметров строки, существуют в двух вариантах – ANSI и Unicode. ANSI-вариант имеет суффикс «A», Unicode-вариант – суффикс «W» (от wide – широкий). В Windows NT/2000/XP ANSI-функции просто преобразуют переданные строки в Unicode и вызывают соответствующую Unicode-функцию. Unicode – «родная» кодировка для этих ОС. Для Win 9x «родная» кодировка – ANSI, в ОС этой группы полностью реализовано всего несколько Unicode-функций, остальные сразу возвращают ошибку. Поэтому программа, использующая Unicode, в Windows NT/2000/XP будет работать быстрее, а в Win 9x не будет работать вообще. Поскольку в Win 9x служба всё равно не сможет работать, это не должно вас волновать.

Если вы не сталкивались с Unicode раньше и не изучали заголовочные файлы с объявлениями API-функций, предыдущий абзац может вас озадачить. Скорее всего, вы неоднократно использовали API-функции, принимающие строки и точно помните, что у них не было никаких суффиксов. А оказывается – есть. Ниже приведёна часть файла winbase.h:

WINADVAPI

BOOL

WINAPI

EncryptFileA(

LPCSTR lpFileName

);

WINADVAPI

BOOL

WINAPI

EncryptFileW(

LPCWSTR lpFileName

);

#ifdef UNICODE

#define EncryptFile EncryptFileW

#else

#define EncryptFile EncryptFileA

#endif // !UNICODE

Если макрос UNICODE определён, вы будете использовать EncryptFileW, в противном случае – EncryptFileA. Так можно менять используемую версию API-функций. Осталось научиться регулировать тип передаваемой строки. Это тоже несложно, достаточно пользоваться типом TCHAR при объявлении строковых и символьных переменных и заключать соответствующие константы внутрь макроса TEXT. И TCHAR, и TEXT определены в tchar.h. Кроме них, в этом файле определёны макросы для функций стандартной библиотеки С. Например, макрос _tscanf разворачивается или как wscanf, или как scanf, в зависимости от макроса UNICODE.

При последовательном употреблении TCHAR, TEXT, _tscanf,.. можно простым изменением настроек переключаться между ANSI и Unicode версиями проекта. Вряд ли вы будете часто пользоваться такой возможностью, но то, что она есть – хорошо.

ПРИМЕЧАНИЕ

Никто не заставляет вас использовать одну и ту же кодировку везде, достаточно просто быть последовательным. Например, модуль, осуществляющий запись в лог-файл, может явно вызывать ANSI-функции (с суффиксом «A») и передавать им char-строки. С таким модулем можно работать, но нужно помнить, что его функциям не стоит передавать TCHAR-строки. Иначе в ANSI-версии проекта это будет работать, а в Unicode-версии даже не скомпилируется. В основной части службы предпочтительнее использовать Unicode.

Мелочи

Здесь собраны факты, знать которые полезно, но не необходимо.

Служба не обязательно является консольным приложением.

В параметре ImagePath ключа HKLM\System\CurrentControlSet\Services\имя_службы можно задать командную строку (можно даже «/uninstall»), но, по-моему, этой возможностью лучше не пользоваться.

Начиная с Windows 2000 в параметре Description ключа HKLM\System\CurrentControl Set\Services\имя_службы можно задать описание службы. Оно отображается Services в столбце «Description». Для установки этого параметра можно воспользоваться RegSetValueEx или ChangeServiceConfig2. Предпочтительнее пользоваться ChangeServiceConfig2, но проще RegSetValueEx…

Судя по всему, пока служба не вызовет StartServiceCtrlDispatcher, SCM не может запустить следующую. Это ещё одна причина не помещать инициализацию в main/WinMain.

После вызова StartServiceCtrlDispatcher основной поток приложения не простаивает. Как минимум, он исполняет обработчики сообщений всех служб exe-файла. Поэтому «задействовано» не три потока, а два.

Когда функция MessageBox вызывается с флагом MB_SERVICE_NOTIFICATION или MD_SERVICE_DEFAULT_DESKTOP_ONLY, в раздел Event Log’а System добавляется запись. Источник – «Application Popup», внутри – содержимое сообщения. Время создания записи соответствует времени вызова функции MessageBox, а не времени отображения сообщения.

Сообщения могут приходить абсолютно бессистемно. То есть, например, несмотря на то, что ваша служба не стоит на паузе, пользователь может (утилитой net.exe или какой-нибудь своей) отправить ей сообщение SERVICE_CONTROL_CONTINUE. Если в результате ваша служба упадёт, он будет очень рад, но уважения к вам у него не прибавится.

Функция CreateProcessW имеет одну особенность – её второй параметр имеет тип LPWSTR, а не LPCWSTR, причём, если этот параметр будет указателем на константу, произойдет исключение. Несмотря на это, в функцию CreateProcessA можно спокойно передавать указатель на константу, так как при преобразовании из ANSI в Unicode она выделяет буфер и передаёт CreateProcessW указатель на него.

Код

В качестве примера я написал небольшую службу, конфигуратор и файл сообщений. Служба почти полностью состоит из стандартной (для меня) обёртки вокруг рабочего потока и может использоваться как заготовка. Краткое описание структуры проекта:

Файл

Описание

Stddef.h

Помимо традиционного включения windows.h, содержит объявления следующих макросов: ServiceName – «внутреннее» имя службы; DisplayName – «отображаемое» имя службы; EventSource – имя источника сообщений; MsgFileName – путь к файлу сообщений из корня службы.

main.cpp

Содержит функцию main – точку входа приложения. Main проверяет командную строку, и в зависимости от её содержимого выполняет следующие действия: /install – пытается инсталлировать службу; /uninstall – пытается удалить службу; что-то иное – выводит справочное сообщение. Если в командной строке ничего нет, предположительно приложение запущено SCM-ом. В этом случае main вызывает функцию для выполнения некой глобальной инициализации, вызывает StartServiceCtrlDispatcher, после возвращения управления вызывает функцию для выполнения глобальной очистки.

Cmdline.h, cmdline.cpp

Функции, вызываемые при обработке командной строки. Это установка/удаление службы, вывод справочного сообщения.

Stdfunc.h, stdfunc.cpp

«Стандартные» функции службы. ServiceMain, ServiceHandler и функции, посылающие SCM сообщения типа «процесс идёт». Наружу выставляются ServiceMain (указатель на неё передаётся в StartServiceCtrlDispatcher) и FatalError, используемая для информирования SCM о внезапном (т.е. не вызванном сообщением SERVICE_CONTROL_SHUTDOWN или SERVICE_CONTROL_STOP) завершении работы службы.

Report.h, report.cpp

Интерфейс к Event Log-у.

Parameters.h, parameters.cpp

Читает из реестра параметры службы.

Work.h, work.cpp

Рабочая часть службы. Содержит функции: GlobalInit – глобальная инициализация; GlobalEnd – глобальная очистка;Init – инициализация конкретной службы;Run – функция, выполняющая основную работу;Stop, Pause, Continue, ParametersChanged – вызываются из ServiceHandler при получении соответствующего сообщения от SCM.

Чтобы создать свою службу, используя этот шаблон, нужно внести следующие изменения:

Файл

Изменение, комментарии

Stddef.h

Изменить значения макросов ServiceName и т.п.

Cmdline.cpp

Если при установке/удалении необходимо выполнить какие-то специфические действия (записать что-то в реестр, и т.п.), нужно реализовать эти самые действия.

Stdfunc.cpp

В этот файл вносятся изменения, если служба должна реагировать на некие сообщения от SCM. В этом случае изменения незначительны: в функции ServiceHandler нужно реализовать соответствующие обработчики, а SetServiceStatus будет вызываться с различными флагами.

Report.h, report.cpp

Поскольку у разных служб разный набор сообщений, в report.h объявляются разные функции. Однако все функции отправки сообщений очень похожи друг на друга, а функции регистрации/дерегистрации источника сообщений просто совпадают.

Parameters.h, parameters.cpp

Скорее всего, у служб различные параметры, поэтому будут отличаться и интерфейс и реализация. Но обычно все параметры получаются каким-то однотипным путём (в одном ключике реестра), причём этот путь может совпадать в различных службах. Т.е. функция получения конкретного параметра может состоять из вызова некоторой промежуточной функции, одинаковой в разных службах.

Work.h, work.cpp

В этом файле реализуется основная логика службы..

На основе такой заготовки можно достаточно быстро сделать простенькую, но работающую службочку. Если нужно разобраться с тем, как эти самые службы работают, или протестировать какую-либо функцию службы (так как службы работают под необычными учётными записями и с использованием необычных WindowStation, некоторые функции могут работать необычно), это очень удобно.

В реальных проектах службы обычно выступают ещё и в роли COM-серверов. Такие службы я рекомендую писать с использованием "ATL COM Wizard". Если же ваша служба не является COM-сервером, или вы по каким-то причинам не переносите ATL… Что ж, можете попробовать использовать нечто подобное и в настоящем проекте. Можете даже взять мой код. Но, как говорится, код предоставляется as is, к сожалению, я написал его уже после завершения «настоящего» проекта, поэтому «в бою» пока не проверял. Заметите ошибки или пути улучшения – пишите, буду благодарен.

Список литературы

Для подготовки данной работы были использованы материалы с сайта http://www.rsdn.ru/

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5168
Авторов
на СтудИзбе
438
Средний доход
с одного платного файла
Обучение Подробнее