45832 (665176), страница 2

Файл №665176 45832 (Программирование служб: подробности) 2 страница45832 (665176) страница 22016-07-31СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 2)

Служба завершилась успешно. dwWin32ExitCode = NO_ERROR, в Event Log ничего записано не будет.

Произошла неисправимая ошибка, и это одна из стандартных ошибок Windows. dwWin32ExitCode = ERROR_..., в Event Log будет добавлена запись, описывающая ошибку, числовое значение ошибки указано не будет.

Произошла неисправимая ошибка, специфичная для вашей службы. dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR, в dwServiceSpecificExitCode код ошибки. Так как систему кодирования ошибок вы придумали сами, расшифровать значение кода можете тоже только вы. В Event Log будет добавлена запись следующего содержания: «The ... service terminated with service-specific error ...» (в местах многоточий – имя службы и код ошибки).

Если для завершения службы необходимо выполнить продолжительные действия, в процессе их выполнения имеет смысл посылать уведомления SERVICE_STOP_PENDING. Но это не обязательно.

Ещё один тонкий момент: что будет с вашей службой после вызова SetServiceStatus? Все потоки прекратят исполняться сразу и окончательно, или им дадут «умереть естественной смертью»? Я попытался выяснить это, и получил следующее (это верно для любых вариантов завершения службы, при которых вызывается SetServiceStatus с соответствующими параметрами, кроме случая с SERVICE_CONTROL_SHUTDOWN):

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

После завершения последней службы функция ServiceControlDispatcher возвращает управление в main/WinMain. Если main/WinMain самостоятельно заканчивается в течение 20-ти секунд, то, как и у нормального приложения, выполняется функция ExitProcess() и завершаются все потоки.

ПРЕДУПРЕЖДЕНИЕ

Так как ServiceControlDispatcher возвращает управление в main/WinMain сразу после вызова SetServiceStatus, main/WinMain может вызвать ExitProcess раньше, чем ваш рабочий поток (или потоки, если у вас их несколько) закончат выполнение. В результате, например, могут оказаться невызванными деструкторы стековых объектов. Чтобы избежать этого можно поступить так:

- получить описатель рабочего потока (например, с помошью DuplicateHandle) и сохранить его в глобальной переменной

- в main/WinMain дождаться завершения рабочего потока

Другие (но тоже печальные) возможные последствия преждевременного вызова ExitProcess описаны в MSDN в Q201349: "PRB: ServiceMain thread May Get Terminated in DllMain() when a Service Process Exits Normally".

Большое спасибо Dima2 за это замечание.

Через 20 секунд после завершения последней службы процесс уничтожается.

Свальный грех

В один exe-файл можно поместить несколько служб. Название раздела характеризует моё отношение к таким проектным решениям. Это затрудняет кодирование и отладку, а единственный известный мне выигрыш – экономия ресурсов на компьютере пользователя (если вы пишете несколько зависимых друг от друга служб, наверное, появляются и другие выигрыши; я этим ни разу не занимался). Но, тем не менее, на моей машине в service.exe находятся службы Alerter, AppMgmt, Browser, Dhcp, dmserver, Dnscache, Eventlog, lanmanserver, lanmanworkstation, LmHosts, Messenger, PlugPlay, ProtectedStorage, seclogon, TrkWks, W32Time и Wmi. Вряд ли их писали люди глупее меня.

Интерактивность

Интерактивности в службах следует избегать. Службы предназначены для непрерывной работы в отсутствии пользователей, поэтому дожидаться, пока оператор нажмёт «OK», можно очень долго. Но, тем не менее, возможности есть.

ПРЕДУПРЕЖДЕНИЕ

Учтите, что все описанные в этом разделе методы (а о существовании других я не слышал) позволяют взаимодействовать только с консольной сессией (службы запускаются в консольной сессии, так как в ней запускается SCM). Поэтому интерактивная (в широком смысле этого слова) служба будет некорректно работать в Windows NT/2000 Terminal Service и, что гораздо более важно, в Windows XP при использовании возможности Fast User Switching. То есть, всё будет корректно, но, возможно, не совсем так, как вы ожидали. Рекомендую почитать про Terminal Service (это круто!) и никогда не использовать интерактивность в службах.

Самое простое – отобразить сообщение (MessageBox). Это может любая служба, какие бы флаги не стояли. Для этого нужно в функцию MessageBox[Ex] помимо прочих флагов передать MB_SERVICE_NOTIFICATION или MB_DEFAULT_DESKTOP_ONLY. Первый флаг заставит функцию вывести сообщение на экран, даже если пользователь ещё не вошёл в систему. Выглядит забавно. Представьте: на экране приглашение ввести пароль и десяток сообщений, поздравляющих пользователя с 1 апреля. Но для этого придётся написать десять служб, так как процесс не может отображать на экране несколько таких сообщений одновременно, судя по всему, они ставятся в очередь (к MB_DEFAULT_DESKTOP_ONLY это тоже относится). Если установлен второй флаг, сообщение появится только на «нормальном» рабочем столе. Более строго, MB_SERVICE_NOTIFICATION заставляет сообщение появиться на текущем активном desktop-е, а MB_DEFAULT_DESKTOP_ONLY только на «нормальном». Этими флагами можно пользоваться, если определен макрос _WIN32_WINNT и его значение больше или равно 0x0400.

ПРИМЕЧАНИЕ

Для реализации этой возможности привлечены неслабые средства. В Spy++ видно, что окна (MessageBox) принадлежат одному из потоков CSRSS.EXE. Это имеет забавный побочный эффект: сообщение может висеть на экране даже после завершения приложения. Соберите и запустите такую программку:

.

#define _WIN32_WINNT 0x0500

#include

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

MessageBox(NULL, "try to kill me", "undead", MB_SERVICE_NOTIFICATION);

return 0;

}

.

А теперь попробуйте убить процесс из Task Manager’а. Если сделать несколько потоков, можно проверить ExitProcess, она в этой ситуации тоже не помогает.

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

Служба запущена в контексте безопасности LocalSystem.

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

Значение параметра NoInteractiveServices ключа HKLM\SYSTEM\CurrentControlSet\ Control\Windows\ должно быть равно 0.

Если всё это так, служба может выводить на экран что угодно. Иначе, служба может попробовать самостоятельно открыть и использовать нужный ей desktop. Подобнее об объектах «desktop» и «window station» смотрите в MSDN.

Подробности программирования

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

Отладка

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

В службе будет как минимум два потока.

Службу запускает SCM.

Если в exe-файле несколько служб, отладка будет ещё неприятнее.

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

Присоединить отладчик к запущенной службе.

Использовать DebugBreak.

В HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options добавить ключ «имя_исполяемого_файла.exe» (без пути), в нём создать строковый параметр Debugger и записать в него полное имя отладчика. При запуске указанного файла, он будет запущен под отладчиком.

Использовать SoftIce.

При отладке кода запуска следует помнить, что ограничение на время (30 секунд) никуда не исчезает, если вы не уложитесь, служба завершится.

Администрирование

Обычно у службы есть какие-то параметры, которые можно настраивать. Иногда нужно иметь возможность определять и корректировать текущее состояние службы.

ПРИМЕЧАНИЕ

Изменение состояния и изменение параметров – это не одно и то же. Например, вы написали какую-то сетевую службу. Если есть возможность изменять состояние, администратор может, просмотрев список текущих соединений, какие-то из них разорвать. Изменением параметров этого не достигнуть.

Остановимся на случае не интерактивной службы, так как в интерактивной службе проблему можно решить так же, как и в обычном приложении.

Для администрирования пишется отдельное приложение (далее – конфигуратор), которое каким-то образом взаимодействует со службой. Могу предложить следующие варианты:

Параметры хранятся в реестре (обычно в HKLM\System\CurrentControlSet\Services\имя_службы\Parameters\). Конфигуратор их изменяет, служба, используя функцию RegNotifyChangeKeyValue, отслеживает эти изменения.

Параметры хранятся где угодно. После их изменения конфигуратор посылает службе сообщение. Для этого нужно открыть службу функцией OpenService с правом доступа SERVICE_USER_DEFINED_CONTROL и послать сообщение функцией ControlService. Конечно, в службе необходимо предусмотреть соответствующую обработку.

Используются именованные каналы, сокеты, DCOM или любое другое средство коммуникации между процессами. В этом случае помимо передачи параметров можно получать и изменять состояние службы.

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

Безопасность

Это очень большая тема, про которую я очень мало знаю. Но она имеет прямое отношение к службам, если вы хотите заниматься их разработкой, вам (и мне, естественно) придется с ней разобраться.

Event Log

Интерактивность – это нехорошо. Но служба должна каким-то образом сообщать администратору об ошибках и других важных событиях. Службам, генерирующим несколько десятков (или больше) сообщений в день, целесообразно использовать для этого файлы в формате какой-нибудь СУБД. Для остальных лучшее решение – Event Log. Он достаточно гибок, стандартен, администратор может просмотреть его утилитой Event Viewer.

ПРИМЕЧАНИЕ

Event Log может использоваться любым приложением. Поскольку статья посвящена службам, я использую слово «служба».

Возможности Event Log-а не исчерпываются тем, что описано в этом разделе, но обычно ничего большего и не требуется. Если вам нужно больше, советую обратиться к уже упоминавшейся книге Джеффри Рихтера и Джейсона Кларка «Программирование серверных приложений в Windows 2000» или к MSDN.

Если вы хотите записать сообщение в Event Log, нужно:

создать файл сообщений (при разработке службы);

зарегистрировать в реестре новый источник сообщений (при инсталляции);

собственно записать сообщение.

Файл сообщений

Файл сообщений – это exe- или dll-файл, содержащий ресурс «таблица сообщений». Для получения нужно скомпилировать message compiler’ом (mc.exe) правильно написанный текстовый файл (ниже), получившийся файл ресурсов включить в проект и скомпоновать. Mc.exe не интегрирован в Visual Studio и запускается из командной строки. Ключами можно не пользоваться, достаточно написать «mc filename.mc». На выходе будет filename.h, filename.rc, filenameXXXX.bin (в некоторых случаях несколько штук). filename.rc – тот самый файл ресурсов, он ссылается на filenameXXXX.bin. filename.h содержит идентификаторы сообщений и используется службой.

«Правильно написанный текстовый файл» имеет следующую структуру:

[Заголовок]

сообщение_1

...

сообщение_N

Заголовок необязателен, он может отсутствовать или присутствовать частично. Обычно используется только поле LanguageNames. Синтаксис несложен:

LanguageNames = (обозначение_для_языка_1 = LangID_1 : имя_bin_файла_1)

...

LanguageNames = (обозначение_для_языка_n = LangID_n : имя_bin_файла_n)

«обозначение_для_языка» и «имя_bin_файла» могут быть произвольными, таблица LangID есть в MSDN (смотрите GetLocalInfo()).

Смысл этого поля – перечисление поддерживаемых языков. Если файл сообщений поддерживает несколько языков, в разных локализациях Windows (русской, английской, ...) Event Log будет отображать разные версии сообщений.

Само сообщение выглядит так:

MessageId = 0x1

Severity = Success

Facility = Application

SymbolicName = MSG_COOL_HACK

Language = English

Hi! I hack you! You login: %1, you password: %2.

.

Language = Russian

Привет! Я тебя взломал! Твой логин: %1, твой пароль: %2.

.

Поля «MessageId», «Severity», «Facility» и «SymbolicName» составляют заголовок сообщения.

MessageId

Идентификатор сообщения. Не обязателен, в случае отсутствия инкрементируется MessageId предыдущего сообщения (для первого сообщения MessageId – 0).

Severity

Тип сообщения, определены типы «Success», «Informational», «Warning», и «Error», их названия можно переопределить в заголовке, но на название типа и иконку, отображаемые Event Viewer’ом, это не повлияет. Не обязательно, в случае отсутствия наследуется от предыдущего сообщения, по умолчанию – значение «Success».

Facility

Позволяет задать категорию сообщения. Определены значения «System» и «Application», можно определить (в заголовке файла) ещё около четырёх тысяч. Не обязательно, в случае отсутствия наследуется от предыдущего сообщения, первое сообщение по умолчанию имеет значение «Application».

SymbolicName

Имя соответствующего сообщению макроса в генерируемом h-файле.

Тело сообщения начинается после строки «Language = XXXX» и заканчивается строкой, не содержащей ничего, кроме точки и перевода строки. На каждый определённый в заголовке язык должно быть по одному «телу» (если вы не определили ни одного языка, используйте «English»). Вместо «%1» ... «%99» будут вставлены строки, которые приложение передаст при записи сообщения. Учтите, что этот механизм предназначен для передачи имён файлов, IP-адресов, каких-то чисел и т.д. Но не для передачи текста. Можно, конечно, сделать так:

Language = English

%1

.

но, с моей точки зрения, это плохая идея. Дело в том, что в файлах Event Log-а хранится имя источника, номер сообщения, переданные строки и прикреплённые данные, но не сам текст. Поэтому, если записать сообщение, а потом изменить dll или значение параметра EventMessageFile в реестре, текст изменится. Насколько я знаю, это нужно, чтобы, когда пользователь из Китая, у которого всё на китайском, посылает свой файл с логом (лог, описываемый в этом разделе, находится в WinNT\System32\config\AppEvent.Evt) разработчику из Нигерии, тот мог бы, используя свою dll, прочитать те же сообщения на нигерийском.

Регистрация источника сообщений

Характеристики

Тип файла
Документ
Размер
175,74 Kb
Тип материала
Учебное заведение
Неизвестно

Список файлов реферата

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