ServiceManager

From Free Pascal wiki
Revision as of 09:27, 12 December 2013 by A.fortuny (talk | contribs) (Some more details about the service name and which name to use)
Jump to navigationJump to search

ServiceManager

For Windows, the fcl-extra package contains a unit called ServiceManager.

The example below checks whether the SamSs (Security Accounts Manager; should always be running) service is running. (Command line equivalent sc query samss).

Please note that if you develop your own service using the Lazdaemon package, the service name you must use is important. While the commands NET START and NET STOP use the service display name, the command SC and the code below use the service internal name. The display name is the one given to the property "DisplayName" of the item created in the DaemonDefs items. The service name is the property "Name" of the same item. The display name is the one currently displayed in the Name column by the MS services manager applet (services.msc) Let's use an example to clarify this. Assume you have written a service application called myService.exe in which there is one item in the DaemonDefs. The item has a name of "MyServ" and the associated "DisplayName" property has the value of "Internal build service". Using the command line as administrator you can:

Install the service:

C:\> \your\path\to\application\myService.exe --install (or /install, -install works too)

Activate the service:

C:\> net start "Internal build service" (do not forget double quotes when multiple words are needed)

or alternatively

C:\> sc start "MyServ"

To stop the service

C:\> net stop "Internal build service"

or alternatively

C:\> sc stop "MyServ"

So the code snippet to call the function below whould be in our case:

...

if IsServiceRunning('MyServ') then

...


program ServiceTest;
// Check if a certain process is running.
{$mode objfpc}{$H+}
uses
  Classes,
  SysUtils,
  ServiceManager,
  JwaWinSvc {for services declarations};

function IsServiceRunning(ServiceName: string): boolean;
  {description Checks if a Windows service is running}
var
  Services: TServiceManager;
  ServiceStatus: TServiceStatus;
begin
  //Check for existing services
  //equivalent to sc query <servicename>
  Services := TServiceManager.Create(nil);
  try
    try
      Services.Acces := SC_MANAGER_CONNECT; //Note typo in property.
      //We don't need more access permissions than this; by default
      //the servicemanager is trying to get all access
      Services.Connect; //Now connect with requested access level
      Services.GetServiceStatus(ServiceName, ServiceStatus);
      if ServiceStatus.dwCurrentState = SERVICE_RUNNING then
      begin
        Result := True;
      end
      else
      begin
        Result := False;
      end;
      Services.Disconnect;
    except
      on E: EServiceManager do
      begin
        // A missing service might throw a missing handle exception? No?
      {LogOutput('Error getting service information for ' + ServiceName +
        '. Technical details: ' + E.ClassName + '/' + E.Message);}
        Result := False;
        raise; //rethrow original exception
      end;
      on E: Exception do
      begin
      {LogOutput('Error getting service information for ' + ServiceName +
        '. Technical details: ' + E.ClassName + '/' + E.Message);
        }
        Result := False;
        raise; //rethrow original exception
      end;
    end;
  finally
    Services.Free;
  end;
end;

const
  ServiceToTest = 'SamSs';

//Security Accounts Manager, should be running, at least on Vista
begin
  WriteLn('Starting test for ' + ServiceToTest + ' service.');
  if IsServiceRunning(ServiceToTest) then
  begin
    WriteLn('The ' + ServiceToTest + ' service is running');
  end
  else
  begin
    WriteLn('The ' + ServiceToTest + ' service is not running');
  end;
end.

See also