<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40376&amp;view=findpost&amp;p=261793</guid>
        <pubDate>Thu, 11 Dec 2003 19:41:59 +0000</pubDate>
        <title>[Раздел] Сервисы</title>
        <link>https://forum.sources.ru/index.php?showtopic=40376&amp;view=findpost&amp;p=261793</link>
        <description><![CDATA[Song: <span class='tag-size' data-value='14' style='font-size:14pt;'>Как запустить и остановить сервис (или получить его статус)</span><br>
<br>
Здесь представлены две функции ServiceStart и ServiceStop, которые показывают, как пользоваться API функциями OpenSCManager, OpenService и т.д.:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">function ServiceStart(aMachine, aServiceName : string ) : boolean; </div><div class="code_line">// aMachine это UNC путь, либо локальный компьютер если пусто</div><div class="code_line">var </div><div class="code_line">&nbsp; h_manager,h_svc: SC_Handle; </div><div class="code_line">&nbsp; svc_status: TServiceStatus; </div><div class="code_line">&nbsp; Temp: PChar; </div><div class="code_line">&nbsp; dwCheckPoint: DWord; </div><div class="code_line">begin </div><div class="code_line">&nbsp; svc_status.dwCurrentState := 1; </div><div class="code_line">&nbsp; h_manager := OpenSCManager(PChar(aMachine), Nil, </div><div class="code_line">&nbsp;                            SC_MANAGER_CONNECT); </div><div class="code_line">&nbsp; if h_manager &#62; 0 then </div><div class="code_line">&nbsp; begin </div><div class="code_line">&nbsp;   h_svc := OpenService(h_manager, PChar(aServiceName), </div><div class="code_line">&nbsp;                        SERVICE_START or SERVICE_QUERY_STATUS); </div><div class="code_line">&nbsp;   if h_svc &#62; 0 then </div><div class="code_line">&nbsp;   begin </div><div class="code_line">&nbsp;     temp := nil; </div><div class="code_line">&nbsp;     if (StartService(h_svc,0,temp)) then </div><div class="code_line">&nbsp;       if (QueryServiceStatus(h_svc,svc_status)) then </div><div class="code_line">&nbsp;       begin </div><div class="code_line">&nbsp;         while (SERVICE_RUNNING &#60;&#62; svc_status.dwCurrentState) do </div><div class="code_line">&nbsp;         begin </div><div class="code_line">&nbsp;           dwCheckPoint := svc_status.dwCheckPoint; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;           Sleep(svc_status.dwWaitHint); </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;           if (not QueryServiceStatus(h_svc,svc_status)) then </div><div class="code_line">&nbsp;             break; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;           if (svc_status.dwCheckPoint &#60; dwCheckPoint) then </div><div class="code_line">&nbsp;           begin </div><div class="code_line">&nbsp;             // QueryServiceStatus не увеличивает dwCheckPoint </div><div class="code_line">&nbsp;             break; </div><div class="code_line">&nbsp;           end; </div><div class="code_line">&nbsp;         end; </div><div class="code_line">&nbsp;       end; </div><div class="code_line">&nbsp;     CloseServiceHandle(h_svc); </div><div class="code_line">&nbsp;   end; </div><div class="code_line">&nbsp;   CloseServiceHandle(h_manager); </div><div class="code_line">&nbsp; end; </div><div class="code_line">&nbsp; Result := SERVICE_RUNNING = svc_status.dwCurrentState; </div><div class="code_line">end; </div><div class="code_line">&nbsp;</div><div class="code_line">function ServiceStop(aMachine,aServiceName : string ) : boolean; </div><div class="code_line">// aMachine это UNC путь, либо локальный компьютер если пусто</div><div class="code_line">var </div><div class="code_line">&nbsp; h_manager,h_svc   : SC_Handle; </div><div class="code_line">&nbsp; svc_status     : TServiceStatus; </div><div class="code_line">&nbsp; dwCheckPoint : DWord; </div><div class="code_line">begin </div><div class="code_line">&nbsp; h_manager:=OpenSCManager(PChar(aMachine),nil, </div><div class="code_line">&nbsp;                          SC_MANAGER_CONNECT); </div><div class="code_line">&nbsp; if h_manager &#62; 0 then </div><div class="code_line">&nbsp; begin </div><div class="code_line">&nbsp;   h_svc := OpenService(h_manager,PChar(aServiceName), </div><div class="code_line">&nbsp;                        SERVICE_STOP or SERVICE_QUERY_STATUS); </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;   if h_svc &#62; 0 then </div><div class="code_line">&nbsp;   begin </div><div class="code_line">&nbsp;     if(ControlService(h_svc,SERVICE_CONTROL_STOP, </div><div class="code_line">&nbsp;                       svc_status))then </div><div class="code_line">&nbsp;     begin </div><div class="code_line">&nbsp;       if(QueryServiceStatus(h_svc,svc_status))then </div><div class="code_line">&nbsp;       begin </div><div class="code_line">&nbsp;         while(SERVICE_STOPPED &#60;&#62; svc_status.dwCurrentState)do </div><div class="code_line">&nbsp;         begin </div><div class="code_line">&nbsp;           dwCheckPoint := svc_status.dwCheckPoint; </div><div class="code_line">&nbsp;           Sleep(svc_status.dwWaitHint); </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;           if(not QueryServiceStatus(h_svc,svc_status))then </div><div class="code_line">&nbsp;           begin </div><div class="code_line">&nbsp;             // couldn&#39;t check status </div><div class="code_line">&nbsp;             break; </div><div class="code_line">&nbsp;           end; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;           if(svc_status.dwCheckPoint &#60; dwCheckPoint)then </div><div class="code_line">&nbsp;             break; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;         end; </div><div class="code_line">&nbsp;       end; </div><div class="code_line">&nbsp;     end; </div><div class="code_line">&nbsp;     CloseServiceHandle(h_svc); </div><div class="code_line">&nbsp;   end; </div><div class="code_line">&nbsp;   CloseServiceHandle(h_manager); </div><div class="code_line">&nbsp; end; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp; Result := SERVICE_STOPPED = svc_status.dwCurrentState; </div><div class="code_line">end; </div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Чтобы узнать состояние сервиса, используйте следующую функцию:<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">function ServiceGetStatus(sMachine, sService: string ): DWord; </div><div class="code_line">var </div><div class="code_line">&nbsp; h_manager,h_service: SC_Handle; </div><div class="code_line">&nbsp; service_status     : TServiceStatus; </div><div class="code_line">&nbsp; hStat : DWord; </div><div class="code_line">begin </div><div class="code_line">&nbsp; hStat := 1; </div><div class="code_line">&nbsp; h_manager := OpenSCManager(PChar(sMachine) ,Nil, </div><div class="code_line">&nbsp;                            SC_MANAGER_CONNECT); </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp; if h_manager &#62; 0 then </div><div class="code_line">&nbsp; begin </div><div class="code_line">&nbsp;   h_svc := OpenService(h_manager,PChar(sService), </div><div class="code_line">&nbsp;                     SERVICE_QUERY_STATUS); </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;   if h_svc &#62; 0 then </div><div class="code_line">&nbsp;   begin </div><div class="code_line">&nbsp;     if(QueryServiceStatus(h_svc, service_status)) then </div><div class="code_line">&nbsp;       hStat := service_status.dwCurrentState; </div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;     CloseServiceHandle(h_svc); </div><div class="code_line">&nbsp;   end; </div><div class="code_line">&nbsp;   CloseServiceHandle(h_manager); </div><div class="code_line">&nbsp; end; </div><div class="code_line">&nbsp; Result := hStat; </div><div class="code_line">end; </div></ol></div></div></div></div><br>
<br>
Она возвращает одну из следующих констант:<br>
<br>
SERVICE_STOPPED <br>
SERVICE_RUNNING <br>
SERVICE_PAUSED <br>
SERVICE_START_PENDING <br>
SERVICE_STOP_PENDING <br>
SERVICE_CONTINUE_PENDING <br>
или<br>
SERVICE_PAUSE_PENDING <br>
<br>
Всё что, что Вам нужно, это unit WinSvc &#33;]]></description>
        <author>Song</author>
        <category>Системные функции, WinAPI, работа с железом</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=40376&amp;view=findpost&amp;p=261787</guid>
        <pubDate>Thu, 11 Dec 2003 19:29:40 +0000</pubDate>
        <title>[Раздел] Сервисы</title>
        <link>https://forum.sources.ru/index.php?showtopic=40376&amp;view=findpost&amp;p=261787</link>
        <description><![CDATA[Song: [doHTML]&lt;table width=&quot;680&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;<br>  &lt;tr&gt;<br>    &lt;td&gt;&lt;hr&gt;<br>    &lt;h3&gt;Написание сервисов Windows NT на WinAPI&lt;/h3&gt;<br>    &lt;p&gt;Источник: &lt;a<br>    href=&quot;http://delphi.xonix.ru/&quot;&gt;delphi.xonix.ru&lt;/a&gt;&lt;/p&gt;<br>    &lt;p&gt;Причиной написания этой статьи, как не странно,<br>    стала необходимость написания своего сервиса. Но<br>    в Borland&#39;е решили немного &quot;порадовать&quot; нас,<br>    пользователей Delphi 6 Personal, не добавив возможности<br>    создания сервисов (в остальных версиях Delphi 5 и 6<br>    эта возможность имеется в виде класса TService).<br>    Решив, что еще не все потеряно, взял на проверку<br>    компоненты из одноименного раздела этого сайта.<br>    Первый оказался с многочисленными багами, а до<br>    пробы второго я не дошел, взглянув на исходник -<br>    модуль Forms в Uses это не только окошки, но и более 300<br>    килобайт &quot;веса&quot; программы. Бессмысленного<br>    увеличения размера не хотелось и пришлось<br>    творить свое.&lt;br&gt;<br>    Так как сервис из воздуха не сотворишь, то мой<br>    исходник и эта статья очень сильно опираются на<br>    MSDN. &lt;/p&gt;<br>    &lt;p align=&quot;center&quot;&gt;&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;p&gt;Итак, приступим к написанию своего сервиса...&lt;br&gt;<br>    Обычный Win32-сервис это обычная программа.<br>    Программу рекомендуется сделать консольной &lt;u&gt;&lt;nobr&gt;(DELPHI<br>    MENU | Project | Options.. | Linker [X]Generate Console Application)&lt;/nobr&gt;&lt;/u&gt; и<br>    крайне рекомендуется сделать ее &lt;b&gt;без форм &lt;/b&gt;&#33;&#33;&#33; и &lt;b&gt;удалить<br>    модуль Forms&lt;/b&gt; из Uses. Рекомендуется потому, что,<br>    во-первых, это окошко показывать не стоит потому,<br>    что оно позволит любому юзеру, прибив ваше окошко<br>    прибить и сервис и, во-вторых, конечно же, размер<br>    файла (19Kb против 350 ). Поэтому удаляем форму &lt;nobr&gt;(&lt;u&gt;DELPHI<br>    MENU | Project | Remove from project...&lt;/u&gt; )&lt;/nobr&gt;. Удалив все формы,<br>    перейдем на главный модуль проекта, в котором<br>    удаляем текст между begin и end и Forms из Uses и добавляем<br>    Windows и WinSvc. В результате должно получиться что-то<br>    вроде этого&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;pre&gt;program Project1;<br><br>uses<br> Windows,WinSvc;<br><br>{&#036;R *.res}<br><br>begin<br><br>end.<br>&lt;/pre&gt;<br>    &lt;p&gt;На этом подготовительный этап закончен -<br>    начинаем писАть сервис.&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;table width=&quot;100%&quot; align=&quot;center&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;&lt;font class=&quot;subheader&quot;&gt;Главная часть программы&lt;/font&gt;&lt;/td&gt;<br>      &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>    &lt;/table&gt;<br>    &lt;p&gt;Как уже отмечалось - сервис это обычная<br>    программа. Программа в Pascal&#39;е находится между begin и<br>    end. После запуска нашего сервиса (здесь и далее<br>    под запуском сервиса понимается именно запуск<br>    его из Менеджера сервисов, а не просто запуск<br>    exe&#39;шника сервиса) менеджер сервисов ждет пока наш<br>    сервис вызовет функцию StartServiceCtrlDispatcher.Ждать он<br>    будет недолго - если в нашем exe&#39;шнике несколько<br>    сервисов то секунд 30, если один - около секунды,<br>    поэтому помещаем вызов &lt;b&gt;StartServiceCtrlDispatcher&lt;/b&gt;<br>    поближе к begin. &lt;br&gt;<br>    &lt;br&gt;<br>    StartServiceCtrlDispatcher качестве аргумента требует &lt;b&gt;_SERVICE_TABLE_ENTRYA&lt;/b&gt;,<br>    поэтому добавляем в var &lt;i&gt;DispatchTable : array [0..кол-во<br>    сервисов] of _SERVICE_TABLE_ENTRYA;&lt;/i&gt; и заполняем этот<br>    массив (естественно перед вызовом<br>    StartServiceCtrlDispatcher).&lt;br&gt;<br>    &lt;br&gt;<br>    Т.к. в нашем ехешнике будет 1 сервис, то заполняем<br>    его так :&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;pre&gt; DispatchTable[0].lpServiceName:=ServiceName;<br> DispatchTable[0].lpServiceProc:=@ServiceProc;<br><br> DispatchTable[1].lpServiceName:=nil;<br> DispatchTable[1].lpServiceProc:=nil;<br>&lt;/pre&gt;<br>    &lt;p&gt;Советую завести константы ServiceName - имя сервиса и<br>    ServiceDisplayName - отображаемое имя.&lt;br&gt;<br>    ServiceProc - основная функция сервиса(о ней ниже), а в<br>    функцию мы передаем ее адрес.&lt;br&gt;<br>    В DispatchTable[кол-во сервисов] все равно nil - это<br>    показывает функции, что предыдущее поле было<br>    последним. У меня получилось так :&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;pre&gt;&lt;i&gt;begin<br> DispatchTable[0].lpServiceName:=ServiceName;<br> DispatchTable[0].lpServiceProc:=@ServiceProc;<br><br> DispatchTable[1].lpServiceName:=nil;<br> DispatchTable[1].lpServiceProc:=nil;<br><br> if not StartServiceCtrlDispatcher(DispatchTable[0])<br>  then LogError(&#39;StartServiceCtrlDispatcher Error&#39;);<br>end.&lt;/i&gt;&lt;/pre&gt;<br>    &lt;p&gt;&lt;br&gt;<br>    StartServiceCtrlDispatcher выполнится только после того, как<br>    все сервисы будут остановлены.&lt;br&gt;<br>    &lt;br&gt;<br>    Функция LogError протоколирует ошибки - напишите ее<br>    сами.&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;table width=&quot;100%&quot; align=&quot;center&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;&lt;font class=&quot;subheader&quot;&gt;Функция ServiceMain&lt;/font&gt;&lt;/td&gt;<br>      &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>    &lt;/table&gt;<br>    &lt;p&gt;&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;p&gt;ServiceMain - основная функция сервиса. Если в<br>    ехешнике несколько сервисов, но для каждого<br>    сервиса пишется своя ServiceMain функция. Имя функции<br>    может быть любым&#33; и передается в<br>    DispatchTable.lpServiceProc:=@ServiceMain (см.предыдущущий абзац). У<br>    меня она называется ServiceProc и описывается так:&lt;br&gt;<br>    &lt;i&gt;procedure ServiceProc(argc : DWORD;var argv : array of PChar);&lt;b&gt;stdcall;&lt;/b&gt;&lt;/i&gt;&lt;br&gt;<br>    argc кол-во аргументов и их массив argv передаются<br>    менеджером сервисов из настроек сервиса. НЕ<br>    ЗАБЫВАЙТЕ STDCALL&#33;&#33;&#33; Такая забывчивость - частая<br>    причина ошибки в программе.&lt;br&gt;<br>    &lt;br&gt;<br>    В ServiceMain требуется выполнить подготовку к<br>    запуску сервиса и зарегистрировать обработчик<br>    сообщений от менеджера сервисов (Handler). Опять<br>    после запуска ServiceMain и до запуска &lt;b&gt;RegisterServiceCtrlHandler&lt;/b&gt;<br>    должно пройти минимум времени. Если сервису надо<br>    делать что-нибудь очень долго и обязательно до<br>    вызова RegisterServiceCtrlHandler, то надо посылать сообщение<br>    &lt;b&gt;SERVICE_START_PENDING&lt;/b&gt; функией &lt;b&gt;SetServiceStatus&lt;/b&gt;.&lt;br&gt;<br>    &lt;br&gt;<br>    Итак, в RegisterServiceCtrlHandler передаем название нашего<br>    сервиса и адрес функции Handler&#39;а (см.далее). Далее<br>    выполняем подготовку к запуску и настройку<br>    сервиса. Остановимся на настройке поподробнее.&lt;br&gt;<br>    Эта самая настройка &lt;i&gt;&lt;b&gt;var&lt;/b&gt; ServiceStatus : SERVICE_STATUS; &lt;/i&gt;&lt;br&gt;<br>    (ServiceStatusHandle : SERVICE_STATUS_HANDLE и ServiceStatus надо сделать<br>    глобальными переменными и поместить их выше всех<br>    функций).&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;table width=&quot;80%&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>      &lt;tr bgColor=&quot;#c2ccff&quot;&gt;<br>        &lt;td colSpan=&quot;2&quot;&gt;&lt;b&gt;dwServiceType&lt;/b&gt; - тип сервиса&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;SERVICE_WIN32_OWN_PROCESS&lt;/td&gt;<br>        &lt;td&gt;Одиночный сервис&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr&gt;<br>        &lt;td&gt;SERVICE_WIN32_SHARE_PROCESS&lt;/td&gt;<br>        &lt;td&gt;Несколько сервисов в одном процессе&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;SERVICE_INTERACTIVE_PROCESS&lt;/td&gt;<br>        &lt;td&gt;интерактивный сервис (может взаимодействовать<br>        с пользователем).&lt;/td&gt;<br>      &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>    &lt;/table&gt;<br>    &lt;p&gt;Остальные константы - о драйверах. Если надо -<br>    смотрите их в MSDN.&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;table width=&quot;80%&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>      &lt;tr bgColor=&quot;#c2ccff&quot;&gt;<br>        &lt;td colSpan=&quot;2&quot;&gt;&lt;b&gt;dwControlsAccepted&lt;/b&gt; - принимаемые сообщения<br>        (какие сообщения мы будем обрабатывать) &lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_PAUSE_CONTINUE&lt;/td&gt;<br>        &lt;td&gt;приостановка/перезапуск&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_STOP&lt;/td&gt;<br>        &lt;td&gt;остановка сервиса&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_SHUTDOWN&lt;/td&gt;<br>        &lt;td&gt;перезагрузка компьютера&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_PARAMCHANGE&lt;/td&gt;<br>        &lt;td&gt;изменение параметров сервиса без перезапуска<br>        (Win2000 и выше)&lt;/td&gt;<br>      &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>    &lt;/table&gt;<br>    &lt;p&gt;Остальные сообщения смотрите опять же в MSDN<br>    (куда уж без него ;-)&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;b&gt;dwWin32ExitCode&lt;/b&gt; и &lt;b&gt;dwServiceSpecificExitCode&lt;/b&gt; - коды ошибок<br>    сервиса. Если все идет нормально, то они должны<br>    быть равны нулю, иначе коду ошибки.&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;b&gt;dwCheckPoint&lt;/b&gt; - если сервис выполняет какое-нибудь<br>    долгое действие при остановке, запуске и т.д. то<br>    dwCheckPoint является индикатором прогресса<br>    (увеличивайте его, чтобы дать понять, что сервис<br>    не завис), иначе он должен быть равен нулю.&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;b&gt;dwWaitHint&lt;/b&gt; - время, через которое сервис должен<br>    послать свой новый статус менеджеру сервисов при<br>    выполнении действия (запуска, остановки и т.д.).<br>    Если dwCurrentState и dwCheckPoint через это кол-во<br>    миллисекунд не изменится, то менеджер сервисов<br>    решит, что произошла ошибка.&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;b&gt;dwCurrentState&lt;/b&gt; - см. где-то &lt;a href=&quot;?id=serviceinfo&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;<br>    Ставим его в SERVICE_RUNNING, если сервис запущен&lt;br&gt;<br>    &lt;br&gt;<br>    После заполнения этой структуры посылаем наш<br>    новый статус функцией SetServiceStatus и мы работаем :).&lt;br&gt;<br>    &lt;br&gt;<br>    После этого пишем код самого сервиса. Я вернусь к<br>    этому попозже.&lt;br&gt;<br>    Вот так выглядит моя ServiceMain :&lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;pre&gt;procedure ServiceProc(argc : DWORD;var argv : array of PChar);stdcall;<br>var<br> Status : DWORD;<br> SpecificError : DWORD;<br>begin<br>  ServiceStatus.dwServiceType      := SERVICE_WIN32;<br>  ServiceStatus.dwCurrentState     := SERVICE_START_PENDING;<br>  ServiceStatus.dwControlsAccepted := SERVICE_ACCEPT_STOP <br>    or SERVICE_ACCEPT_PAUSE_CONTINUE;<br>  ServiceStatus.dwWin32ExitCode           := 0;<br>  ServiceStatus.dwServiceSpecificExitCode := 0;<br>  ServiceStatus.dwCheckPoint              := 0;<br>  ServiceStatus.dwWaitHint                := 0;<br><br>  ServiceStatusHandle := <br>           RegisterServiceCtrlHandler(ServiceName,@ServiceCtrlHandler);<br>  if ServiceStatusHandle = 0 then WriteLn(&#39;RegisterServiceCtrlHandler Error&#39;);<br><br>  Status :=ServiceInitialization(argc,argv,SpecificError);<br>  if Status &lt;&gt; NO_ERROR<br>   then begin<br>    ServiceStatus.dwCurrentState := SERVICE_STOPPED;<br>    ServiceStatus.dwCheckPoint   := 0;<br>    ServiceStatus.dwWaitHint     := 0;<br>    ServiceStatus.dwWin32ExitCode:=Status;<br>    ServiceStatus.dwServiceSpecificExitCode:=SpecificError;<br><br>    SetServiceStatus (ServiceStatusHandle, ServiceStatus);<br>	LogError(&#39;ServiceInitialization&#39;);<br>    exit;<br>   end;<br><br>   ServiceStatus.dwCurrentState :=SERVICE_RUNNING;<br>   ServiceStatus.dwCheckPoint   :=0;<br>   ServiceStatus.dwWaitHint     :=0;<br><br>   if not SetServiceStatus (ServiceStatusHandle,ServiceStatus)<br>    then begin<br>     Status:=GetLastError;<br>	 LogError(&#39;SetServiceStatus&#39;);<br>     exit;<br>    end;<br>  // WORK HERE <br>  //ЗДЕСЬ БУДЕТ ОСНОВНОЙ КОД ПРОГРАММЫ<br>end;&lt;/pre&gt;<br>    &lt;p&gt;&lt;br&gt;<br>&#60;&#33;-- Part 5 --&#62;    &lt;/p&gt;<br>    &lt;table width=&quot;100%&quot; align=&quot;center&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;&lt;font class=&quot;subheader&quot;&gt;Функция Handler&lt;/font&gt;&lt;/td&gt;<br>      &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>    &lt;/table&gt;<br>    &lt;p&gt;Функция Handler будет вызываться менеджером<br>    сервисов при передаче сообщений сервису. Опять<br>    же название функции - любое. Адрес функции<br>    передается с помощью функции RegisterServiceCtrlHandler (см.<br>    выше). Функция имеет один параметр типа DWORD (Cardinal) -<br>    сообщение сервису. Если в одном процессе<br>    несколько сервисов - для каждого из них должна<br>    быть своя функция.&lt;br&gt;<br>    &lt;i&gt;procedure ServiceCtrlHandler(Opcode : Cardinal);&lt;b&gt;stdcall;&lt;/b&gt;&lt;/i&gt;&lt;br&gt;<br>    Опять не забываем про stdcall.&lt;br&gt;<br>    &lt;br&gt;<br>    Итак, функция получает код сообщения, который мы<br>    и проверяем. Начинаем вспоминать, что мы писали в<br>    ServiceStatus.dwControlsAccepted. У меня это SERVICE_ACCEPT_STOP и<br>    SERVICE_ACCEPT_PAUSE_CONTINUE, значит, мне надо проверять<br>    сообщения SERVICE_CONTROL_PAUSE, SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_STOP<br>    и выполнять соответствующие действия. Остальные<br>    сообщения:&lt;br&gt;<br>    &lt;br&gt;<br>    &lt;/p&gt;<br>    &lt;table width=&quot;80%&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>      &lt;tr bgColor=&quot;#c2ccff&quot;&gt;<br>        &lt;td&gt;&lt;b&gt;ServiceStatus.dwControlsAccepted&lt;/b&gt;&lt;/td&gt;<br>        &lt;td&gt;&lt;b&gt;Обрабатываемые сообщения&lt;/b&gt;&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_PAUSE_CONTINUE&lt;/td&gt;<br>        &lt;td&gt;SERVICE_CONTROL_PAUSE и SERVICE_CONTROL_CONTINUE &lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_STOP&lt;/td&gt;<br>        &lt;td&gt;SERVICE_CONTROL_STOP&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_SHUTDOWN&lt;/td&gt;<br>        &lt;td&gt;SERVICE_CONTROL_SHUTDOWN&lt;/td&gt;<br>      &lt;/tr&gt;<br>      &lt;tr&gt;<br>        &lt;td&gt;SERVICE_ACCEPT_PARAMCHANGE&lt;/td&gt;<br>        &lt;td&gt;SERVICE_CONTROL_PARAMCHANGE&lt;/td&gt;<br>      &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>    &lt;/table&gt;<br><br>&lt;br&gt;<br>  &lt;p&gt;Также надо обрабатывать SERVICE_CONTROL_INTERROGATE. Что это<br>  такое - непонятно, но обрабатывать надо :)<br>  Передаем новый статус сервиса менеджеру<br>  сервисов функцией SetServiceStatus.&lt;br&gt;<br>  &lt;br&gt;<br>  Пример функции Handler:&lt;br&gt;<br>  &lt;br&gt;<br>  &lt;/p&gt;<br>  &lt;pre&gt;procedure ServiceCtrlHandler(Opcode : Cardinal);stdcall;<br>var<br> Status : Cardinal;<br>begin<br> case Opcode of<br>  SERVICE_CONTROL_PAUSE    :<br>   begin<br>    ServiceStatus.dwCurrentState := SERVICE_PAUSED;<br>    end;<br>  SERVICE_CONTROL_CONTINUE :<br>   begin<br>    ServiceStatus.dwCurrentState := SERVICE_RUNNING;<br>   end;<br>  SERVICE_CONTROL_STOP     :<br>   begin<br>    ServiceStatus.dwWin32ExitCode:=0;<br>    ServiceStatus.dwCurrentState := SERVICE_STOPPED;<br>    ServiceStatus.dwCheckPoint   :=0;<br>    ServiceStatus.dwWaitHint     :=0;<br><br>    if not SetServiceStatus (ServiceStatusHandle,ServiceStatus)<br>     then begin<br>      Status:=GetLastError;<br>	  LogError(&#39;SetServiceStatus&#39;);<br>      Exit;<br>     end;<br>     exit;<br>   end;<br><br>  SERVICE_CONTROL_INTERROGATE : ;<br> end;<br><br> if not SetServiceStatus (ServiceStatusHandle, ServiceStatus)<br>  then begin<br>   Status := GetLastError;<br>   LogError(&#39;SetServiceStatus&#39;);<br>   Exit;<br>  end;<br>end;<br>&lt;/pre&gt;<br>  &lt;p&gt;&nbsp;&lt;/p&gt;<br>  &lt;table width=&quot;100%&quot; align=&quot;center&quot; border=&quot;1&quot;&gt;<br>&lt;TBODY&gt;<br>    &lt;tr bgColor=&quot;#ffffff&quot;&gt;<br>      &lt;td&gt;&lt;font class=&quot;subheader&quot;&gt;Реализация главной функции<br>      программы&lt;/font&gt;&lt;/td&gt;<br>    &lt;/tr&gt;<br>&lt;/TBODY&gt;<br>  &lt;/table&gt;<br>  &lt;p&gt;&lt;br&gt;<br>  &lt;/p&gt;<br>  &lt;p&gt;В функции ServiceMain (см.там, где отмечено) пишем код<br>  сервиса. Так как сервис обычно постоянно<br>  находится в памяти компьютера, то скорее всего<br>  код будет находиться в цикле. Например в таком :&lt;br&gt;<br>  &lt;br&gt;<br>  &lt;/p&gt;<br>  &lt;pre&gt;repeat<br> Что-нибудь делаем пока сервис не завершится.<br>until ServiceStatus.dwCurrentState = SERVICE_STOPPED;<br>&lt;/pre&gt;<br>  &lt;p&gt;Но это пройдет если сервис не обрабатывает<br>  сообщения приостановки/перезапуска, иначе<br>  сервис никак не прореагирует. Другой вариант :&lt;br&gt;<br>  &lt;/p&gt;<br>  &lt;pre&gt;repeat <br> if ServiceStatus.dwCurrentState &lt;&gt; SERVICE_PAUSED<br>  then чего-то делаем<br>until ServiceStatus.dwCurrentState = SERVICE_STOPPED; <br>&lt;/pre&gt;<br>  &lt;p&gt;И третий, имхо, самый правильный вариант =<br>  использование потока :&lt;br&gt;<br>  Пишем функцию &lt;/p&gt;<br>  &lt;pre&gt;function MainServiceThread(p:Pointer):DWORD;stdcall;<br>begin<br> что-то делаем<br>end;  <br>&lt;/pre&gt;<br>  &lt;p&gt;и в ServiceMain создаем поток &lt;/p&gt;<br>  &lt;pre&gt;var<br> ThID : Cardinal;<br>  <br>hThread:=CreateThread(nil,0,@MainServiceThread,nil,0,ThID);<br>и ждем его завершения<br>WaitForSingleObject(hThread,INFINITE);<br>закрывая после этого его дескриптор<br>CloseHandle(hThread);<br>&lt;/pre&gt;<br>  &lt;p&gt;При этом hThread делаем глобальной переменной.&lt;br&gt;<br>  Теперь при приостановке сервиса (в Handler) делаем<br>  так &lt;/p&gt;<br>  &lt;pre&gt;  SERVICE_CONTROL_PAUSE    :<br>   begin<br>    ServiceStatus.dwCurrentState := SERVICE_PAUSED;<br>    SuspendThread(hThread); // приостанавливаем поток<br>   end;&lt;/pre&gt;<br>  &lt;p&gt;и при возобновлении работы сервиса &lt;/p&gt;<br>  &lt;pre&gt;  SERVICE_CONTROL_CONTINUE :<br>   begin<br>    ServiceStatus.dwCurrentState := SERVICE_RUNNING;<br>    ResumeThread(hThread); // возобновляем поток<br>   end;&lt;/pre&gt;<br>  &lt;p&gt;&lt;br&gt;<br>  &lt;/p&gt;<br>  &lt;p&gt;&nbsp;&lt;/p&gt;<br>    &lt;/td&gt;<br>  &lt;/tr&gt;<br>&lt;/table&gt;[/doHTML]]]></description>
        <author>Song</author>
        <category>Системные функции, WinAPI, работа с железом</category>
      </item>
	
      </channel>
      </rss>
	