mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-16 00:08:21 +02:00
213 lines
5.5 KiB
ObjectPascal
213 lines
5.5 KiB
ObjectPascal
unit DaemonUnit;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, DaemonApp, DaemonWorkerThread
|
|
{$IFDEF UNIX}
|
|
, DaemonSystemdInstallerUnit // Some systemd installer support for -install | -ininstall
|
|
{$ENDIF};
|
|
|
|
// -------------------------------------------------------------------------------
|
|
// Demo application on how to use the TDaemon application type
|
|
// 2/2022 by arminlinder@arminlinder.de
|
|
|
|
// Based on document
|
|
// "Taming the daemon: Writing cross-platform service applications in FPC/Lazarus"
|
|
// by Michaël Van Canneyt, February 4, 2007
|
|
// -------------------------------------------------------------------------------
|
|
|
|
const
|
|
DAEMON_VERSION = '1.2'; // Just for logging
|
|
|
|
type
|
|
|
|
{ TTestDaemon }
|
|
|
|
TTestDaemon = class(TDaemon)
|
|
procedure DataModuleAfterInstall(Sender: TCustomDaemon);
|
|
procedure DataModuleAfterUnInstall(Sender: TCustomDaemon);
|
|
procedure DataModuleContinue(Sender: TCustomDaemon; var OK: boolean);
|
|
procedure DataModulePause(Sender: TCustomDaemon; var OK: boolean);
|
|
procedure DataModuleStart(Sender: TCustomDaemon; var OK: boolean);
|
|
procedure DataModuleStop(Sender: TCustomDaemon; var OK: boolean);
|
|
private
|
|
FDaemonWorkerThread: TDaemonWorkerThread;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
procedure LogToFile(aMessage: string);
|
|
|
|
var
|
|
TestDaemon: TTestDaemon;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Quick and dirty write log message to file
|
|
// Note: TDaemonApplication has extensive logging capabilities built-in!
|
|
// ---------------------------------------------------------------------
|
|
|
|
procedure LogToFile(aMessage: string);
|
|
|
|
function TimeStamped(S: string): string;
|
|
// Return a timestamped copy of a string
|
|
|
|
begin
|
|
Result := FormatDateTime('hh:mm:ss', now) + ' ' + S;
|
|
end;
|
|
|
|
var
|
|
f: Text;
|
|
LogFilePath: string;
|
|
|
|
begin
|
|
// create a daily log file in the .exe directory
|
|
LogFilePath := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) +
|
|
FormatDateTime('YYYYMMDD', now) + '.log';
|
|
AssignFile(f, LogFilePath);
|
|
try
|
|
if FileExists(LogFilePath) then
|
|
Append(f)
|
|
else
|
|
begin
|
|
Rewrite(f);
|
|
writeln(f, TimeStamped('Log created'));
|
|
end;
|
|
Writeln(f, TimeStamped(aMessage));
|
|
finally
|
|
CloseFile(f);
|
|
end;
|
|
end;
|
|
|
|
{ TTestDaemon }
|
|
|
|
// -------------------------------
|
|
// Installation and deinstallation
|
|
// -------------------------------
|
|
// Note: Windows code is already in the DaemonApp unit
|
|
// Code here tries to approximate same functionality for Unix
|
|
|
|
procedure TTestDaemon.DataModuleAfterInstall(Sender: TCustomDaemon);
|
|
|
|
var
|
|
isInstalled: boolean;
|
|
FilePath: string;
|
|
|
|
begin
|
|
isInstalled := True;
|
|
{$IFDEF UNIX}
|
|
FilePath := GetSystemdControlFilePath(self.Name);
|
|
isInstalled := CreateSystemdControlFile(self, FilePath);
|
|
if not isInstalled then
|
|
LogToFile('Error creating systemd control file: ' + FilePath);
|
|
{$ENDIF}
|
|
if isInstalled then
|
|
LogToFile('Daemon installed, version:' + DAEMON_VERSION);
|
|
end;
|
|
|
|
procedure TTestDaemon.DataModuleAfterUnInstall(Sender: TCustomDaemon);
|
|
|
|
var
|
|
isUnInstalled: boolean;
|
|
FilePath: string;
|
|
|
|
begin
|
|
isUninstalled := True;
|
|
{$IFDEF UNIX}
|
|
FilePath := GetSystemdControlFilePath(self.Name);
|
|
isUnInstalled := RemoveSystemdControlFile(FilePath);
|
|
if not isUninstalled then
|
|
LogToFile('Error removing systemd control file: ' + FilePath);
|
|
{$ENDIF}
|
|
if isUninstalled then
|
|
LogToFile('Daemon uninstalled');
|
|
end;
|
|
|
|
// -----------------------
|
|
// Service control signals
|
|
// -----------------------
|
|
|
|
procedure TTestDaemon.DataModuleStart(Sender: TCustomDaemon; var OK: boolean);
|
|
|
|
begin
|
|
LogToFile(Format('Daemon received start signal, PID:%d', [GetProcessID]));
|
|
// Create a suspended worker thread
|
|
FDaemonWorkerThread := TDaemonWorkerThread.Create;
|
|
// Parametrize it
|
|
FDaemonWorkerThread.FreeOnTerminate := False;
|
|
// Start the worker
|
|
FDaemonWorkerThread.Start;
|
|
OK := True;
|
|
end;
|
|
|
|
procedure TTestDaemon.DataModulePause(Sender: TCustomDaemon; var OK: boolean);
|
|
// Note: Pause and resume signals are provided by Windows only
|
|
|
|
begin
|
|
LogToFile('Daemon recedived pause signal');
|
|
FDaemonWorkerThread.Suspend; // deprecated, yet still working
|
|
OK := True;
|
|
end;
|
|
|
|
procedure TTestDaemon.DataModuleContinue(Sender: TCustomDaemon; var OK: boolean);
|
|
// Note: Pause and resume signals are provided by Windows only
|
|
|
|
begin
|
|
LogToFile('Daemon recedived continue signal');
|
|
FDaemonWorkerThread.resume; // deprecated, yet still working
|
|
OK := True;
|
|
end;
|
|
|
|
procedure TTestDaemon.DataModuleStop(Sender: TCustomDaemon; var OK: boolean);
|
|
|
|
begin
|
|
LogToFile('Daemon received stop signal');
|
|
// stop and terminate the worker
|
|
FDaemonWorkerThread.Terminate;
|
|
// Wait for the thread to terminate.
|
|
FDaemonWorkerThread.WaitFor;
|
|
FDaemonWorkerThread.Free;
|
|
LogToFile('Daemon stopped');
|
|
OK := True;
|
|
end;
|
|
|
|
// --------------------------
|
|
// constructor and destructor
|
|
// --------------------------
|
|
|
|
constructor TTestDaemon.Create(AOwner: TComponent);
|
|
|
|
begin
|
|
inherited Create(AOwner);
|
|
// Nothing to do here, just for logging
|
|
LogToFile('Daemon object created');
|
|
end;
|
|
|
|
destructor TTestDaemon.Destroy;
|
|
|
|
begin
|
|
// Nothing to do here, just for logging
|
|
LogToFile('Daemon object destroyed');
|
|
inherited Destroy;
|
|
end;
|
|
|
|
// ----------------------------------------
|
|
// Daemon registration. Created by template
|
|
// ----------------------------------------
|
|
|
|
procedure RegisterDaemon;
|
|
begin
|
|
RegisterDaemonClass(TTestDaemon);
|
|
end;
|
|
|
|
initialization
|
|
RegisterDaemon;
|
|
end.
|