Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Service handler uses a global variable for service handler (works in all cases) - see http://synopse.info/forum/viewtopic.php?pid=3683#p3683 |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
215e44e66b1226ae772594cd9b0b9170 |
User & Date: | G018869 2012-04-10 13:17:23 |
2012-04-10
| ||
16:25 |
| |
13:17 | Service handler uses a global variable for service handler (works in all cases) - see http://synopse.info/forum/viewtopic.php?pid=3683#p3683 check-in: 215e44e66b user: G018869 tags: trunk | |
09:26 | new ForceID parameter for TSQLRest.Add() to allow adding a given ID check-in: 3f9985da02 user: G018869 tags: trunk | |
Changes to SQLite3/SQLite3Service.pas.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 ... 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 ... 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 ... 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 ... 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 ... 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 ... 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
the startup program logs the error and displays a message but continues the startup operation), SERVICE_ERROR_SEVERE, SERVICE_ERROR_CRITICAL } constructor CreateNewService(const TargetComputer, DatabaseName, Name, DisplayName, Path: string; const OrderGroup: string = ''; const Dependances: string = ''; const Username: string = ''; const Password: string = ''; DesiredAccess: DWord = SERVICE_ALL_ACCESS; ServiceType: DWord = SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS; StartType: DWord = SERVICE_DEMAND_START; ErrorControl: DWord = SERVICE_ERROR_NORMAL); {{ Opens an existing service, in order to control it or its configuration from your application. Parameters (strings are unicode-ready since Delphi 2009): - TargetComputer - set it to empty string if local computer is the target. - DatabaseName - set it to empty string if the default database is supposed ('ServicesActive'). - Name - name of a service. - DesiredAccess - a combination of following flags: ................................................................................ Delphi compiler), either UnicodeString (till Delphi 2009) } function Start(const Args: array of PChar): boolean; end; TService = class; /// callback procedure for Windows Service Controller TServiceCtrlHandler = procedure(CtrlCode: DWord); stdcall; /// event triggered for Control handler TServiceControlEvent = procedure(Sender: TService; Code: DWORD) of object; /// event triggered to implement the Service functionality TServiceEvent = procedure(Sender: TService) of object; {{ TService is the class used to implement a service provided by an application } TService = class protected fSName: String; fDName: String; fStartType: dword; fServiceType: dword; fData: DWORD; fCtrlHandler: TServiceCtrlHandler; fOnControl: TServiceControlEvent; fOnInterrogate: TServiceEvent; fOnPause: TServiceEvent; fOnShutdown: TServiceEvent; fOnStart: TServiceEvent; ................................................................................ // - main application must call the global ServicesRun procedure to actually // start the services // - caller must free the TService instance when it's no longer used constructor Create(const aServiceName, aDisplayName: String); reintroduce; virtual; /// free memory and release handles destructor Destroy; override; {{ Reports new status to the system } function ReportStatus(dwState, dwExitCode, dwWait:DWORD):BOOL; {{ Installs the service in the database - return true on success - create a local TServiceController with the current executable file, with the supplied command line parameters} function Install(const Params: string=''): boolean; {{ Removes the service from database - uses a local TServiceController with the current Service Name } ................................................................................ {{ this is the main method, in which the Service should implement its run } procedure Execute; virtual; {{ Name of the service. Must be unique } property ServiceName: String read fSName; {{ Display name of the service } property DisplayName: String read fDName write fDName; {{ Type of service } property ServiceType: dword read fServiceType write fServiceType; {{ Type of start of service } property StartType: dword read fStartType write fStartType; {{ Number of arguments passed to the service by the service controler } property ArgCount: Integer read GetArgCount; {{ List of arguments passed to the service by the service controler } property Args[Idx: Integer]: String read GetArgs; {{ Current service status - To report new status to the system, assign another value to this record, or use ReportStatus method (better) } ................................................................................ {{ launch the registered Services execution - the registered list of service provided by the aplication is sent to the operating system } procedure ServicesRun; {{ convert the Control Code retrieved from Windows into a service state enumeration item } function CurrentStateToServiceState(CurrentState: DWord): TServiceState; /// return the ready to be displayed text of a TServiceState value function ServiceStateText(State: TServiceState): string; implementation ................................................................................ raise Exception.CreateFmt('Cannot allocate memory for service jump gate: %s', [fSName]); JumperAddr := @JumpToService; AfterCallAddr := Pointer(PtrInt(FJumper)+5); Offset := PtrInt(JumperAddr)-PtrInt(AfterCallAddr); PByte (PtrInt(FJumper)+0)^ := $E8; // call opcode PInteger(PtrInt(FJumper)+1)^ := Offset; // points to JumpToService PPtrInt (PtrInt(FJumper)+5)^ := PtrInt(self); // will be set as EAX=sef Result := FJumper; end; end; function CurrentStateToServiceState(CurrentState: DWord): TServiceState; begin case CurrentState of SERVICE_STOPPED: result := ssStopped; SERVICE_START_PENDING: result := ssStarting; SERVICE_STOP_PENDING: result := ssStopping; SERVICE_RUNNING: result := ssRunning; SERVICE_CONTINUE_PENDING: result := ssResuming; ................................................................................ if (schService>0) then begin result := true; CloseServiceHandle(schService); end; end; end; {procedure TService.MessageExecute(EndCode: dword); var aMsg: TMsg; begin while fCurrentCode<>EndCode do begin while PeekMessage(aMsg,0,0,0,PM_REMOVE) do begin TranslateMessage(aMsg); DispatchMessage(aMsg); end; |
| | | | | | | | | | | | | |
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 ... 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 ... 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 ... 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 ... 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 ... 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 ... 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
the startup program logs the error and displays a message but continues the startup operation), SERVICE_ERROR_SEVERE, SERVICE_ERROR_CRITICAL } constructor CreateNewService(const TargetComputer, DatabaseName, Name, DisplayName, Path: string; const OrderGroup: string = ''; const Dependances: string = ''; const Username: string = ''; const Password: string = ''; DesiredAccess: DWORD = SERVICE_ALL_ACCESS; ServiceType: DWORD = SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS; StartType: DWORD = SERVICE_DEMAND_START; ErrorControl: DWORD = SERVICE_ERROR_NORMAL); {{ Opens an existing service, in order to control it or its configuration from your application. Parameters (strings are unicode-ready since Delphi 2009): - TargetComputer - set it to empty string if local computer is the target. - DatabaseName - set it to empty string if the default database is supposed ('ServicesActive'). - Name - name of a service. - DesiredAccess - a combination of following flags: ................................................................................ Delphi compiler), either UnicodeString (till Delphi 2009) } function Start(const Args: array of PChar): boolean; end; TService = class; /// callback procedure for Windows Service Controller TServiceCtrlHandler = procedure(CtrlCode: DWORD); stdcall; /// event triggered for Control handler TServiceControlEvent = procedure(Sender: TService; Code: DWORD) of object; /// event triggered to implement the Service functionality TServiceEvent = procedure(Sender: TService) of object; {{ TService is the class used to implement a service provided by an application } TService = class protected fSName: String; fDName: String; fStartType: DWORD; fServiceType: DWORD; fData: DWORD; fCtrlHandler: TServiceCtrlHandler; fOnControl: TServiceControlEvent; fOnInterrogate: TServiceEvent; fOnPause: TServiceEvent; fOnShutdown: TServiceEvent; fOnStart: TServiceEvent; ................................................................................ // - main application must call the global ServicesRun procedure to actually // start the services // - caller must free the TService instance when it's no longer used constructor Create(const aServiceName, aDisplayName: String); reintroduce; virtual; /// free memory and release handles destructor Destroy; override; {{ Reports new status to the system } function ReportStatus(dwState, dwExitCode, dwWait: DWORD): BOOL; {{ Installs the service in the database - return true on success - create a local TServiceController with the current executable file, with the supplied command line parameters} function Install(const Params: string=''): boolean; {{ Removes the service from database - uses a local TServiceController with the current Service Name } ................................................................................ {{ this is the main method, in which the Service should implement its run } procedure Execute; virtual; {{ Name of the service. Must be unique } property ServiceName: String read fSName; {{ Display name of the service } property DisplayName: String read fDName write fDName; {{ Type of service } property ServiceType: DWORD read fServiceType write fServiceType; {{ Type of start of service } property StartType: DWORD read fStartType write fStartType; {{ Number of arguments passed to the service by the service controler } property ArgCount: Integer read GetArgCount; {{ List of arguments passed to the service by the service controler } property Args[Idx: Integer]: String read GetArgs; {{ Current service status - To report new status to the system, assign another value to this record, or use ReportStatus method (better) } ................................................................................ {{ launch the registered Services execution - the registered list of service provided by the aplication is sent to the operating system } procedure ServicesRun; {{ convert the Control Code retrieved from Windows into a service state enumeration item } function CurrentStateToServiceState(CurrentState: DWORD): TServiceState; /// return the ready to be displayed text of a TServiceState value function ServiceStateText(State: TServiceState): string; implementation ................................................................................ raise Exception.CreateFmt('Cannot allocate memory for service jump gate: %s', [fSName]); JumperAddr := @JumpToService; AfterCallAddr := Pointer(PtrInt(FJumper)+5); Offset := PtrInt(JumperAddr)-PtrInt(AfterCallAddr); PByte (PtrInt(FJumper)+0)^ := $E8; // call opcode PInteger(PtrInt(FJumper)+1)^ := Offset; // points to JumpToService PPtrInt (PtrInt(FJumper)+5)^ := PtrInt(self); // will be set as EAX=self Result := FJumper; end; end; function CurrentStateToServiceState(CurrentState: DWORD): TServiceState; begin case CurrentState of SERVICE_STOPPED: result := ssStopped; SERVICE_START_PENDING: result := ssStarting; SERVICE_STOP_PENDING: result := ssStopping; SERVICE_RUNNING: result := ssRunning; SERVICE_CONTINUE_PENDING: result := ssResuming; ................................................................................ if (schService>0) then begin result := true; CloseServiceHandle(schService); end; end; end; {procedure TService.MessageExecute(EndCode: DWORD); var aMsg: TMsg; begin while fCurrentCode<>EndCode do begin while PeekMessage(aMsg,0,0,0,PM_REMOVE) do begin TranslateMessage(aMsg); DispatchMessage(aMsg); end; |
Changes to SQLite3/Samples/10 - Background Http service/httpservice.dpr.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
destructor Destroy; override; end; const SERVICENAME = 'mORMotHttpServerService'; SERVICEDISPLAYNAME = 'mORMot Http Server Service'; { TSQLite3HttpService } constructor TSQLite3HttpService.Create; begin inherited Create(SERVICENAME,SERVICEDISPLAYNAME); OnStart := DoStart; OnStop := DoStop; OnResume := DoStart; // trivial Pause/Resume actions OnPause := DoStop; end; destructor TSQLite3HttpService.Destroy; ................................................................................ Start([]); end; finally Free; end; end; var Service: TSQLite3HttpService; begin if ParamCount<>0 then CheckParameters else begin Service := TSQLite3HttpService.Create; try // launches the registered Services execution = do all the magic ServicesRun; finally Service.Free; end; end; end. |
>
>
>
>
>
>
>
>
>
>
>
>
<
|
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
destructor Destroy; override; end; const SERVICENAME = 'mORMotHttpServerService'; SERVICEDISPLAYNAME = 'mORMot Http Server Service'; var /// use a global variable for service handler (works in all cases) // - see http://synopse.info/forum/viewtopic.php?pid=3683#p3683 Service: TSQLite3HttpService; procedure ServiceControlHandler(CtrlCode: DWORD); stdcall; begin Service.DoCtrlHandle(CtrlCode); end; { TSQLite3HttpService } constructor TSQLite3HttpService.Create; begin inherited Create(SERVICENAME,SERVICEDISPLAYNAME); ControlHandler := ServiceControlHandler; OnStart := DoStart; OnStop := DoStop; OnResume := DoStart; // trivial Pause/Resume actions OnPause := DoStop; end; destructor TSQLite3HttpService.Destroy; ................................................................................ Start([]); end; finally Free; end; end; begin if ParamCount<>0 then CheckParameters else begin Service := TSQLite3HttpService.Create; try // launches the registered Services execution = do all the magic ServicesRun; finally Service.Free; end; end; end. |