![]() |
|
Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply |
![]()
|
|
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
Всем привет,
Как в Delphi можно создать свою службу? Я попробовал сделать с помощью TService, но почему-то ни одно событие не работает(кроме ServiceCreate). |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 9 Всего: 98 |
-------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
Я бы хотел понять почему моим способом не получается сделать? |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 9 Всего: 98 |
каким это "твоим"? ( это раз )
а не работает потому, что что-то делаеш не правильно ( это два ) понять как делать правильно поможет та ссылка ( особенно последний пост ) ( это три ) -------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| ne0n |
|
|||
|
PlayBoy ![]() ![]() Профиль Группа: Участник Сообщений: 733 Регистрация: 5.8.2005 Где: Н.Новгород Репутация: 4 Всего: 11 |
Нарыл статью для написание сервисв под Nt, есть еще очень полезный примерчик!
Надо? |
|||
|
||||
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
Конечно, давай! |
|||
|
||||
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
Сделал как в примере из хелпа в Delphi(Service applications) но сервис все равно через 15 секунд отрубается. Что я неправильно делаю?
|
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 9 Всего: 98 |
что в логах видно?
-------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
Что за логи? |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 9 Всего: 98 |
те, что в Event Viewer' е пишуться...
-------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
В том то и дело что ничего не пишет. |
|||
|
||||
| _hunter |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 8564 Регистрация: 24.6.2003 Где: Europe::Ukraine:: Kiev Репутация: 9 Всего: 98 |
значит ошибок нет. и выходиш ты сам
-------------------- Tempora mutantur, et nos mutamur in illis... |
|||
|
||||
| this |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 98 Регистрация: 12.9.2005 Репутация: нет Всего: 1 |
Все делаю как в примере. А у тебя нет исходников какого-нибудь примера сервиса? |
|||
|
||||
| Poseidon |
|
||||||||||||||||||||
![]() Delphi developer ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 5273 Регистрация: 4.2.2005 Где: Гомель, Беларусь Репутация: 10 Всего: 133 |
Написание сервисов Windows NT на WinAPI
Источник: delphi.xonix.ru Причиной написания этой статьи, как не странно, стала необходимость написания своего сервиса. Но в Borland'е решили немного "порадовать" нас, пользователей Delphi 6 Personal, не добавив возможности создания сервисов (в остальных версиях Delphi 5 и 6 эта возможность имеется в виде класса TService). Решив, что еще не все потеряно, взял на проверку компоненты из одноименного раздела этого сайта. Первый оказался с многочисленными багами, а до пробы второго я не дошел, взглянув на исходник - модуль Forms в Uses это не только окошки, но и более 300 килобайт "веса" программы. Бессмысленного увеличения размера не хотелось и пришлось творить свое. Так как сервис из воздуха не сотворишь, то мой исходник и эта статья очень сильно опираются на MSDN. Итак, приступим к написанию своего сервиса... Обычный Win32-сервис это обычная программа. Программу рекомендуется сделать консольной (DELPHI MENU | Project | Options.. | Linker [X]Generate Console Application) и крайне рекомендуется сделать ее без форм !!! и удалить модуль Forms из Uses. Рекомендуется потому, что, во-первых, это окошко показывать не стоит потому, что оно позволит любому юзеру, прибив ваше окошко прибить и сервис и, во-вторых, конечно же, размер файла (19Kb против 350 ). Поэтому удаляем форму (DELPHI MENU | Project | Remove from project... ). Удалив все формы, перейдем на главный модуль проекта, в котором удаляем текст между begin и end и Forms из Uses и добавляем Windows и WinSvc. В результате должно получиться что-то вроде этого
На этом подготовительный этап закончен - начинаем писАть сервис. Главная часть программы Как уже отмечалось - сервис это обычная программа. Программа в Pascal'е находится между begin и end. После запуска нашего сервиса (здесь и далее под запуском сервиса понимается именно запуск его из Менеджера сервисов, а не просто запуск exe'шника сервиса) менеджер сервисов ждет пока наш сервис вызовет функцию StartServiceCtrlDispatcher.Ждать он будет недолго - если в нашем exe'шнике несколько сервисов то секунд 30, если один - около секунды, поэтому помещаем вызов StartServiceCtrlDispatcher поближе к begin. StartServiceCtrlDispatcher качестве аргумента требует _SERVICE_TABLE_ENTRYA, поэтому добавляем в var DispatchTable : array [0..кол-во сервисов] of _SERVICE_TABLE_ENTRYA; и заполняем этот массив (естественно перед вызовом StartServiceCtrlDispatcher). Т.к. в нашем ехешнике будет 1 сервис, то заполняем его так :
ServiceProc - основная функция сервиса(о ней ниже), а в функцию мы передаем ее адрес. В DispatchTable[кол-во сервисов] все равно nil - это показывает функции, что предыдущее поле было последним. У меня получилось так :
Функция LogError протоколирует ошибки - напишите ее сами.< Функция ServiceMain ServiceMain - основная функция сервиса. Если в ехешнике несколько сервисов, но для каждого сервиса пишется своя ServiceMain функция. Имя функции может быть любым! и передается в DispatchTable.lpServiceProc:=@ServiceMain (см.предыдущущий абзац). У меня она называется ServiceProc и описывается так: procedure ServiceProc(argc : DWORD;var argv : array of PChar);stdcall; argc кол-во аргументов и их массив argv передаются менеджером сервисов из настроек сервиса. НЕ ЗАБЫВАЙТЕ STDCALL!!! Такая забывчивость - частая причина ошибки в программе. В ServiceMain требуется выполнить подготовку к запуску сервиса и зарегистрировать обработчик сообщений от менеджера сервисов (Handler). Опять после запуска ServiceMain и до запуска RegisterServiceCtrlHandler должно пройти минимум времени. Если сервису надо делать что-нибудь очень долго и обязательно до вызова RegisterServiceCtrlHandler, то надо посылать сообщение SERVICE_START_PENDING функией SetServiceStatus. Итак, в RegisterServiceCtrlHandler передаем название нашего сервиса и адрес функции Handler'а (см.далее). Далее выполняем подготовку к запуску и настройку сервиса. Остановимся на настройке поподробнее. Эта самая настройка var ServiceStatus : SERVICE_STATUS; (ServiceStatusHandle : SERVICE_STATUS_HANDLE и ServiceStatus надо сделать глобальными переменными и поместить их выше всех функций). dwServiceType - тип сервиса SERVICE_WIN32_OWN_PROCESS Одиночный сервис SERVICE_WIN32_SHARE_PROCESS Несколько сервисов в одном процессе SERVICE_INTERACTIVE_PROCESS интерактивный сервис (может взаимодействовать с пользователем). Остальные константы - о драйверах. Если надо - смотрите их в MSDN. dwControlsAccepted - принимаемые сообщения (какие сообщения мы будем обрабатывать) SERVICE_ACCEPT_PAUSE_CONTINUE приостановка/перезапуск SERVICE_ACCEPT_STOP остановка сервиса SERVICE_ACCEPT_SHUTDOWN перезагрузка компьютера SERVICE_ACCEPT_PARAMCHANGE изменение параметров сервиса без перезапуска (Win2000 и выше) Остальные сообщения смотрите опять же в MSDN (куда уж без него • dwWin32ExitCode и dwServiceSpecificExitCode - коды ошибок сервиса. Если все идет нормально, то они должны быть равны нулю, иначе коду ошибки. • dwCheckPoint - если сервис выполняет какое-нибудь долгое действие при остановке, запуске и т.д. то dwCheckPoint является индикатором прогресса (увеличивайте его, чтобы дать понять, что сервис не завис), иначе он должен быть равен нулю. • dwWaitHint - время, через которое сервис должен послать свой новый статус менеджеру сервисов при выполнении действия (запуска, остановки и т.д.). Если dwCurrentState и dwCheckPoint через это кол-во миллисекунд не изменится, то менеджер сервисов решит, что произошла ошибка. • dwCurrentState - Ставим его в SERVICE_RUNNING, если сервис запущен После заполнения этой структуры посылаем наш новый статус функцией SetServiceStatus и мы работаем После этого пишем код самого сервиса. Я вернусь к этому попозже. Вот так выглядит моя ServiceMain :
Функция Handler будет вызываться менеджером сервисов при передаче сообщений сервису. Опять же название функции - любое. Адрес функции передается с помощью функции RegisterServiceCtrlHandler (см. выше). Функция имеет один параметр типа DWORD (Cardinal) - сообщение сервису. Если в одном процессе несколько сервисов - для каждого из них должна быть своя функция. procedure ServiceCtrlHandler(Opcode : Cardinal);stdcall; Опять не забываем про stdcall. Итак, функция получает код сообщения, который мы и проверяем. Начинаем вспоминать, что мы писали в ServiceStatus.dwControlsAccepted. У меня это SERVICE_ACCEPT_STOP и SERVICE_ACCEPT_PAUSE_CONTINUE, значит, мне надо проверять сообщения SERVICE_CONTROL_PAUSE, SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_STOP и выполнять соответствующие действия. Остальные сообщения: ServiceStatus.dwControlsAccepted Обрабатываемые сообщения SERVICE_ACCEPT_PAUSE_CONTINUE SERVICE_CONTROL_PAUSE и SERVICE_CONTROL_CONTINUE SERVICE_ACCEPT_STOP SERVICE_CONTROL_STOP SERVICE_ACCEPT_SHUTDOWN SERVICE_CONTROL_SHUTDOWN SERVICE_ACCEPT_PARAMCHANGE SERVICE_CONTROL_PARAMCHANGE Также надо обрабатывать SERVICE_CONTROL_INTERROGATE. Что это такое - непонятно, но обрабатывать надо Пример функции Handler:
В функции ServiceMain (см.там, где отмечено) пишем код сервиса. Так как сервис обычно постоянно находится в памяти компьютера, то скорее всего код будет находиться в цикле. Например в таком :
Но это пройдет если сервис не обрабатывает сообщения приостановки/перезапуска, иначе сервис никак не прореагирует. Другой вариант :
И третий, имхо, самый правильный вариант = использование потока : Пишем функцию
Теперь при приостановке сервиса (в Handler) делаем так
-------------------- Если хочешь, что бы что-то работало - используй написанное, если хочешь что-то понять - пиши сам... |
||||||||||||||||||||
|
|||||||||||||||||||||
| Girder |
|
|||
![]() Лентяй 2 ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1993 Регистрация: 12.5.2004 Репутация: 25 Всего: 155 |
Поиск... и еще раз поиск.
Читай ремарки в коде http://forum.vingrad.ru/index.php?findpost=471413 Добавлено @ 10:50 Poseidon почти все енто есть в нашем факе!!! И в принципе... инфы там более чем достаточно! -------------------- Как слышим, так и пишим. Истина где-то там... |
|||
|
||||
![]()
|
| Правила форума "Delphi: WinAPI и системное программирование" | |
|
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |