Delphi · 2025年8月14日

Delphi控制Windows服务

//注册服务
function InstallService(ServiceName, DisplayName: PWideChar; FileName: string; BWait: boolean):Boolean;
var
  SCManager: SC_HANDLE;
  Service: SC_HANDLE;
begin
  Result := False;
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCManager = 0 then Exit;
  try
    Service := CreateService(SCManager, //句柄
                             ServiceName, //服务名称
                             DisplayName, //显示服务名
                             SERVICE_ALL_ACCESS, //服务访问类型
                             SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS,//服务类型
                             SERVICE_AUTO_START, //自动启动服务
                             SERVICE_ERROR_IGNORE, //忽略错误
                             PWideChar(FileName), //启动的文件名
                             nil, nil, nil, nil, nil);
    if Service = 0 then Exit;
    Result := True;
    CloseServiceHandle(Service);
  finally
    CloseServiceHandle(SCManager);
  end;
end;

//卸载服务
function UninstallService(ServiceName: PWideChar):Boolean;
var
  SCManager: SC_HANDLE;
  Service: SC_HANDLE;
begin
  Result := False;
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCManager = 0 then Exit;
  try
    Service := OpenService(SCManager, ServiceName, SERVICE_ALL_ACCESS);
    try
      try
        ControlService(Service, SERVICE_CONTROL_STOP, Status);
        Result := DeleteService(Service);
      except
        on E:Exception do
        begin
          //
        end;
      end;
    finally
      CloseServiceHandle(Service);
    end;
  finally
    CloseServiceHandle(SCManager);
  end;
end;

//获取服务状态
function ServiceGetStatus(sMachine, sService: string ): Cardinal;
var
  schm,      //service control manager handle
  schs: SC_Handle;   //service handle
  ss: TServiceStatus;  //service status
  dwStat : DWord;  //current service status
begin
  Result := 0;
  dwStat := 0;
  schm := OpenSCManager(PChar(sMachine), Nil, SC_MANAGER_CONNECT);
  if(schm > 0)then
  begin
    //open a handle to the specified service
    schs := OpenService(schm, PChar(sService), SERVICE_QUERY_STATUS);
    if(schs > 0)then
    begin
      //retrieve the current status of the specified service
      if(QueryServiceStatus(schs, ss))then
      begin
        dwStat := ss.dwCurrentState;
      end;
      CloseServiceHandle(schs);  //close service handle
    end;
    CloseServiceHandle(schm);  // close service control manager handle
  end;
  Result := dwStat;
end;

//启动服务
function StartupService(const SvrName: string; BWait: boolean): Boolean;
var
  SCH, SvcSCH: SC_HANDLE;
  arg: PChar;
  dwStartType: DWORD;
begin
  Result := False;
  SCH := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCH <= 0 then Exit;
  SvcSCH := OpenService(SCH, PChar(SvrName), SERVICE_ALL_ACCESS);
  if SvcSCH <= 0 then Exit;
  try
    Result := StartService(SvcSCH, 0, arg);
    if BWait then
      WaitForService(SvcSCH, SERVICE_RUNNING);
  finally
    CloseServiceHandle(SvcSCH);
    CloseServiceHandle(SCH);
  end;
end;

//停止服务
function StopServices(const SvrName: string; BWait: boolean): Boolean;
var
  SCH, SvcSCH: SC_HANDLE;
  SS: TServiceStatus;
begin
  Result := False;
  SCH := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCH <= 0 then Exit;
  SvcSCH := OpenService(SCH, PChar(SvrName), SERVICE_ALL_ACCESS);
  if SvcSCH <= 0 then Exit;
  try
    Result := ControlService(SvcSCH, SERVICE_CONTROL_STOP, SS);
    if BWait then
      WaitForService(SvcSCH, SERVICE_STOPPED);
  finally
    CloseServiceHandle(SCH);
    CloseServiceHandle(SvcSCH);
  end;
    
  //重启服务
  function RestartServices(const SvrName: string; BWait: boolean): Boolean;
var
  SCH, SvcSCH: SC_HANDLE;
  arg: PChar;
  dwStartType: DWORD;
  ServiceStatus: _SERVICE_STATUS;
  SS: TServiceStatus;
begin
  Result := False;
  SCH := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if SCH <= 0 then Exit;
  SvcSCH := OpenService(SCH, PChar(SvrName), SERVICE_ALL_ACCESS);
  if SvcSCH <= 0 then Exit;

  if not ControlService(SvcSCH, SERVICE_CONTROL_INTERROGATE, ServiceStatus) then exit;
  if ServiceStatus.dwCurrentState = SERVICE_RUNNING then  //如果正在运行,则先停止服务
  begin
    ControlService(SvcSCH, SERVICE_CONTROL_STOP, SS);
    WaitForService(SvcSCH, SERVICE_STOPPED);
    //StopServices(SvrName, true);
  end;

  try
    Result := StartService(SvcSCH, 0, arg);
    if BWait then
      WaitForService(SvcSCH, SERVICE_RUNNING);
  finally
    CloseServiceHandle(SvcSCH);
    CloseServiceHandle(SCH);
  end;
end;

//等待服务操作
function WaitForService(ServiceHandle: Longword; AStatus: Longword): Boolean;
var
  PendingStatus: Longword;
  ServiceStatus: _SERVICE_STATUS;
  Error: Integer;
begin
  Result := False;
  case AStatus of
    SERVICE_RUNNING: PendingStatus := SERVICE_START_PENDING;
    SERVICE_STOPPED: PendingStatus := SERVICE_STOP_PENDING;
  end;
  repeat
    if not ControlService(ServiceHandle, SERVICE_CONTROL_INTERROGATE, ServiceStatus) then
    begin
      Break;
    end;
    if ServiceStatus.dwWin32ExitCode <> 0 then
      Break;
    Result := ServiceStatus.dwCurrentState = AStatus;
    if not Result and (ServiceStatus.dwCurrentState = PendingStatus) then
      Sleep(ServiceStatus.dwWaitHint)
    else
      Break;
  until Result;
end;
Pascal