Delphi: службы
КОМПЬЮТЕРНЫЕ КУРСЫ «ПОИСК»
Пример проекта службы
Попробуем создать демонстрационный проект простейшего сервиса для ОС Windows NT. Для этого откроем диалоговое окно New Items и на странице New дважды щелкнем по пиктограмме Service Application.
В результате Delphi создаст шаблон проекта службы с одним сервисом.
Начнем работу с конфигурирования сервиса. Для этого выберем модуль Service1 и внесем ряд изменений в его свойства:
Тип сервиса: | ServiceType:=stWin32; |
---|---|
Интерактивность: | Interactive:=true; |
Имя сервиса: | Name:=DemoService; |
Название: | DisplayName:=Демонстрация сервиса; |
Тип старта: | StartType:=stManual; |
Реакция на ошибки при старте: | ErrorSeverity:=esIgnory; |
Сохраните проект в отдельном каталоге, при этом модуль службы назовите DemoSrv.pas, а весь проект – dmsrv.dpr. В секции частных объявлений модуля DemoSrv.pas опишем две переменные:
В момент старта сервиса получаем контекст дисплея и обнуляем счетчик:
Переходим к описанию события OnExecute() сервиса. О факте работы сервиса информируем пользователя текстовой строкой, в которой выводим текущее значение счетчика. Служба остановится в случае, когда счетчик превысит значение 100 или по команде от внешней управляющей программы. Для этого внутри цикла с помощью ProcessRequests() регулярно производим асинхронный опрос менеджера служб на предмет поступления команд от внешних приложений.
Обращаю внимание, что вывод текстовой строки на экран возможен только в случае, когда сервис работает в интерактивном режиме. Событие остановки используем для освобождения дескриптора контекста устройства:
Регистрация службы средствами приложения
Для регистрации службы в операционной системе владеющее службой приложение должно быть запущено из командной строки с ключом /INSTALL. Например:
Для снятия с регистрации применяют ключ /UNINSTALL. Процесс установки сервиса сопровождается выводом уведомляющего сообщения. Для отказа от показа окна уведомления используйте ключ /SILENT. Откройте консоль управления службами компьютера, найдите в ней наш сервис «Демонстрация сервиса» и запустите его на выполнение…
Источник: Д.Осипов — Delphi. Профессиональное программирование.
Исходный код примера здесь. Выполнен на Delphi XE.
Delphi разработка службы windows
Уважаемые знатоки!
Подскажите, если кто занимался:
1. Где можно посмотреть
программирование служб Windows на Delphi с примерами?
Может у вас есть пример?
2. Есть приложение с формой. Как из него сделать службу?
С благодарностью Леонид Федьков.
← →
Сергей М. © ( 2006-08-14 14:50 ) [1]
> приложение с формой. Как из него сделать службу?
Сергею.
Для вывода и просмотра определённых данных, собираемых службой.
← →
Сергей М. © ( 2006-08-14 15:04 ) [3]
Это делается не так.
Реализуется отдельное приложение-служба (безо всяких форм), манипулирующая некими данными.
Реализуется приложение-апплет панели управления (с нужными формами), для вывода и просмотра тех самых «определённых данных».
Взаимодействие между сервисом и апплетом осуществляется любым подходящим и удобным способом — NamedPipes, TCP/IP, MMF, win-сообщения
← →
Сергей М. © ( 2006-08-14 15:05 ) [4]
Переделывать же «одним махом» готовое GUI-приложение в сервис не только нежелательно, но и зачастую невозможно.
Вот те пример. File->New->Other->Service application
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;
type
TService1 = class(TService)
procedure ServiceExecute(Sender: TService);
private
< Private declarations >
public
function GetServiceController: TServiceController; override;
< Public declarations >
end;
var
Service1: TService1;
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
Service1.Controller(CtrlCode);
end;
function TService1.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
procedure TService1.ServiceExecute(Sender: TService);
begin
while not Self.Terminated do
begin
ServiceThread.ProcessRequests(False);
<твои процедуры>
end;
end;
end;
С использованием форм будет много проблем. Почему — RTFM.
Лучше пусть просмотром занимается самостоятельная прога.
← →
Чапаев © ( 2006-08-14 19:57 ) [7]
> win-сообщения
А вот как бы с минимальными усилиями обмениваться сообщениями с делфовым service application? Я ничего лучше не придумал, чем сотворить невидимое окно и ему сообщения слать.
← →
Сергей М. © ( 2006-08-15 08:09 ) [8]
> Чапаев © (14.08.06 19:57) [7]
> ничего лучше не придумал, чем сотворить невидимое окно и
> ему сообщения слать
Не нужно никаких окон.
Сообщение м.б. послано не только окну, но и нити.
См. PostThreadMessage().
Единственное ограничение — асинхронность вышеупомянутой ф-ции.
← →
Чапаев © ( 2006-08-15 09:36 ) [9]
> Не нужно никаких окон.
> Сообщение м.б. послано не только окну, но и нити.
> См. PostThreadMessage().
> Единственное ограничение — асинхронность вышеупомянутой
> ф-ции.
В теории я это знаю, а вот на практике. Как получить хэндл потока службы? Как в обработчик сообщений потока вставить реакцию на пользовательское событие? Речь идёт не о «службе с нуля», а о делфовом service application.
> Единственное ограничение — асинхронность вышеупомянутой
> ф-ции.
Немножко не понял. А оконная функция — синхронна?
> Как получить хэндл потока службы?
Для отправки сообщения нити требуется не хендл, а ID нити.
Нить сервиса может записать свой ID, например, в MMF.
> Как в обработчик сообщений потока вставить реакцию на пользовательское
> событие?
цикл следует организовать примерно так (как вариант) :
while not Terminated do begin
WaitMessage;
if PeekMessage(Msg, -1, TM_FIRST_MSG, TM_TM_LAST_MSG, PM_REMOVE) then
Dispatch(Msg.Message)
else
ProcessRequests(False);
end;
> оконная функция — синхронна?
Не оконная ф-ция, а ф-ция SendMessage().
Она вернет управление после обработки целевым окном посылаемого ему сообщения, в то время как PostThreadMessage() посылает сообщение и тут же возвращает управление.
← →
Ketmar © ( 2006-08-15 09:55 ) [11]
интересно, почему так усиленно игноритуют сокеты, при помощи которых можно очень удобно реализовать это самое общение? плюс — при желании — даже удалённое администрирование сервиса?
← →
Чапаев © ( 2006-08-15 10:09 ) [12]
> Нить сервиса может записать свой ID, например, в MMF.
Так. А MMF — это что?
> цикл следует организовать примерно так
Это понятно. Но как к этому добраться в Service Application?
> Не оконная ф-ция, а ф-ция SendMessage().
Понял. Не сообразил сразу, к чему синхронность относится.
← →
Сергей М. © ( 2006-08-15 10:14 ) [13]
Memory Mapped File
см. CreateFilemapping() + MapViewOfFile()
> как к этому добраться в Service Application?
Подобный цикл должен фигурировать в обработчике TService.OnExecute
← →
Сергей М. © ( 2006-08-15 10:19 ) [14]
> Ketmar © (15.08.06 09:55) [11]>
> интересно, почему так усиленно игноритуют сокеты
Если не требуется удаленное взаимодействие с сервисом, то сокеты тут вряд ли оправданы.
А если и требуется, то при условии гомогенной сет.опер.среды разумнее использовать NamedPipes. Да и в гетерогенной пайпы тоже можно юзать — *nix-системы поддерживают пайп-технологию.
> Memory Mapped File
Ясно. Просто с аббревиатурой не сталкивался. Только вот MMF в данном случае. Не из пушки по воробьям?
> Подобный цикл должен фигурировать в обработчике TService.OnExecute
Ага. Попробую, спасибо.
← →
Сергей М. © ( 2006-08-15 10:36 ) [16]
> MMF в данном случае. Не из пушки по воробьям?
Может и так ..
Но в прогр.реализации это проще, чем иные способы «публикования» подобного рода инф-ции.
Вот еще вариант «публикования» : для главного окна сервис-приложения установить св-во (см. SetProp), являющее собой строку с текстовым представлением ID нити сервиса. Тогда любой процесс того же десктопа может найдя интересующее окно прочитать это св-во (GetProp). Но это оправдано лишь в случае когда сервис-приложение реализует один-единственный сервис, а не множество сервисов (что вполне нормально).
← →
Сергей М. © ( 2006-08-15 10:39 ) [17]
Я бы таки настоятельно рекомендовал для интерпроцессного взаимодействия использовать не механизм win-сообщений, а именованые пайпы.
← →
Чапаев © ( 2006-08-15 11:01 ) [18]
> [17] Сергей М. © (15.08.06 10:39)
Ага. Мне это сразу понравилось, просто раньше не мог додуматься, как в службе читать-писать в канал. Теперь, благодаря твоему примеру, всё прояснилось. 🙂
← →
Ketmar © ( 2006-08-15 14:55 ) [19]
> [14] Сергей М. © (15.08.06 10:19)
да пофигу — что пнём об сову, что совой об пень. для одной и той же машины сокеты сеть не дёргают, так что ничем не хуже пайпов. это вопрос скорее личного вкуса. %-)
← →
Сергей М. © ( 2006-08-15 15:01 ) [20]
> для одной и той же машины сокеты сеть не дёргают
Пайпы тоже не «дергают». Зато не тратят время на работу отнюдь не самых быстрых транспортных протоколов на базе IP
← →
Чапаев © ( 2006-08-15 15:37 ) [21]
В XP, знаю, TCP/IP есть всегда. А в более ранних системах? В 2000, например?
← →
Ketmar © ( 2006-08-15 15:38 ) [22]
> [20] Сергей М. © (15.08.06 15:01)
где-то я читал (точно не скажу уже, где), что вся работа сокетов для локалхоста ограничивается копированием буферов. не уверен, на, кажется, так.
← →
Rouse_ © ( 2006-08-15 16:19 ) [23]
> Ketmar © (15.08.06 14:55) [19]
> > [14] Сергей М. © (15.08.06 10:19)
> да пофигу — что пнём об сову, что совой об пень. для
> одной и той же машины сокеты сеть не дёргают, так что ничем
> не хуже пайпов. это вопрос скорее личного вкуса. %-)
На машине отсутствуют сетевые карты и MSLoopback, или присутствуют, но вместо TCP стоит IPX. Что в данном случае делать будешь?
Я как пару раз наткнулся на такие варианты, сразу отказылся от использования сокетов. Причем такие варианты стояли и в солидных конторах, которые у нас сразу по несколько десятков а то и сотен экземпляров ПО закупили, таким не скажешь — «да у вас админы тупые, настраивайте как надо», это они говорят — мы за что вам такие бешенные деньги платили, за то чтоб еще под ваши требования потом конфигурировать ПО?
← →
Ketmar © ( 2006-08-15 18:12 ) [24]
> [23] Rouse_ © (15.08.06 16:19)
нет, если пишешь за большие деньги и для кого-то — то лучше делать вообще несколько вариантов. TCP, IPX, Pipes (MailSlots? %-). а если для себя — то сокеты рулят. %-)
← →
pasha_golub © ( 2006-08-15 18:35 ) [25]
← →
Чапаев © ( 2006-08-15 18:36 ) [26]
> то лучше делать вообще несколько вариантов
Лучше один сделать.
← →
Чапаев © ( 2006-08-15 18:39 ) [27]
> трубы рулят. :0)
Пока не оказывается, что прога и на 98 винде работать должна. 🙁
← →
pasha_golub © ( 2006-08-15 18:52 ) [28]
> Чапаев © (15.08.06 18:39) [27]
И такое бываеть. У меня на работе один Вин95 еще жив до сих пор.
← →
Ketmar © ( 2006-08-15 18:53 ) [29]
> [27] Чапаев © (15.08.06 18:39)
в 98 сервисов нет. %-)
← →
Чапаев © ( 2006-08-15 19:10 ) [30]
> [29] Ketmar © (15.08.06 18:53)
Нету, конечно. Просто как-то раз, помнится, написал красивое такое взаимодействие клиента и сервера через трубы, а тут — бац! — выясняется, что под 98 это не идёт. Пришлось через сокеты делать.
← →
Ketmar © ( 2006-08-15 19:34 ) [31]
> [30] Чапаев © (15.08.06 19:10)
там ещё и мэйлслоты криво сделаны. %-)
> Чапаев © (15.08.06 19:10) [30]
> такое взаимодействие клиента и сервера через трубы, а тут
> — бац! — выясняется, что под 98 это не идёт.
Дык, его надо б было через безымянную трубу брать.
← →
Чапаев © ( 2006-08-15 19:44 ) [33]
> Дык, его надо б было через безымянную трубу брать.
Что ж. Если ещё такая оказия случится — буду знать. 🙂
← →
Сергей М. © ( 2006-08-16 08:15 ) [34]
> Чапаев © (15.08.06 19:10) [30]
> выясняется, что под 98 это не идёт
Win9x не реализует лишь серверный пайп-механизм, а пайп-клиенты там работают вполне успешно.
← →
Чапаев © ( 2006-08-16 08:48 ) [35]
Я в курсе. Но надо было, чтоб клиент и сервер могли работать как на одной машине, так и на разных. Короче, я про свой конкретный случай, а не про «трубы вообще». 😉
← →
Ketmar © ( 2006-08-16 10:03 ) [36]
> [35] Чапаев © (16.08.06 08:48)
ну вот. «на разных». даёшь сокеты! %-)