Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.11.17;
Скачать: CL | DM;

Вниз

Сервис в Win2K   Найти похожие ветки 

 
lds   (2003-10-23 11:07) [0]

Как на API написать сервис, ясенно не используя компонент TService?


 
Polevi ©   (2003-10-23 11:27) [1]

program someservice;

{$APPTYPE CONSOLE}

uses
SysUtils,
Windows,
WinSvc;

const
FServiceName:string="Some service";

var
FStatusHandle:THandle;
T:TSomeThread;
FLastStatus:DWORD;

procedure SetStatus(AStatus:DWORD);
var
st:TServiceStatus;
begin
st.dwServiceType:=SERVICE_WIN32_OWN_PROCESS;
st.dwCurrentState:=AStatus;
st.dwControlsAccepted:=SERVICE_ACCEPT_STOP;
st.dwWin32ExitCode:=NO_ERROR;
st.dwServiceSpecificExitCode:=0;
if (AStatus=SERVICE_START_PENDING) or (AStatus=SERVICE_STOP_PENDING) then
begin
st.dwCheckPoint:=1;
st.dwWaitHint:=1000;
end
else
begin
st.dwCheckPoint:=0;
st.dwWaitHint:=0;
end;
FLastStatus:=AStatus;
SetServiceStatus(FStatusHandle,st);
end;

procedure ServiceHandler(CtrlCode: DWord); stdcall;
begin
if CtrlCode=(SERVICE_CONTROL_STOP) then
begin
SetStatus(SERVICE_STOP_PENDING);
T.Stop;
end
else
SetStatus(FLastStatus);
end;

procedure ServiceMain(Argc: DWord; Argv: PLPSTR); stdcall;
begin
FStatusHandle:=RegisterServiceCtrlHandler(PChar(FServiceName),@ServiceHandler);
if (FStatusHandle <> 0) then
begin
try
SetStatus(SERVICE_RUNNING);
T:=TSomeThread.Create(false);
T.WaitFor;
finally
SetStatus(SERVICE_STOPPED);
end;
end;
end;

function InstallService:boolean;
var
scm,serv:THandle;
begin
scm:=OpenSCManager(nil,nil,SC_MANAGER_CREATE_SERVICE);
serv:=CreateService(scm,PChar(FServiceName),PChar(FServiceName),SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,SERVICE_DEMAND_START,SERVICE_ERROR_IGNORE,
PChar(ParamStr(0)),nil,nil,nil,nil,nil);
Result:=serv<>0;
if Result then CloseServiceHandle(serv);
end;

procedure RemoveService;
var
scm,serv:THandle;
begin
scm:=OpenSCManager(nil,nil,SC_MANAGER_CONNECT);
serv:=OpenService(scm,PChar(FServiceName),SERVICE_ALL_ACCESS);
try
DeleteService(serv);
finally
CloseServiceHandle(serv);
end;
end;

var
ste:TServiceTableEntry;
s:string;
begin
{ TODO -oUser -cConsole Main : Insert code here }
if FindCmdLineSwitch("INSTALL",["-","\","/"], True) then
InstallService
else
if FindCmdLineSwitch("UNINSTALL",["-","\","/"], True) then
RemoveService
else
begin
ste.lpServiceName:=PChar(FServiceName);
ste.lpServiceProc:=@ServiceMain;
StartServiceCtrlDispatcher(ste);
end;
end.


 
lds   (2003-10-27 07:11) [2]

Чего-то не хочет он запускаться... Пишет, что функция не возвратила результата...


 
Юрий Зотов ©   (2003-10-27 14:32) [3]

var
ste: array[0..1] of TServiceTableEntry;

ste[0].lpServiceName:=PChar(FServiceName);
ste[0].lpServiceProc:=@ServiceMain;
ste[1].lpServiceName:=nil;
ste[1].lpServiceProc:=nil;

StartServiceCtrlDispatcher( ste[0]);

В процедуре ServiceHandler нужно обрабатывать, как минимум, коды SERVICE_CONTROL_STOP, SERVICE_CONTROL_SHUTDOWN (завершая сервис) и SERVICE_CONTROL_INTERROGATE (выдавая текущее состояние сервиса).

Кое-что по сабжу можно найти здесь:
http://borland.xportal.ru/index.php

А еще лучше - найти книгу:
Дж. Рихтер, Дж. Кларк. Программирование серверных приложений для Windows 2000.
Там разъясняется все, и подробно.


 
sniknik ©   (2003-10-27 15:06) [4]

точно рабочий
http://delphi.chertenok.ru/forum/my_download.php?tema=del&action=show&id=173


 
Polevi ©   (2003-10-27 15:17) [5]

>Юрий Зотов © (27.10.03 14:32) [3]
пример работает 100%


 
Юрий Зотов ©   (2003-10-27 15:36) [6]

> Polevi © (27.10.03 15:17) [5]

Я тоже пытался так делать. Не работало, пока не сделал массив с пустым последним элементом. Сразу же все стало ОК. То же самое сказано и в MSDN, и у Рихтера.

Весь фокус в том, что один исполняемый файл может содержать произвольное количество сервисов. Для этого и нужен массив, а по пустому элементу определяется его конец.

> sniknik © (27.10.03 15:06) [4]

Хороший пример, но не могу понять зачем создавать еще один поток? Дело в том, что функция ServiceMain и без этого все равно вызывается в отдельном потоке (а вот CtrlHandler - в главном). Стало быть, простое GetCurrentThread в ServiceMain дает хэндл потока, которым можно управлять из CtrlHandler через глобальную переменную. И тогда не приходится плодить лишних сущностей, расходуя лишние ресурсы.


 
sniknik ©   (2003-10-27 17:00) [7]

> Хороший пример, но не могу понять зачем создавать еще один поток?
я там пояснял что просто для примера (что так можно и все), вообще вся програмка это один большой пример ничего больше, не заметили там протоколируется любое действие (а где такое нужно кроме как в примере?, при разборе как это работает).


 
Polevi ©   (2003-10-27 18:43) [8]

>Юрий Зотов © (27.10.03 15:36) [6]
я в курсе, но у меня работает и так, вот как бывает :-)


 
Юрий Зотов ©   (2003-10-27 19:12) [9]

> Polevi © (27.10.03 18:43) [8]

Возможно удачное совпадение - после структуры в памяти идут нули. По ним и определяется "конец массива".



Страницы: 1 вся ветка

Текущий архив: 2003.11.17;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.025 c
1-56562
Gray Angel
2003-11-06 13:53
2003.11.17
Довесок к Exeption


11-56553
Ash
2003-02-25 14:53
2003.11.17
TStrList


1-56750
goliath
2003-11-06 15:57
2003.11.17
Приведите пожалуйста пример использования TVirtualTreeView


1-56658
Sectey
2003-11-05 10:24
2003.11.17
Компонент в рунтайме


1-56721
RoLeX
2003-11-06 20:49
2003.11.17
Как написать следующее условие: если X не равен Edit2.text, то...