1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465 |
- {
- $Id: header,v 1.1 2000/07/13 06:33:45 michael Exp $
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2000 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit daemonapp;
- {$mode objfpc}{$H+}
- interface
- uses
- Custapp, Classes, SysUtils, eventlog, rtlconsts;
- Type
- TCustomDaemon = Class;
- TDaemonController = Class;
- TDaemonEvent = procedure(Sender: TCustomDaemon) of object;
- TDaemonOKEvent = procedure(Sender: TCustomDaemon; var OK: Boolean) of object;
- TDaemonOption = (doAllowStop,doAllowPause,doInteractive);
- TDaemonOptions = Set of TDaemonOption;
- TDaemonRunMode = (drmUnknown,drmInstall,drmUninstall,drmRun);
-
- { TCustomDaemonDescription }
- TDaemonDef = Class;
- TCurrentStatus =
- (csStopped, csStartPending, csStopPending, csRunning,
- csContinuePending, csPausePending, csPaused);
- TCustomDaemon = Class(TDataModule)
- private
- FController: TDaemonController;
- FDaemonDef: TDaemonDef;
- FThread : TThread;
- FStatus: TCurrentStatus;
- function GetLogger: TEventLog;
- procedure SetStatus(const AValue: TCurrentStatus);
- Protected
- Function Start : Boolean; virtual;
- Function Stop : Boolean; virtual;
- Function Pause : Boolean; virtual;
- Function Continue : Boolean; virtual;
- Function Execute : Boolean; virtual;
- Function ShutDown : Boolean; virtual;
- Function Install : Boolean; virtual;
- Function UnInstall: boolean; virtual;
- Function HandleCustomCode(ACode : DWord) : Boolean; Virtual;
- Public
- Procedure CheckControlMessages(Wait : Boolean);
- Procedure LogMessage(const Msg : String);
- Procedure ReportStatus;
-
- // Filled in at runtime by controller
- Property Definition : TDaemonDef Read FDaemonDef;
- Property DaemonThread : TThread Read FThread;
- Property Controller : TDaemonController Read FController;
- Property Status : TCurrentStatus Read FStatus Write SetStatus;
- Property Logger : TEventLog Read GetLogger;
- end;
- TCustomDaemonClass = Class of TCustomDaemon;
- { TDaemon }
- TCustomControlCodeEvent = Procedure(Sender : TCustomDaemon; ACode : DWord; Var Handled : Boolean) of object;
- TDaemon = Class(TCustomDaemon)
- private
- FAfterInstall: TDaemonEvent;
- FAfterUnInstall: TDaemonEvent;
- FBeforeInstall: TDaemonEvent;
- FBeforeUnInstall: TDaemonEvent;
- FOnContinue: TDaemonOKEvent;
- FOnCustomControl: TCustomControlCodeEvent;
- FOnExecute: TDaemonEvent;
- FOnPause: TDaemonOKEvent;
- FOnShutDown: TDaemonEvent;
- FOnStart: TDaemonOKEvent;
- FOnStop: TDaemonOKEvent;
- Protected
- Function Start : Boolean; override;
- Function Stop : Boolean; override;
- Function Pause : Boolean; override;
- Function Continue : Boolean; override;
- Function Execute : Boolean; override;
- Function ShutDown : Boolean; override;
- Function Install : Boolean; override;
- Function UnInstall: boolean; override;
- Function HandleCustomCode(ACode : DWord) : Boolean; Override;
- Public
- Property Definition;
- Property Status;
- Published
- Property OnStart : TDaemonOKEvent Read FOnStart Write FOnStart;
- Property OnStop : TDaemonOKEvent Read FOnStop Write FOnStop;
- Property OnPause : TDaemonOKEvent Read FOnPause Write FOnPause;
- Property OnContinue : TDaemonOKEvent Read FOnContinue Write FOnContinue;
- Property OnShutDown : TDaemonEvent Read FOnShutDown Write FOnShutDown;
- Property OnExecute : TDaemonEvent Read FOnExecute Write FOnExecute;
- Property BeforeInstall : TDaemonEvent Read FBeforeInstall Write FBeforeInstall;
- Property AfterInstall : TDaemonEvent Read FAfterInstall Write FAfterInstall;
- Property BeforeUnInstall : TDaemonEvent Read FBeforeUnInstall Write FBeforeUnInstall;
- Property AfterUnInstall : TDaemonEvent Read FAfterUnInstall Write FAfterUnInstall;
- Property OnControlCode : TCustomControlCodeEvent Read FOnCustomControl Write FOnCustomControl;
- end;
- { TDaemonController }
- TDaemonController = Class(TComponent)
- Private
- FDaemon : TCustomDaemon;
- FLastStatus: TCurrentStatus;
- FSysData : TObject;
- FParams : TStrings;
- FCheckPoint : DWord;
- Public
- Constructor Create(AOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure StartService; virtual;
- Procedure Main(Argc : DWord; Args : PPChar); Virtual;
- Procedure Controller(ControlCode,EventType : DWord; EventData : Pointer); Virtual;
- Function ReportStatus : Boolean; virtual;
- Property Daemon : TCustomDaemon Read FDaemon;
- Property Params : TStrings Read FParams;
- Property LastStatus : TCurrentStatus Read FLastStatus;
- Property CheckPoint : DWord read FCheckPoint;
- end;
-
- TDaemonClass = Class of TDaemon;
-
- { Windows specific service registration types }
-
- TServiceType = (stWin32, stDevice, stFileSystem);
- TErrorSeverity = (esIgnore, esNormal, esSevere, esCritical);
- TStartType = (stBoot, stSystem, stAuto, stManual, stDisabled);
-
- { TDependency }
- TDependency = class(TCollectionItem)
- private
- FName: String;
- FIsGroup: Boolean;
- protected
- function GetDisplayName: string; override;
- Public
- Procedure Assign(Source : TPersistent); override;
- published
- property Name: String read FName write FName;
- property IsGroup: Boolean read FIsGroup write FIsGroup;
- end;
-
- { TDependencies }
- TDependencies = class(TCollection)
- private
- FOwner: TPersistent;
- function GetItem(Index: Integer): TDependency;
- procedure SetItem(Index: Integer; Value: TDependency);
- protected
- function GetOwner: TPersistent; override;
- public
- constructor Create(AOwner: TPersistent);
- property Items[Index: Integer]: TDependency read GetItem write SetItem; default;
- end;
- { TWinBindings }
- TWinBindings = class(TPersistent)
- private
- FDependencies: TDependencies;
- FErrCode: DWord;
- FErrorSeverity: TErrorSeverity;
- FLoadGroup: String;
- FPassWord: String;
- FServiceType: TServiceType;
- FStartType: TStartType;
- FTagID: DWord;
- FUserName: String;
- FWaitHint: Integer;
- FWin32ErrorCode: DWord;
- procedure SetDependencies(const AValue: TDependencies);
- Public
- Constructor Create;
- Destructor Destroy; override;
- Procedure Assign(Source : TPersistent); override;
- property ErrCode: DWord read FErrCode write FErrCode;
- property Win32ErrCode: DWord read FWin32ErrorCode write FWin32ErrorCode;
- Published
- Property Dependencies : TDependencies Read FDependencies Write SetDependencies;
- Property GroupName : String Read FLoadGroup Write FLoadGroup;
- Property Password : String Read FPassWord Write FPassword;
- Property UserName : String Read FUserName Write FUserName;
- Property StartType : TStartType Read FStartType Write FStartType;
- Property WaitHint : Integer Read FWaitHint Write FWaitHint;
- Property IDTag : DWord Read FTagID Write FTagID;
- Property ServiceType : TServiceType Read FServiceType Write FServiceType;
- Property ErrorSeverity : TErrorSeverity Read FErrorSeverity Write FErrorSeverity;
- end;
- { TDaemonDef }
-
- TDaemonDef = Class(TCollectionItem)
- private
- FDaemonClass: TCustomDaemonClass;
- FDaemonClassName: String;
- FDescription: String;
- FDisplayName: String;
- FEnabled: Boolean;
- FInstance: TCustomDaemon;
- FLogStatusReport: Boolean;
- FName: String;
- FOnCreateInstance: TNotifyEvent;
- FOptions: TDaemonOptions;
- FServiceName: String;
- FWinBindings: TWinBindings;
- FRunArgs : String;
- procedure SetName(const AValue: String);
- procedure SetWinBindings(const AValue: TWinBindings);
- Protected
- function GetDisplayName: string; override;
- Public
- Constructor Create(ACollection : TCollection); override;
- Destructor Destroy; override;
- Property DaemonClass : TCustomDaemonClass read FDaemonClass;
- Property Instance : TCustomDaemon Read FInstance Write FInstance;
- Published
- Property DaemonClassName : String Read FDaemonClassName Write FDaemonClassName;
- Property Name : String Read FName Write SetName;
- Property Description : String Read FDescription Write FDescription;
- Property DisplayName : String Read FDisplayName Write FDisplayName;
- Property RunArguments : String Read FRunArgs Write FRunArgs;
- Property Options : TDaemonOptions Read FOptions Write FOptions;
- Property Enabled : Boolean Read FEnabled Write FEnabled default true;
- Property WinBindings : TWinBindings Read FWinBindings Write SetWinBindings;
- Property OnCreateInstance : TNotifyEvent Read FOnCreateInstance Write FOnCreateInstance;
- Property LogStatusReport : Boolean Read FLogStatusReport Write FLogStatusReport;
- end;
- { TDaemonDefs }
- TDaemonDefs = Class(TCollection)
- private
- FOwner : TPersistent;
- function GetDaemonDef(Index : Integer): TDaemonDef;
- procedure SetDaemonDef(Index : Integer; const AValue: TDaemonDef);
- Protected
- Procedure BindClasses;
- Function GetOwner : TPersistent; override;
- Public
- Constructor Create(AOwner : TPersistent; AClass : TCollectionItemClass);
- Function IndexOfDaemonDef(Const DaemonName : String) : Integer;
- Function FindDaemonDef(Const DaemonName : String) : TDaemonDef;
- Function DaemonDefByName(Const DaemonName : String) : TDaemonDef;
- Property Daemons[Index : Integer] : TDaemonDef Read GetDaemonDef Write SetDaemonDef; default;
- end;
-
- { TCustomDaemonMapper }
- TCustomDaemonMapper = Class(TComponent)
- private
- FDaemonDefs: TDaemonDefs;
- FOnCreate: TNotifyEvent;
- FOnDestroy: TNotifyEvent;
- FOnInstall: TNotifyEvent;
- FOnRun: TNotifyEvent;
- FOnUnInStall: TNotifyEvent;
- procedure SetDaemonDefs(const AValue: TDaemonDefs);
- Protected
- Procedure CreateDefs; virtual;
- Procedure DoOnCreate; virtual;
- Procedure DoOnDestroy; virtual;
- Procedure DoOnInstall; virtual;
- Procedure DoOnUnInstall; virtual;
- Procedure DoOnRun; virtual;
- Public
- Constructor Create(AOwner : TComponent); override;
- Destructor Destroy; override;
- Published
- Property DaemonDefs : TDaemonDefs Read FDaemonDefs Write SetDaemonDefs;
- Property OnCreate : TNotifyEvent Read FOnCreate Write FOnCreate;
- Property OnDestroy : TNotifyEvent Read FOnDestroy Write FOnDestroy;
- Property OnRun : TNotifyEvent Read FOnRun Write FOnRun;
- Property OnInstall : TNotifyEvent Read FOnInstall Write FOnInstall;
- Property OnUnInstall : TNotifyEvent Read FOnUnInStall Write FOnUninStall;
- end;
-
- { TDaemonMapper }
- TDaemonMapper = Class(TCustomDaemonMapper)
- Constructor Create(AOwner : TComponent); override;
- Constructor CreateNew(AOwner : TComponent; Dummy : Integer = 0);
- end;
-
- TCustomDaemonMapperClass = Class of TCustomDaemonMapper;
-
- { TDaemonThread }
- TDaemonThread = Class(TThread)
- Private
- FDaemon : TCustomDaemon;
- Protected
- procedure StartServiceExecute; virtual;
- procedure HandleControlCode(ACode : DWord); virtual;
- Public
- Constructor Create(ADaemon : TCustomDaemon);
- Procedure Execute; override;
- Procedure CheckControlMessage(WaitForMessage : Boolean);
- Function StopDaemon : Boolean; virtual;
- Function PauseDaemon : Boolean; virtual;
- Function ContinueDaemon : Boolean; virtual;
- Function ShutDownDaemon : Boolean; virtual;
- Function InterrogateDaemon : Boolean; virtual;
- Property Daemon : TCustomDaemon Read FDaemon;
- end;
- { TCustomDaemonApplication }
- TGuiLoopEvent = Procedure Of Object;
-
- TCustomDaemonApplication = Class(TCustomApplication)
- private
- FGUIHandle: THandle;
- FGUIMainLoop: TGuiLoopEvent;
- FEventLog: TEventLog;
- FMapper : TCustomDaemonMapper;
- FOnRun: TNotifyEvent;
- FRunMode: TDaemonRunMode;
- FSysData: TObject;
- FControllerCount : Integer;
- FAutoRegisterMessageFile : Boolean;
- procedure BindDaemonDefs(AMapper: TCustomDaemonMapper);
- function InstallRun: Boolean;
- procedure SysInstallDaemon(Daemon: TCustomDaemon);
- procedure SysUnInstallDaemon(Daemon: TCustomDaemon);
- function UnInstallRun: Boolean;
- function RunDaemonsRun: Boolean;
- Procedure Main(Argc : DWord; Args : PPchar);
- Function RunGUIloop(P : Pointer) : integer;
- Protected
- // OS (System) dependent calls
- Procedure SysStartUnInstallDaemons;
- Procedure SysEndUnInstallDaemons;
- Procedure SysStartInstallDaemons;
- Procedure SysEndInstallDaemons;
- Procedure SysStartRunDaemons;
- Procedure SysEndRunDaemons;
- // Customizable behaviour
- procedure CreateDaemonController(Var AController : TDaemonController); virtual;
- Procedure CreateServiceMapper(Var AMapper : TCustomDaemonMapper); virtual;
- Procedure CreateDaemonInstance(Var ADaemon : TCustomDaemon; DaemonDef : TDaemonDef); virtual;
- Procedure RemoveController(AController : TDaemonController); virtual;
- Function GetEventLog: TEventLog; virtual;
- Procedure DoRun; override;
- procedure DoLog(EventType: TEventType; const Msg: String); override;
- Property SysData : TObject Read FSysData Write FSysData;
- Public
- Constructor Create(AOwner : TComponent); override;
- destructor Destroy; override;
- Procedure ShowException(E : Exception); override;
- Function CreateDaemon(DaemonDef : TDaemonDef) : TCustomDaemon;
- Procedure StopDaemons(Force : Boolean);
- procedure InstallDaemons;
- procedure RunDaemons;
- procedure UnInstallDaemons;
- procedure ShowHelp;
- procedure CreateForm(InstanceClass: TComponentClass; var Reference); virtual;
- Property OnRun : TNotifyEvent Read FOnRun Write FOnRun;
- Property EventLog : TEventLog Read GetEventLog;
- Property GUIMainLoop : TGuiLoopEvent Read FGUIMainLoop Write FGuiMainLoop;
- Property GuiHandle : THandle Read FGUIHandle Write FGUIHandle;
- Property RunMode : TDaemonRunMode Read FRunMode;
- Property AutoRegisterMessageFile : Boolean Read FAutoRegisterMessageFile Write FAutoRegisterMessageFile default true;
- end;
- TCustomDaemonApplicationClass = Class of TCustomDaemonApplication;
-
- TDaemonApplication = Class(TCustomDaemonApplication);
- EDaemon = Class(Exception);
- Function Application : TCustomDaemonApplication;
- Procedure RegisterDaemonMapper(AMapperClass : TCustomDaemonMapperClass);
- Procedure RegisterDaemonClass(AClass : TCustomDaemonClass);
- Procedure RegisterDaemonApplicationClass(AClass : TCustomDaemonApplicationClass);
- Procedure DaemonError(Msg : String);
- Procedure DaemonError(Fmt : String; Args : Array of const);
- Resourcestring
- SErrNoServiceMapper = 'No daemon mapper class registered.';
- SErrOnlyOneMapperAllowed = 'Not changing daemon mapper class %s with %s: Only 1 mapper allowed.';
- SErrNothingToDo = 'No command given, use ''%s -h'' for usage.';
- SErrDuplicateName = 'Duplicate daemon name: %s';
- SErrUnknownDaemonClass = 'Unknown daemon class name: %s';
- SErrDaemonStartFailed = 'Failed to start daemon %s : %s';
- SDaemonStatus = 'Daemon %s current status: %s';
- SControlFailed = 'Control code %s handling failed: %s';
- SCustomCode = '[Custom code %d]';
- SErrServiceManagerStartFailed = 'Failed to start service manager: %s';
- SErrNoDaemonForStatus = '%s: No daemon for status report';
- SErrNoDaemonDefForStatus = '%s: No daemon definition for status report';
- SErrWindowClass = 'Could not register window class';
- SErrApplicationAlreadyCreated = 'An application instance of class %s was already created.';
- SHelpUsage = 'Usage: %s [command]';
- SHelpCommand = 'Where command is one of the following:';
- SHelpInstall = 'To install the program as a service';
- SHelpUnInstall = 'To uninstall the service';
- SHelpRun = 'To run the service';
- { $define svcdebug}
- {$ifdef svcdebug}
- Procedure DebugLog(Msg : String);
- {$endif}
- Var
- CurrentStatusNames : Array[TCurrentStatus] of string =
- ('Stopped', 'Start Pending', 'Stop Pending', 'Running',
- 'Continue Pending', 'Pause Pending', 'Paused');
- SStatus : Array[1..5] of string =
- ('Stop','Pause','Continue','Interrogate','Shutdown');
- DefaultDaemonOptions : TDaemonOptions = [doAllowStop,doAllowPause];
- AppClass : TCustomDaemonApplicationClass;
-
- implementation
- // This must come first, so a uses clause can be added.
- {$i daemonapp.inc}
- Var
- AppInstance : TCustomDaemonApplication;
- MapperClass : TCustomDaemonMapperClass;
- DesignMapper : TCustomDaemonMapper;
- DaemonClasses : TStringList;
-
- {$ifdef svcdebug}
- Var
- FL : Text;
- LCS : TRTLCriticalSection;
-
- Procedure StartLog;
- begin
- {$ifdef win32}
- Assign(FL,'c:\service.log');
- {$else}
- Assign(FL,'/tmp/service.log');
- {$endif}
- Rewrite(FL);
- InitCriticalSection(LCS);
- DebugLog('Start logging');
- end;
- Procedure DebugLog(Msg : String);
- begin
- EnterCriticalSection(LCS);
- try
- Writeln(FL,Msg);
- Flush(FL);
- Finally
- LeaveCriticalSection(LCS);
- end;
- end;
- Procedure EndLog;
- begin
- DebugLog('Done logging');
- Close(FL);
- DoneCriticalSection(LCS);
- end;
- {$endif svcdebug}
- Procedure RegisterDaemonApplicationClass(AClass : TCustomDaemonApplicationClass);
- begin
- If (AppInstance<>Nil) then
- DaemonError(SErrApplicationAlreadyCreated,[AppInstance.ClassName]);
- AppClass:=AClass;
- end;
- Procedure RegisterDaemonClass(AClass : TCustomDaemonClass);
- Var
- DN : String;
- I : Integer;
-
- begin
- If Not Assigned(DaemonClasses) then
- begin
- DaemonClasses:=TStringList.Create;
- DaemonClasses.Sorted:=True;
- end;
- DN:=AClass.ClassName;
- I:=DaemonClasses.IndexOf(DN);
- If (I=-1) then
- I:=DaemonClasses.Add(DN);
- DaemonClasses.Objects[I]:=TObject(AClass);
- end;
- Procedure CreateDaemonApplication;
- begin
- If (AppClass=Nil) then
- AppClass:=TCustomDaemonApplication;
- AppInstance:=AppClass.Create(Nil);
- end;
- Procedure DoneDaemonApplication;
- begin
- FreeAndNil(AppInstance);
- FreeAndNil(DaemonClasses);
- end;
- function Application: TCustomDaemonApplication;
- begin
- {$ifdef svcdebug}Debuglog('Application');{$endif}
- If (AppInstance=Nil) then
- begin
- {$ifdef svcdebug}Debuglog('Application creating instance');{$endif}
- CreateDaemonApplication;
- end;
- Result:=AppInstance;
- end;
- Procedure RegisterDaemonMapper(AMapperClass : TCustomDaemonMapperClass);
- begin
- If Assigned(MapperClass) then
- DaemonError(SErrOnlyOneMapperAllowed,[MapperClass.ClassName,AMapperClass.ClassName]);
- MapperClass:=AMapperClass;
- end;
- procedure DaemonError(Msg: String);
- begin
- Raise EDaemon.Create(MSg);
- end;
- procedure DaemonError(Fmt: String; Args: array of const);
- begin
- Raise EDaemon.CreateFmt(Fmt,Args);
- end;
- { TDaemon }
- function TDaemon.Start: Boolean;
- begin
- Result:=inherited Start;
- If assigned(FOnStart) then
- FOnStart(Self,Result);
- end;
- function TDaemon.Stop: Boolean;
- begin
- Result:=inherited Stop;
- If assigned(FOnStop) then
- FOnStop(Self,Result);
- end;
- function TDaemon.Pause: Boolean;
- begin
- Result:=inherited Pause;
- If assigned(FOnPause) then
- FOnPause(Self,Result);
- end;
- function TDaemon.Continue: Boolean;
- begin
- Result:=inherited Continue;
- If assigned(FOnContinue) then
- FOnContinue(Self,Result);
- end;
- function TDaemon.Execute: Boolean;
- begin
- Result:=Assigned(FOnExecute);
- If Result Then
- FOnExecute(Self);
- end;
- function TDaemon.ShutDown: Boolean;
- begin
- Result:=Inherited ShutDown;
- If Assigned(FOnShutDown) then
- FOnShutDown(Self);
- end;
- function TDaemon.Install: Boolean;
- begin
- If Assigned(FBeforeInstall) then
- FBeforeInstall(Self);
- Result:=inherited Install;
- If Assigned(FAfterInstall) then
- FAfterInstall(Self)
- end;
- function TDaemon.UnInstall: boolean;
- begin
- If Assigned(FBeforeUnInstall) then
- FBeforeUnInstall(Self);
- Result:=inherited UnInstall;
- If Assigned(FAfterUnInstall) then
- FAfterUnInstall(Self)
- end;
- function TDaemon.HandleCustomCode(ACode: DWord): Boolean;
- begin
- Result:=Assigned(FOnCustomControl);
- If Result then
- FOnCustomControl(Self,ACode,Result);
- end;
- { TCustomDaemon }
- Function TCustomDaemon.Start : Boolean;
- begin
- Result:=True;
- end;
- Function TCustomDaemon.Stop : Boolean;
- begin
- Result:=True;
- end;
- Function TCustomDaemon.Pause : Boolean;
- begin
- Result:=True;
- end;
- Function TCustomDaemon.Continue : Boolean;
- begin
- Result:=True;
- end;
- function TCustomDaemon.Execute: Boolean;
- begin
- Result:=False;
- end;
- Function TCustomDaemon.ShutDown : Boolean;
- begin
- Result:=True;
- end;
- Procedure TCustomDaemon.ReportStatus;
- begin
- Controller.ReportStatus;
- end;
- procedure TCustomDaemon.LogMessage(const Msg: String);
- begin
- Application.Log(etInfo,Msg);
- end;
- function TCustomDaemon.GetLogger: TEventLog;
- begin
- Result:=Application.EventLog;
- end;
- procedure TCustomDaemon.SetStatus(const AValue: TCurrentStatus);
- begin
- FStatus:=AValue;
- Controller.ReportStatus;
- end;
- Function TCustomDaemon.Install : Boolean;
- begin
- Result:=True;
- Application.SysInstallDaemon(Self);
- end;
- Function TCustomDaemon.UnInstall : Boolean;
- begin
- Result:=True;
- Application.SysUnInstallDaemon(Self);
- end;
- function TCustomDaemon.HandleCustomCode(ACode: DWord): Boolean;
- begin
- Result:=False
- end;
- Procedure TCustomDaemon.CheckControlMessages(Wait : Boolean);
- begin
- If Assigned(FThread) then
- TDaemonThread(FThread).CheckControlMessage(Wait);
- end;
-
- { TCustomServiceApplication }
- procedure TCustomDaemonApplication.CreateServiceMapper(Var AMapper : TCustomDaemonMapper);
- begin
- AMapper:=MapperClass.Create(Self);
- BindDaemonDefs(Amapper);
- end;
- procedure TCustomDaemonApplication.BindDaemonDefs(AMapper : TCustomDaemonMapper);
- begin
- AMApper.DaemonDefs.BindClasses;
- end;
- procedure TCustomDaemonApplication.CreateDaemonController(Var AController : TDaemonController);
- begin
- ACOntroller:=TDaemonController.Create(Self);
- end;
- Function TCustomDaemonApplication.RunDaemonsRun : Boolean;
- begin
- Result:=HasOption('r','run');
- // No Borland compatibility needed, as the install will take care of the -r
- end;
- procedure TCustomDaemonApplication.Main(Argc: DWord; Args: PPchar);
- Var
- SN : String;
- DD : TDaemonDef;
-
- begin
- {$ifdef svcdebug}DebugLog('Application.Main');{$endif svcdebug}
- If (Argc=0) then
- begin
- {$ifdef svcdebug}DebugLog('Using Default daemon');{$endif svcdebug}
- if FMapper.DaemonDefs.Count=1 then
- DD:=FMapper.DaemonDefs[0]
- else
- DD:=Nil
- end
- else
- begin
- {$ifdef svcdebug}DebugLog('Application.Main 2 : '+IntToStr(Argc));{$endif svcdebug}
- DD:=Nil;
- SN:='';
- If (Args<>Nil) then
- begin
- If (Args^<>Nil) then
- SN:=StrPas(Args^)
- else
- SN:='';
- end;
- {$ifdef svcdebug}DebugLog('Looking for daemon '+SN);{$endif svcdebug}
- DD:=FMapper.DaemonDefs.FindDaemonDef(SN);
- end;
- If (DD<>Nil) then
- begin
- {$ifdef svcdebug}DebugLog('Found daemon '+SN);{$endif svcdebug}
- DD.Instance.Controller.Main(Argc,Args);
- end
- else
- begin
- {$ifdef svcdebug}DebugLog('Did not fin daemon '+SN);{$endif svcdebug}
- end;
- end;
- Function TCustomDaemonApplication.InstallRun : Boolean;
- begin
- Result:=HasOption('i','install');
- // Borland compatibility.
- If not Result then
- Result:=FindCmdLineSwitch ('install',['/'],True);
- end;
- Function TCustomDaemonApplication.UnInstallRun : Boolean;
- begin
- Result:=HasOption('u','uninstall');
- // Borland compatibility.
- If not Result then
- Result:=FindCmdLineSwitch ('uninstall',['/'],True);
- end;
- Procedure TCustomDaemonApplication.InstallDaemons;
- Var
- D : TCustomDaemon;
- DD : TDaemonDef;
- C : TDaemonController;
- I : Integer;
- begin
- FrunMode:=drmInstall;
- SysStartInstallDaemons;
- try
- FMapper.DoOnInstall;
- For I:=0 to FMapper.DaemonDefs.Count-1 do
- begin
- DD:=FMapper.DaemonDefs[i];
- If DD.Enabled then
- begin
- D:=CreateDaemon(DD);
- Try
- // Need to call this because of the before/after events.
- D.Install;
- Finally
- D.Free;
- end;
- end;
- end;
- Finally
- SysEndInstallDaemons;
- end;
- end;
- Procedure TCustomDaemonApplication.UnInstallDaemons;
- Var
- D : TCustomDaemon;
- DD : TDaemonDef;
- I : Integer;
- begin
- FrunMode:=drmUnInstall;
- if FAutoRegisterMessageFile then
- EventLog.UnRegisterMessageFile;
- SysStartUnInstallDaemons;
- Try
- FMapper.DoOnUnInstall;
- // Uninstall in reverse order. One never knows.
- For I:=FMapper.DaemonDefs.Count-1 downto 0 do
- begin
- DD:=FMapper.DaemonDefs[i];
- If DD.Enabled then
- begin
- D:=CreateDaemon(FMapper.DaemonDefs[i]);
- Try
- // Need to call this because of the before/after events.
- D.UnInstall
- Finally
- D.Free;
- end;
- end;
- end;
- Finally
- SysEndUnInstallDaemons;
- end;
- end;
- procedure TCustomDaemonApplication.ShowHelp;
- begin
- if IsConsole then
- begin
- writeln(Format(SHelpUsage,[ParamStr(0)]));
- writeln(SHelpCommand);
- writeln(' -i --install '+SHelpInstall);
- writeln(' -u --uninstall '+SHelpUnInstall);
- writeln(' -r --run '+SHelpRun);
- end
- end;
- procedure TCustomDaemonApplication.CreateForm(InstanceClass: TComponentClass;
- var Reference);
-
- Var
- Instance: TComponent;
-
- begin
- // Allocate the instance, without calling the constructor
- Instance := TComponent(InstanceClass.NewInstance);
- // set the Reference before the constructor is called, so that
- // events and constructors can refer to it
- TComponent(Reference) := Instance;
- try
- Instance.Create(Self);
- except
- TComponent(Reference) := nil;
- Raise;
- end;
- end;
- procedure TCustomDaemonApplication.DoLog(EventType: TEventType; const Msg: String);
- begin
- EventLog.Log(EventType,Msg);
- end;
- Procedure TCustomDaemonApplication.RunDaemons;
- Var
- D : TCustomDaemon;
- DD : TDaemonDef;
- I : Integer;
- begin
- FRunMode:=drmRun;
- SysStartRunDaemons;
- FMapper.DoOnRun;
- For I:=0 to FMapper.DaemonDefs.Count-1 do
- begin
- DD:=FMapper.DaemonDefs[i];
- If DD.Enabled then
- D:=CreateDaemon(FMapper.DaemonDefs[i]);
- end;
- try
- SysEndRunDaemons;
- except
- HandleException(Self);
- Terminate;
- end;
- end;
- function TCustomDaemonApplication.GetEventLog: TEventLog;
- begin
- if not assigned(FEventLog) then
- begin
- FEventLog:=TEventlog.Create(Self);
- FEventLog.RaiseExceptionOnError:=False;
- if FAutoRegisterMessageFile then
- FEventLog.RegisterMessageFile('');
- end;
- result := FEventLog;
- end;
- destructor TCustomDaemonApplication.Destroy;
- begin
- if assigned(FEventLog) then
- FEventLog.Free;
- inherited Destroy;
- end;
- constructor TCustomDaemonApplication.Create(AOwner : TComponent);
- begin
- inherited;
- FAutoRegisterMessageFile:=True;
- end;
- procedure TCustomDaemonApplication.DoRun;
- begin
- try
- If Not Assigned(MapperClass) then
- DaemonError(SErrNoServiceMapper);
- CreateServiceMapper(FMapper);
- if InstallRun then
- InstallDaemons
- else If UnInstallRun then
- UnInstallDaemons
- else if RunDaemonsRun then
- RunDaemons
- else if Assigned(OnRun) then
- OnRun(Self)
- else if HasOption('h','help') then
- begin
- if IsConsole then
- ShowHelp;
- end
- else
- begin
- if IsConsole then
- ShowHelp
- else
- DaemonError(SErrNothingToDo,[ParamStr(0)]);
- end;
- {$ifdef svcdebug}DebugLog('Terminating');{$endif svcdebug}
- Terminate;
- {$ifdef svcdebug}DebugLog('Terminated');{$endif svcdebug}
- except
- Terminate;
- Raise
- end;
- end;
- procedure TCustomDaemonApplication.ShowException(E: Exception);
- begin
- Log(etError,E.Message);
- inherited ShowException(E)
- end;
- Procedure TCustomDaemonApplication.CreateDaemonInstance(Var ADaemon : TCustomDaemon; DaemonDef : TDaemonDef);
- begin
- ADaemon:=DaemonDef.DaemonClass.CreateNew(Self,0);
- end;
- function TCustomDaemonApplication.CreateDaemon(DaemonDef: TDaemonDef): TCustomDaemon;
- Var
- C : TDaemonController;
- begin
- CreateDaemonInstance(Result,DaemonDef);
- CreateDaemonController(C);
- C.FDaemon:=Result;
- Result.FController:=C;
- Result.FDaemonDef:=DaemonDef;
- If (Daemondef.Instance=Nil) then
- DaemonDef.Instance:=Result;
- end;
- procedure TCustomDaemonApplication.StopDaemons(Force: Boolean);
- Const
- ControlCodes : Array[Boolean] of DWord
- = (SERVICE_CONTROL_STOP,SERVICE_CONTROL_SHUTDOWN);
- Var
- L : TFPList;
- I : Integer;
- begin
- L:=TFPList.Create;
- try
- For I:=0 to ComponentCount-1 do
- If Components[i] is TDaemonController then
- L.Add(Components[i]);
- For I:=L.Count-1 downto 0 do
- TDaemonController(L[i]).Controller(ControlCodes[Force],0,Nil);
- finally
- L.Free;
- end;
- end;
- { TDaemonDefs }
- function TDaemonDefs.GetDaemonDef(Index : Integer): TDaemonDef;
- begin
- Result:=TDaemonDef(Items[index]);
- end;
- procedure TDaemonDefs.SetDaemonDef(Index : Integer; const AValue: TDaemonDef);
- begin
- Items[Index]:=AValue;
- end;
- procedure TDaemonDefs.BindClasses;
- Var
- D : TDaemonDef;
- I,J : Integer;
-
- begin
- For I:=0 to Count-1 do
- begin
- D:=GetDaemonDef(I);
- J:=DaemonClasses.IndexOf(D.DaemonClassName);
- If (J=-1) then
- DaemonError(SErrUnknownDaemonClass,[D.DaemonClassName])
- else
- D.FDaemonClass:=TCustomDaemonClass(DaemonClasses.Objects[J]);
- end;
- end;
- function TDaemonDefs.GetOwner: TPersistent;
- begin
- Result:=FOwner;
- end;
- constructor TDaemonDefs.Create(AOwner: TPersistent; AClass : TCollectionItemClass);
- begin
- Inherited Create(AClass);
- FOwner:=AOwner;
-
- end;
- function TDaemonDefs.IndexOfDaemonDef(Const DaemonName: String): Integer;
- begin
- Result:=Count-1;
- While (Result>=0) and (CompareText(GetDaemonDef(Result).Name,DaemonName)<>0) do
- Dec(Result);
- end;
- function TDaemonDefs.FindDaemonDef(Const DaemonName: String): TDaemonDef;
- Var
- I : Integer;
- begin
- I:=IndexOfDaemonDef(DaemonName);
- If I<>-1 then
- Result:=GetDaemonDef(I)
- else
- Result:=Nil;
- end;
- function TDaemonDefs.DaemonDefByName(Const DaemonName: String): TDaemonDef;
- begin
- Result:=FindDaemonDef(DaemonName);
- end;
- { TDaemonDef }
- procedure TDaemonDef.SetName(const AValue: String);
- begin
- If (AValue<>FName) then
- begin
- If (AValue<>'') and (Collection<>Nil)
- and (Collection is TDaemonDefs)
- and ((Collection as TDaemonDefs).IndexOfDaemonDef(AValue)<>-1) then
- DaemonError(SErrDuplicateName,[Avalue]);
- FName:=AValue;
- end;
- end;
- procedure TDaemonDef.SetWinBindings(const AValue: TWinBindings);
- begin
- FWinBindings.Assign(AValue);
- end;
- function TDaemonDef.GetDisplayName: string;
- begin
- Result:=Name;
- end;
- constructor TDaemonDef.Create(ACollection: TCollection);
- begin
- inherited Create(ACollection);
- FWinBindings:=TWinBindings.Create;
- FEnabled:=True;
- FOptions:=DefaultDaemonOptions;
- end;
- destructor TDaemonDef.Destroy;
- begin
- FreeAndNil(FWinBindings);
- inherited Destroy;
- end;
- { TCustomDaemonMapper }
- procedure TCustomDaemonMapper.SetDaemonDefs(const AValue: TDaemonDefs);
- begin
- if (FDaemonDefs=AValue) then
- exit;
- FDaemonDefs.Assign(AValue);
- end;
- procedure TCustomDaemonMapper.CreateDefs;
- begin
- FDaemonDefs:=TDaemonDefs.Create(Self,TDaemonDef);
- end;
- procedure TCustomDaemonMapper.DoOnCreate;
- begin
- If Assigned(FOnCreate) then
- FOnCreate(Self);
- end;
- procedure TCustomDaemonMapper.DoOnDestroy;
- begin
- If Assigned(FOnDestroy) then
- FOnDestroy(Self);
- end;
- procedure TCustomDaemonMapper.DoOnInstall;
- begin
- If Assigned(FOnInstall) then
- FOnInstall(Self);
- end;
- procedure TCustomDaemonMapper.DoOnUnInstall;
- begin
- If Assigned(FOnUnInstall) then
- FOnUnInstall(Self);
- end;
- procedure TCustomDaemonMapper.DoOnRun;
- begin
- If Assigned(FOnRun) then
- FOnRun(Self);
- end;
- constructor TCustomDaemonMapper.Create(AOwner: TComponent);
- begin
- CreateDefs; // First, otherwise streaming will fail.
- inherited Create(AOwner);
- DoOnCreate;
- end;
- destructor TCustomDaemonMapper.Destroy;
- begin
- DoOnDestroy;
- FreeAndNil(FDaemonDefs);
- inherited Destroy;
- end;
- { TDaemonThread }
- constructor TDaemonThread.Create(ADaemon: TCustomDaemon);
- begin
- FDaemon:=ADAemon;
- FDaemon.FThread:=Self;
- FreeOnTerminate:=False;
- Inherited Create(True);
- end;
- procedure TDaemonThread.Execute;
- begin
- If FDaemon.Start then
- begin
- FDaemon.Status:=csRunning;
- StartServiceExecute;
- if not FDaemon.Execute then
- begin
- While Not Terminated do
- CheckControlMessage(True);
- CheckControlMessage(False);
- end;
- end
- else
- begin
- FDaemon.Status:=csStopped;
- Application.Terminate;
- end;
- end;
- procedure TDaemonThread.HandleControlCode(ACode : DWord);
- Var
- CS : TCurrentStatus;
- CC,OK : Boolean;
- S : String;
- begin
- {$ifdef svcdebug}DebugLog('Handling control code '+IntToStr(ACode));{$endif svcdebug}
- CS:=FDaemon.Status;
- Try
- OK:=True;
- CC:=False;
- Case ACode of
- SERVICE_CONTROL_STOP : OK:=StopDaemon;
- SERVICE_CONTROL_PAUSE : OK:=PauseDaemon;
- SERVICE_CONTROL_CONTINUE : OK:=ContinueDaemon;
- SERVICE_CONTROL_SHUTDOWN : OK:=ShutDownDaemon;
- SERVICE_CONTROL_INTERROGATE : OK:=InterrogateDaemon;
- else
- CC:=True;
- FDaemon.HandleCustomCode(ACode);
- end;
- If not OK then
- FDaemon.Status:=CS;
- Except
- On E : Exception do
- begin
- // Shutdown MUST be done, in all other cases roll back status.
- If (ACode<>SERVICE_CONTROL_SHUTDOWN) then
- FDaemon.Status:=CS;
- If (ACode in [1..5]) then
- S:=SStatus[ACode]
- else
- S:=Format(SCustomCode,[ACode]);
- end;
- end;
- end;
- function TDaemonThread.StopDaemon: Boolean;
- begin
- FDaemon.Status:=csStopPending;
- Result:=FDaemon.Stop;
- If Result then
- begin
- FDaemon.Status:=csStopped;
- Terminate;
- end;
- end;
- function TDaemonThread.PauseDaemon: Boolean;
- begin
- FDaemon.Status:=csPausePending;
- Result:=FDaemon.Pause;
- If Result then
- begin
- FDaemon.Status:=csPaused;
- Suspend;
- end;
- end;
- function TDaemonThread.ContinueDaemon: Boolean;
- begin
- FDaemon.Status:=csContinuePending;
- Result:=FDaemon.Continue;
- If Result then
- FDaemon.Status:=csRunning;
- end;
- function TDaemonThread.ShutDownDaemon: Boolean;
- begin
- FDaemon.Status:=csStopPending;
- Try
- Result:=FDaemon.ShutDown;
- finally
- FDaemon.Status:=csStopped;
- Terminate;
- end;
- end;
- Function TDaemonThread.InterrogateDaemon: Boolean;
- begin
- FDaemon.ReportStatus;
- Result:=True;
- end;
- { ---------------------------------------------------------------------
- TDaemonController - Global implementation
- ---------------------------------------------------------------------}
- constructor TDaemonController.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FParams:=TStringList.Create;
- end;
- destructor TDaemonController.Destroy;
- begin
- FreeAndNil(FSysData);
- FreeAndNil(FParams);
- inherited Destroy;
- end;
- { TWinBindings }
- procedure TWinBindings.SetDependencies(const AValue: TDependencies);
- begin
- if (FDependencies<>AValue) then
- FDependencies.Assign(AValue);
- end;
- Constructor TWinBindings.Create;
- begin
- FDependencies:=TDependencies.Create(Self);
- end;
- destructor TWinBindings.Destroy;
- begin
- FreeAndNil(FDependencies);
- inherited Destroy;
- end;
- procedure TWinBindings.Assign(Source: TPersistent);
- Var
- WB : TWinBindings;
- begin
- if Source is TWinBindings then
- begin
- WB:=Source as TWinBindings;
- GroupName:=WB.GroupName;
- Password:=WB.PassWord;
- UserName:=WB.UserName;
- StartType:=WB.StartType;
- WaitHint:=WB.WaitHint;
- IDTag:=WB.IDTag;
- ServiceType:=WB.ServiceType;
- ErrorSeverity:=WB.ErrorSeverity;
- Dependencies.Assign(WB.Dependencies);
- ErrCode:=WB.ErrCode;
- Win32ErrCode:=WB.Win32ErrCode;
- end
- else
- inherited Assign(Source);
- end;
- { TDependency }
- function TDependency.GetDisplayName: string;
- begin
- Result:=Name;
- end;
- procedure TDependency.Assign(Source: TPersistent);
- Var
- D : TDependency;
- begin
- if Source is TDependency then
- begin
- D:=Source as TDependency;
- Name:=D.Name;
- IsGroup:=D.IsGroup;
- end
- else
- inherited Assign(Source);
- end;
- { TDependencies }
- function TDependencies.GetItem(Index: Integer): TDependency;
- begin
- Result:=TDependency(Inherited GetItem(Index));
- end;
- procedure TDependencies.SetItem(Index: Integer; Value: TDependency);
- begin
- Inherited SetItem(Index,Value);
- end;
- function TDependencies.GetOwner: TPersistent;
- begin
- Result:=FOwner;
- end;
- constructor TDependencies.Create(AOwner: TPersistent);
- begin
- Inherited Create(TDependency);
- FOwner:=AOwner;
- end;
- { TDaemonMapper }
- constructor TDaemonMapper.Create(AOwner: TComponent);
- begin
- CreateNew(AOwner,0);
- if (ClassType<>TDaemonMapper) and not (csDesigning in ComponentState) then
- begin
- if not InitInheritedComponent(Self,TDaemonMapper) then
- raise EStreamError.CreateFmt(SErrNoSTreaming, [ClassName]);
- end;
- end;
- constructor TDaemonMapper.CreateNew(AOwner: TComponent; Dummy: Integer);
- begin
- inherited Create(AOwner);
- end;
- Initialization
- {$ifdef svcdebug}
- StartLog;
- {$endif}
- SysInitDaemonApp;
- Finalization
- SysDoneDaemonApp;
- DoneDaemonApplication;
- {$ifdef svcdebug}
- EndLog;
- {$endif}
- end.
|