对NT服务型程序的控制代码。如安装服务、启动、停止服务、取服务状态等。
{*******************************************************************************
 XOtecExpress Visual Component Library Copyright (c) 2008 XOtec Studio.
   XOtecExpress Visual Component Library Copyright (c) 2008 XOtec Studio.
 By: PengJunLi Build: 2008-05-24
   By: PengJunLi Build: 2008-05-24 E-mail: iinsnian@126.com  xotec@vip.qq.com
   E-mail: iinsnian@126.com  xotec@vip.qq.com QQ:442801172  (陆岛工作室)
   QQ:442801172  (陆岛工作室)
 *******************************************************************************}
*******************************************************************************}
 unit xtSrvUnit;
unit xtSrvUnit;
 interface
interface
 uses Windows, Messages,  SysUtils, Classes, Forms, WinSvc, SvcMgr;
uses Windows, Messages,  SysUtils, Classes, Forms, WinSvc, SvcMgr;
 const
const SM_BASE                      = WM_USER + 1736;
  SM_BASE                      = WM_USER + 1736; SM_INITIALIZE                = SM_BASE + 1;
  SM_INITIALIZE                = SM_BASE + 1; SM_SHUTDOWN                  = SM_BASE + 2;
  SM_SHUTDOWN                  = SM_BASE + 2; SM_BREAKWAIT                 = SM_BASE + 5;
  SM_BREAKWAIT                 = SM_BASE + 5; SM_USERSINFOUPDATE           = SM_BASE + 11;
  SM_USERSINFOUPDATE           = SM_BASE + 11;
 type
type EServiceError = class(Exception);
  EServiceError = class(Exception); TxtServiceStatus = (ssUnknow, ssStopped, ssStartPending, ssStopPending, ssRuning, ssContinuePending, ssPausePending, ssPaused);
  TxtServiceStatus = (ssUnknow, ssStopped, ssStartPending, ssStopPending, ssRuning, ssContinuePending, ssPausePending, ssPaused);
 { TxtServiceApplication }
  { TxtServiceApplication } 
   TxtServiceApplication = class(TServiceApplication)
  TxtServiceApplication = class(TServiceApplication) private
  private FEventLogger: TEventLogger;
    FEventLogger: TEventLogger; procedure OnExceptionHandler(Sender: TObject; E: Exception);
    procedure OnExceptionHandler(Sender: TObject; E: Exception); public
  public constructor Create(AOwner: TComponent); override;
    constructor Create(AOwner: TComponent); override; destructor Destroy; override;
    destructor Destroy; override; procedure Run; override;
    procedure Run; override; procedure ContinueRun;
    procedure ContinueRun; end;
  end;

 function Application: TxtServiceApplication;
function Application: TxtServiceApplication;
 function ServerInstalling: Boolean;
function ServerInstalling: Boolean;
 function IsServerIsRuning(ServiceName: string): Boolean;
function IsServerIsRuning(ServiceName: string): Boolean;
 //取服务状态
//取服务状态 function GetServiceStatus(ServiceName: string): TxtServiceStatus;
function GetServiceStatus(ServiceName: string): TxtServiceStatus; //服务是否正在运行
//服务是否正在运行 function IsServiceRuning(ServiceName: string): Boolean;
function IsServiceRuning(ServiceName: string): Boolean; //服务是否已停止
//服务是否已停止 function IsServiceStopped(ServiceName: string): Boolean;
function IsServiceStopped(ServiceName: string): Boolean;
 //启动服务
//启动服务 function StartService(ServiceName: string): Boolean; overload; // Simple start
function StartService(ServiceName: string): Boolean; overload; // Simple start function StartService(ServiceName: string; NumberOfArgument: DWORD; ServiceArgVectors: PChar): Boolean;overload; // More complex start
function StartService(ServiceName: string; NumberOfArgument: DWORD; ServiceArgVectors: PChar): Boolean;overload; // More complex start //停止服务
//停止服务 function StopService(ServiceName: string): Boolean;
function StopService(ServiceName: string): Boolean; //暂停服务
//暂停服务 function PauseService(ServiceName: string): Boolean;
function PauseService(ServiceName: string): Boolean; //继续服务
//继续服务 function ContinueService(ServiceName: string): Boolean;
function ContinueService(ServiceName: string): Boolean; //关闭服务
//关闭服务 function ShutdownService(ServiceName: string): Boolean;
function ShutdownService(ServiceName: string): Boolean; //禁止服务启动
//禁止服务启动 function DisableService(ServiceName: string): Boolean;
function DisableService(ServiceName: string): Boolean;
 //服务是否已安装
//服务是否已安装 function IsServiceInstalled(ServiceName: string): Boolean;
function IsServiceInstalled(ServiceName: string): Boolean; //安装服务
//安装服务 function InstallService(ServiceName, DisplayName, Filename: string; ServiceDescription: string=''): Boolean;
function InstallService(ServiceName, DisplayName, Filename: string; ServiceDescription: string=''): Boolean; //反安装服务
//反安装服务 function UnInstallService(ServiceName: string): Boolean;
function UnInstallService(ServiceName: string): Boolean; //为服务程序添加描述
//为服务程序添加描述 procedure ServiceUpdateDescription(const ServiceName, Description: string);
procedure ServiceUpdateDescription(const ServiceName, Description: string);
 //取得系统中所有服务列表
//取得系统中所有服务列表 function GetNtServiceList(sMachine: string; AList: TStrings): Boolean;
function GetNtServiceList(sMachine: string; AList: TStrings): Boolean;
 function InitServiceDesktop: boolean;
function InitServiceDesktop: boolean; procedure DoneServiceDeskTop;
procedure DoneServiceDeskTop;
 implementation
implementation
 uses Registry;
uses Registry;
 const
const DefaultWindowStation         = 'WinSta0';
  DefaultWindowStation         = 'WinSta0'; DefaultDesktop               = 'Default';
  DefaultDesktop               = 'Default';
 var
var hwinstaSave: HWINSTA;
  hwinstaSave: HWINSTA; hdeskSave: HDESK;
  hdeskSave: HDESK; hwinstaUser: HWINSTA;
  hwinstaUser: HWINSTA; hdeskUser: HDESK;
  hdeskUser: HDESK; FContinueHandlingMessages: Boolean = true;
  FContinueHandlingMessages: Boolean = true;
 { ServerInstalling }
{ ServerInstalling }
 function ServerInstalling: Boolean;
function ServerInstalling: Boolean; begin
begin Result := FindCmdLineSwitch('INSTALL',['-','/','/'], True) or
  Result := FindCmdLineSwitch('INSTALL',['-','/','/'], True) or FindCmdLineSwitch('UNINSTALL',['-','/','/'], True);
            FindCmdLineSwitch('UNINSTALL',['-','/','/'], True); end;
end;
 { GetServiceStatus }
{ GetServiceStatus }
 function GetServiceStatus(ServiceName: string): TxtServiceStatus;
function GetServiceStatus(ServiceName: string): TxtServiceStatus; var
var ServiceStatus: TServiceStatus;
  ServiceStatus: TServiceStatus; hSCManager, ServiceHandle: SC_Handle;
  hSCManager, ServiceHandle: SC_Handle; begin
begin Result := ssUnknow;
  Result := ssUnknow; if (Trim(ServiceName)='') then Exit;
  if (Trim(ServiceName)='') then Exit;
 hSCManager := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
  hSCManager := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); if hSCManager<>0 then
  if hSCManager<>0 then begin
  begin ServiceHandle := OpenService(hSCManager, PChar(ServiceName), SERVICE_QUERY_STATUS);
    ServiceHandle := OpenService(hSCManager, PChar(ServiceName), SERVICE_QUERY_STATUS); if ServiceHandle<>0 then
    if ServiceHandle<>0 then begin
    begin QueryServiceStatus(ServiceHandle, ServiceStatus);
      QueryServiceStatus(ServiceHandle, ServiceStatus); CloseServiceHandle(ServiceHandle);
      CloseServiceHandle(ServiceHandle); end;
    end; CloseServiceHandle(hSCManager);
    CloseServiceHandle(hSCManager); end;
  end;
 case ServiceStatus.dwCurrentState of
  case ServiceStatus.dwCurrentState of SERVICE_STOPPED         : Result := ssStopped;
    SERVICE_STOPPED         : Result := ssStopped; SERVICE_START_PENDING   : Result := ssStartPending;
    SERVICE_START_PENDING   : Result := ssStartPending; SERVICE_STOP_PENDING    : Result := ssStopPending;
    SERVICE_STOP_PENDING    : Result := ssStopPending; SERVICE_RUNNING         : Result := ssRuning;
    SERVICE_RUNNING         : Result := ssRuning; SERVICE_CONTINUE_PENDING: Result := ssContinuePending;
    SERVICE_CONTINUE_PENDING: Result := ssContinuePending; SERVICE_PAUSE_PENDING   : Result := ssPausePending;
    SERVICE_PAUSE_PENDING   : Result := ssPausePending; SERVICE_PAUSED          : Result := ssPaused;
    SERVICE_PAUSED          : Result := ssPaused; end;
  end; end;
end;
 { IsServiceRuning }
{ IsServiceRuning }
 function IsServiceRuning(ServiceName: string): Boolean;
function IsServiceRuning(ServiceName: string): Boolean; begin
begin Result := (GetServiceStatus(ServiceName) = ssRuning);
  Result := (GetServiceStatus(ServiceName) = ssRuning); end;
end;
 { IsServiceStopped }
{ IsServiceStopped }
 function IsServiceStopped(ServiceName: string): Boolean;
function IsServiceStopped(ServiceName: string): Boolean; begin
begin Result := (GetServiceStatus(ServiceName) = ssStopped);
  Result := (GetServiceStatus(ServiceName) = ssStopped); end;
end;
 { StartService }
{ StartService }
 function StartService(ServiceName: string): Boolean; overload; // Simple start
function StartService(ServiceName: string): Boolean; overload; // Simple start begin
begin Result := StartService(ServiceName, 0, nil);
  Result := StartService(ServiceName, 0, nil); end;
end;
 function StartService(ServiceName: string; NumberOfArgument: DWORD; ServiceArgVectors: PChar): Boolean;overload; // More complex start
function StartService(ServiceName: string; NumberOfArgument: DWORD; ServiceArgVectors: PChar): Boolean;overload; // More complex start var
var SCManager, hService: SC_HANDLE;
  SCManager, hService: SC_HANDLE; begin
begin Result := False;
   Result := False; if (Trim(ServiceName)='') then Exit;
  if (Trim(ServiceName)='') then Exit; 
   SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
   SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); Result := SCManager <> 0;
   Result := SCManager <> 0; if Result then
   if Result then try
   try hService := OpenService(SCManager, PChar(ServiceName), SERVICE_ALL_ACCESS);
     hService := OpenService(SCManager, PChar(ServiceName), SERVICE_ALL_ACCESS); Result := hService <> 0;
     Result := hService <> 0; if (hService <> 0) then
     if (hService <> 0) then try
     try Result := WinSvc.StartService(hService, NumberOfArgument, PChar(ServiceArgVectors));
       Result := WinSvc.StartService(hService, NumberOfArgument, PChar(ServiceArgVectors)); if not Result and (GetLastError = ERROR_SERVICE_ALREADY_RUNNING) then
       if not Result and (GetLastError = ERROR_SERVICE_ALREADY_RUNNING) then Result := True;
         Result := True; finally
     finally CloseServiceHandle(hService);
       CloseServiceHandle(hService); end;
     end; finally
   finally CloseServiceHandle(SCManager);
     CloseServiceHandle(SCManager); end;
   end; end;
end;
 function DoControlService(ServiceName: string; ControlFalg: Cardinal): Boolean;
function DoControlService(ServiceName: string; ControlFalg: Cardinal): Boolean; var
var ServiceStatus: TServiceStatus;
  ServiceStatus: TServiceStatus; SCManager, hService: SC_HANDLE;
  SCManager, hService: SC_HANDLE; begin
begin Result := False;
  Result := False; if (Trim(ServiceName)='') then Exit;
  if (Trim(ServiceName)='') then Exit;
 SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
   SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if SCManager<>0 then
  if SCManager<>0 then begin
  begin hService := OpenService(SCManager, PChar(ServiceName), SERVICE_ALL_ACCESS);
     hService := OpenService(SCManager, PChar(ServiceName), SERVICE_ALL_ACCESS); if hService<>0 then
    if hService<>0 then begin
    begin Result := ControlService(hService, ControlFalg, ServiceStatus);
      Result := ControlService(hService, ControlFalg, ServiceStatus); CloseServiceHandle(hService);
      CloseServiceHandle(hService); end;
    end; CloseServiceHandle(SCManager);
    CloseServiceHandle(SCManager); end;
  end; end;
end;
 { StopService }
{ StopService }
 function StopService(ServiceName: string): Boolean;
function StopService(ServiceName: string): Boolean; begin
begin Result := DoControlService(ServiceName, SERVICE_CONTROL_STOP);
  Result := DoControlService(ServiceName, SERVICE_CONTROL_STOP); end;
end; { PauseService }
{ PauseService }
 function PauseService(ServiceName: string): Boolean;
function PauseService(ServiceName: string): Boolean; begin
begin Result := DoControlService(ServiceName, SERVICE_CONTROL_PAUSE);
  Result := DoControlService(ServiceName, SERVICE_CONTROL_PAUSE); end;
end;
 { ContinueService }
{ ContinueService }
 function ContinueService(ServiceName: string): Boolean;
function ContinueService(ServiceName: string): Boolean; begin
begin Result := DoControlService(ServiceName, SERVICE_CONTROL_CONTINUE);
  Result := DoControlService(ServiceName, SERVICE_CONTROL_CONTINUE); end;
end;
 { ShutdownService }
{ ShutdownService }
 function ShutdownService(ServiceName: string): Boolean;
function ShutdownService(ServiceName: string): Boolean; begin
begin Result := DoControlService(ServiceName, SERVICE_CONTROL_SHUTDOWN);
  Result := DoControlService(ServiceName, SERVICE_CONTROL_SHUTDOWN); end;
end;
 { DisableService }
{ DisableService }
 function DisableService(ServiceName: string): Boolean;
function DisableService(ServiceName: string): Boolean; var
var SCManager, ServiceHandle: SC_HANDLE;
  SCManager, ServiceHandle: SC_HANDLE; begin
begin Result := False;
  Result := False; if (Trim(ServiceName)='') then Exit;
  if (Trim(ServiceName)='') then Exit;
 SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if SCManager<>0 then
  if SCManager<>0 then begin
  begin ServiceHandle := OpenService(SCManager, PChar(ServiceName), SERVICE_CHANGE_CONFIG);
    ServiceHandle := OpenService(SCManager, PChar(ServiceName), SERVICE_CHANGE_CONFIG); if ServiceHandle<>0 then
    if ServiceHandle<>0 then begin
    begin ChangeServiceConfig(ServiceHandle,
      ChangeServiceConfig(ServiceHandle, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE,
                          SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, nil, nil, nil, nil, nil, nil, nil);
                          nil, nil, nil, nil, nil, nil, nil); CloseServiceHandle(ServiceHandle);
      CloseServiceHandle(ServiceHandle); Result := True;
      Result := True; end;
    end; CloseServiceHandle(SCManager);
    CloseServiceHandle(SCManager); end;
  end; end;
end;
 { InstallService }
{ InstallService }
 function InstallService(ServiceName, DisplayName, Filename: string; ServiceDescription: string=''): Boolean;
function InstallService(ServiceName, DisplayName, Filename: string; ServiceDescription: string=''): Boolean; var
var SCManager, ServiceHandle: SC_HANDLE;
  SCManager, ServiceHandle: SC_HANDLE; begin
begin Result := False;
  Result := False; if (Trim(ServiceName)='') and not FileExists(Filename) then Exit;
  if (Trim(ServiceName)='') and not FileExists(Filename) then Exit; 
   SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  SCManager := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if SCManager = 0 then Exit;
  if SCManager = 0 then Exit; 
   try
  try ServiceHandle := CreateService(SCManager, PChar(ServiceName), PChar(DisplayName),
    ServiceHandle := CreateService(SCManager, PChar(ServiceName), PChar(DisplayName), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS,
                                   SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, PChar(Filename),
                                   SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, PChar(Filename), nil, nil, nil, nil, nil);
                                   nil, nil, nil, nil, nil);
 if IsServiceInstalled(ServiceName) and (ServiceDescription<>'') then
    if IsServiceInstalled(ServiceName) and (ServiceDescription<>'') then ServiceUpdateDescription(ServiceName, ServiceDescription);
      ServiceUpdateDescription(ServiceName, ServiceDescription); CloseServiceHandle(ServiceHandle);
    CloseServiceHandle(ServiceHandle); Result := ServiceHandle<>0;
    Result := ServiceHandle<>0; finally
  finally CloseServiceHandle(SCManager);
    CloseServiceHandle(SCManager); end;
  end; end;
end;
 { UnInstallService }
{ UnInstallService }
 function UnInstallService(ServiceName: string): Boolean;
function UnInstallService(ServiceName: string): Boolean; var
var SCManager, ServiceHandle: SC_HANDLE;
  SCManager, ServiceHandle: SC_HANDLE; begin
begin Result := False;
  Result := False; if (Trim(ServiceName)='') then Exit;
  if (Trim(ServiceName)='') then Exit;
 SCManager := OpenSCManager(nil,nil,GENERIC_WRITE);
  SCManager := OpenSCManager(nil,nil,GENERIC_WRITE); if SCManager = 0 then Exit;
  if SCManager = 0 then Exit; try
  try ServiceHandle := OpenService(SCManager, PChar(ServiceName), _DELETE);
    ServiceHandle := OpenService(SCManager, PChar(ServiceName), _DELETE); Result := DeleteService(ServiceHandle);
    Result := DeleteService(ServiceHandle); CloseServiceHandle(ServiceHandle);
    CloseServiceHandle(ServiceHandle); finally
  finally CloseServiceHandle(SCManager);
    CloseServiceHandle(SCManager); end;
  end; end;
end;
 procedure ServiceUpdateDescription(const ServiceName, Description: string);
procedure ServiceUpdateDescription(const ServiceName, Description: string); var
var reg: TRegistry;
  reg: TRegistry; begin
begin reg := TRegistry.Create;
  reg := TRegistry.Create; try
  try with reg do begin
    with reg do begin RootKey := HKEY_LOCAL_MACHINE;
      RootKey := HKEY_LOCAL_MACHINE; if OpenKey('SYSTEM/CurrentControlSet/Services/' + ServiceName, False) then
      if OpenKey('SYSTEM/CurrentControlSet/Services/' + ServiceName, False) then begin
      begin WriteString('Description', Description);
         WriteString('Description', Description); end;
         end; CloseKey;
         CloseKey; end;
      end; finally
   finally reg.Free;
     reg.Free; end;
   end; end;
end;
 { IsServiceInstalled }
{ IsServiceInstalled }
 function IsServiceInstalled(ServiceName: string): Boolean;
function IsServiceInstalled(ServiceName: string): Boolean; var
var Mgr, Svc: Integer;
  Mgr, Svc: Integer; begin
begin Result := False;
  Result := False; if (Trim(ServiceName)='') then Exit;
  if (Trim(ServiceName)='') then Exit;
 Mgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  Mgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS); if Mgr <> 0 then
  if Mgr <> 0 then begin
  begin Svc := OpenService(Mgr, PChar(ServiceName), SERVICE_ALL_ACCESS);
    Svc := OpenService(Mgr, PChar(ServiceName), SERVICE_ALL_ACCESS); Result := Svc <> 0;
    Result := Svc <> 0; if Result then
    if Result then CloseServiceHandle(Svc);
      CloseServiceHandle(Svc); CloseServiceHandle(Mgr);
    CloseServiceHandle(Mgr); end;
  end; end;
end;
 { IsServerIsRuning }
{ IsServerIsRuning }
 function IsServerIsRuning(ServiceName: string): Boolean;
function IsServerIsRuning(ServiceName: string): Boolean; begin
begin Result := False;
  Result := False; 
   if (Trim(ServiceName)<>'') and not ServerInstalling then
  if (Trim(ServiceName)<>'') and not ServerInstalling then begin
  begin CreateMutex(nil, True, PChar(ServiceName + '_Mutex'));
    CreateMutex(nil, True, PChar(ServiceName + '_Mutex')); Result := GetLastError = ERROR_ALREADY_EXISTS;
    Result := GetLastError = ERROR_ALREADY_EXISTS; end;
  end; end;
end;
 function GetNtServiceList(sMachine: string; AList: TStrings): Boolean;
function GetNtServiceList(sMachine: string; AList: TStrings): Boolean; var
var i: integer;
   i: integer; sName, sDisplay: string;
   sName, sDisplay: string; SCManager: SC_Handle;
   SCManager: SC_Handle; nBytesNeeded, nServices, nResumeHandle: Cardinal;
   nBytesNeeded, nServices, nResumeHandle: Cardinal; ServiceStatusRecs: array[0..511] of TEnumServiceStatus;
   ServiceStatusRecs: array[0..511] of TEnumServiceStatus; begin
begin Result := false;
   Result := false; SCManager := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_ALL_ACCESS);
   SCManager := OpenSCManager(PChar(sMachine), nil, SC_MANAGER_ALL_ACCESS); try
   try if (SCManager = 0) then Exit;
     if (SCManager = 0) then Exit; nResumeHandle := 0;
     nResumeHandle := 0; while True do
     while True do begin
     begin EnumServicesStatus(SCManager, SERVICE_WIN32, SERVICE_STATE_ALL, ServiceStatusRecs[0], SizeOf(ServiceStatusRecs),
       EnumServicesStatus(SCManager, SERVICE_WIN32, SERVICE_STATE_ALL, ServiceStatusRecs[0], SizeOf(ServiceStatusRecs), nBytesNeeded, nServices, nResumeHandle);
         nBytesNeeded, nServices, nResumeHandle); 
          for i := 0 to nServices - 1 do
       for i := 0 to nServices - 1 do begin
       begin sName := ServiceStatusRecs[i].lpServiceName;
         sName := ServiceStatusRecs[i].lpServiceName; sName := StringReplace(sName, '=', '?', [rfReplaceAll, rfIgnoreCase]);
         sName := StringReplace(sName, '=', '?', [rfReplaceAll, rfIgnoreCase]);
 sDisplay := ServiceStatusRecs[i].lpDisplayName;
         sDisplay := ServiceStatusRecs[i].lpDisplayName; sDisplay := StringReplace(sDisplay, '=', '#13#10', [rfReplaceAll, rfIgnoreCase]);
         sDisplay := StringReplace(sDisplay, '=', '#13#10', [rfReplaceAll, rfIgnoreCase]); sDisplay := StringReplace(sDisplay, '=', '#13', [rfReplaceAll, rfIgnoreCase]);
         sDisplay := StringReplace(sDisplay, '=', '#13', [rfReplaceAll, rfIgnoreCase]); sDisplay := StringReplace(sDisplay, '=', '#10', [rfReplaceAll, rfIgnoreCase]);
         sDisplay := StringReplace(sDisplay, '=', '#10', [rfReplaceAll, rfIgnoreCase]); AList.Add(sName + '=' + sDisplay);
         AList.Add(sName + '=' + sDisplay); end;
       end; 
        if nBytesNeeded = 0 then Break;
       if nBytesNeeded = 0 then Break; end;
     end; Result := True;
     Result := True; finally
   finally CloseServiceHandle(SCManager);
     CloseServiceHandle(SCManager); end;
   end; end;
end;
 { InitServiceDesktop }
{ InitServiceDesktop }
 function InitServiceDesktop: boolean;
function InitServiceDesktop: boolean; var
var dwThreadId: DWORD;
  dwThreadId: DWORD; begin
begin dwThreadId := GetCurrentThreadID;
  dwThreadId := GetCurrentThreadID; // Ensure connection to service window station and desktop, and
  // Ensure connection to service window station and desktop, and // save their handles.
  // save their handles. hwinstaSave := GetProcessWindowStation;
  hwinstaSave := GetProcessWindowStation; hdeskSave   := GetThreadDesktop(dwThreadId);
  hdeskSave   := GetThreadDesktop(dwThreadId);

 hwinstaUser := OpenWindowStation(DefaultWindowStation, FALSE, MAXIMUM_ALLOWED);
  hwinstaUser := OpenWindowStation(DefaultWindowStation, FALSE, MAXIMUM_ALLOWED); if hwinstaUser = 0 then
  if hwinstaUser = 0 then begin
  begin OutputDebugString(PChar('OpenWindowStation failed' +  SysErrorMessage(GetLastError)));
    OutputDebugString(PChar('OpenWindowStation failed' +  SysErrorMessage(GetLastError))); Result := false;
    Result := false; exit;
    exit; end;
  end;
 if not SetProcessWindowStation(hwinstaUser)  then
  if not SetProcessWindowStation(hwinstaUser)  then begin
  begin OutputDebugString('SetProcessWindowStation failed');
    OutputDebugString('SetProcessWindowStation failed'); Result := false;
    Result := false; exit;
    exit; end;
  end;
 hdeskUser := OpenDesktop(DefaultDesktop, 0, FALSE, MAXIMUM_ALLOWED);
  hdeskUser := OpenDesktop(DefaultDesktop, 0, FALSE, MAXIMUM_ALLOWED); if hdeskUser = 0 then
  if hdeskUser = 0 then begin
  begin OutputDebugString('OpenDesktop failed');
    OutputDebugString('OpenDesktop failed'); SetProcessWindowStation(hwinstaSave);
    SetProcessWindowStation(hwinstaSave); CloseWindowStation(hwinstaUser);
    CloseWindowStation(hwinstaUser); Result := false;
    Result := false; exit;
    exit; end;
  end; Result := SetThreadDesktop(hdeskUser);
  Result := SetThreadDesktop(hdeskUser); if not Result then
  if not Result then OutputDebugString(PChar('SetThreadDesktop' + SysErrorMessage(GetLastError)));
    OutputDebugString(PChar('SetThreadDesktop' + SysErrorMessage(GetLastError))); end;
end;
 { DoneServiceDeskTop }
{ DoneServiceDeskTop }
 procedure DoneServiceDeskTop;
procedure DoneServiceDeskTop; begin
begin // Restore window station and desktop.
  // Restore window station and desktop. SetThreadDesktop(hdeskSave);
  SetThreadDesktop(hdeskSave); SetProcessWindowStation(hwinstaSave);
  SetProcessWindowStation(hwinstaSave); if hwinstaUser <> 0 then
  if hwinstaUser <> 0 then CloseWindowStation(hwinstaUser);
    CloseWindowStation(hwinstaUser); if hdeskUser <> 0 then
  if hdeskUser <> 0 then CloseDesktop(hdeskUser);
    CloseDesktop(hdeskUser); end;
end;
 { TServiceStartThread }
{ TServiceStartThread }
 type
type TServiceTableEntryArray = array of TServiceTableEntry;
  TServiceTableEntryArray = array of TServiceTableEntry;
 TServiceStartThread = class(TThread)
  TServiceStartThread = class(TThread) private
  private FServiceStartTable: TServiceTableEntryArray;
    FServiceStartTable: TServiceTableEntryArray; protected
  protected procedure DoTerminate; override;
    procedure DoTerminate; override; procedure Execute; override;
    procedure Execute; override; public
  public constructor Create(Services: TServiceTableEntryArray);
    constructor Create(Services: TServiceTableEntryArray); end;
  end;
 constructor TServiceStartThread.Create(Services: TServiceTableEntryArray);
constructor TServiceStartThread.Create(Services: TServiceTableEntryArray); begin
begin FreeOnTerminate := False;
  FreeOnTerminate := False; ReturnValue := 0;
  ReturnValue := 0; FServiceStartTable := Services;
  FServiceStartTable := Services; inherited Create(False);
  inherited Create(False); end;
end;
 procedure TServiceStartThread.DoTerminate;
procedure TServiceStartThread.DoTerminate; begin
begin inherited DoTerminate;
  inherited DoTerminate; // Application run as application on NT or application run on the Win 9x
  // Application run as application on NT or application run on the Win 9x if (ReturnValue = ERROR_FAILED_SERVICE_CONTROLLER_) or
  if (ReturnValue = ERROR_FAILED_SERVICE_CONTROLLER_) or (ReturnValue = ERROR_CALL_NOT_IMPLEMENTED)
     (ReturnValue = ERROR_CALL_NOT_IMPLEMENTED) then
  then begin
  begin // for break Application.ProcessMessages loop
    // for break Application.ProcessMessages loop FContinueHandlingMessages := False;
    FContinueHandlingMessages := False; // Send a fake message to Application, for a breaking WaitMessage-loop
    // Send a fake message to Application, for a breaking WaitMessage-loop PostMessage(Forms.Application.Handle, SM_BREAKWAIT, 0, 0);
    PostMessage(Forms.Application.Handle, SM_BREAKWAIT, 0, 0); end
  end else
  else PostMessage(Forms.Application.Handle, WM_QUIT, 0, 0);
    PostMessage(Forms.Application.Handle, WM_QUIT, 0, 0); end;
end;
 procedure TServiceStartThread.Execute;
procedure TServiceStartThread.Execute; begin
begin if StartServiceCtrlDispatcher(FServiceStartTable[0]) then
  if StartServiceCtrlDispatcher(FServiceStartTable[0]) then ReturnValue := 0 else
    ReturnValue := 0 else ReturnValue := GetLastError;
    ReturnValue := GetLastError; end;
end;
 { DoneServiceApplication }
{ DoneServiceApplication }
 procedure DoneServiceApplication;
procedure DoneServiceApplication; begin
begin with Forms.Application do
  with Forms.Application do begin
  begin if Handle <> 0 then ShowOwnedPopups(Handle, False);
    if Handle <> 0 then ShowOwnedPopups(Handle, False); ShowHint := False;
    ShowHint := False; Destroying;
    Destroying; DestroyComponents;
    DestroyComponents; end;
  end; with Application do
  with Application do begin
  begin Destroying;
    Destroying; DestroyComponents;
    DestroyComponents; end;
  end; end;
end;
 { TxtServiceApplication }
{ TxtServiceApplication }
 procedure TxtServiceApplication.ContinueRun;
procedure TxtServiceApplication.ContinueRun; begin
begin while not Forms.Application.Terminated do
  while not Forms.Application.Terminated do Forms.Application.HandleMessage;
    Forms.Application.HandleMessage; 
     Forms.Application.Terminate;
  Forms.Application.Terminate; end;
end;
 constructor TxtServiceApplication.Create(AOwner: TComponent);
constructor TxtServiceApplication.Create(AOwner: TComponent); begin
begin FEventLogger := TEventLogger.Create(ExtractFileName(ParamStr(0)));
  FEventLogger := TEventLogger.Create(ExtractFileName(ParamStr(0))); inherited Create(AOwner);
  inherited Create(AOwner); end;
end;
 destructor TxtServiceApplication.Destroy;
destructor TxtServiceApplication.Destroy; begin
begin inherited Destroy;
  inherited Destroy; FEventLogger.Free;
  FEventLogger.Free; end;
end;
 procedure TxtServiceApplication.OnExceptionHandler(Sender: TObject; E: Exception);
procedure TxtServiceApplication.OnExceptionHandler(Sender: TObject; E: Exception); begin
begin DoHandleException(E);
  DoHandleException(E); end;
end;
 procedure ServiceMain(Argc: DWord; Argv: PLPSTR); stdcall;
procedure ServiceMain(Argc: DWord; Argv: PLPSTR); stdcall; begin
begin TxtServiceApplication(Application).DispatchServiceMain(Argc, Argv);
  TxtServiceApplication(Application).DispatchServiceMain(Argc, Argv); end;
end;
 procedure TxtServiceApplication.Run;
procedure TxtServiceApplication.Run;
 function FindSwitch(const Switch: string): Boolean;
  function FindSwitch(const Switch: string): Boolean; begin
  begin Result := FindCmdLineSwitch(Switch, ['-', '/'], True);
    Result := FindCmdLineSwitch(Switch, ['-', '/'], True); end;
  end;
 var
var ServiceStartTable: TServiceTableEntryArray;
  ServiceStartTable: TServiceTableEntryArray; ServiceCount, i, J: Integer;
  ServiceCount, i, J: Integer; StartThread: TServiceStartThread;
  StartThread: TServiceStartThread; begin
begin AddExitProc(DoneServiceApplication);
  AddExitProc(DoneServiceApplication); 
   if FindSwitch('INSTALL') then
  if FindSwitch('INSTALL') then RegisterServices(True, FindSwitch('SILENT')) else
    RegisterServices(True, FindSwitch('SILENT')) else if FindSwitch('UNINSTALL') then
  if FindSwitch('UNINSTALL') then RegisterServices(False, FindSwitch('SILENT')) else
    RegisterServices(False, FindSwitch('SILENT')) else begin
  begin Forms.Application.OnException := OnExceptionHandler;
    Forms.Application.OnException := OnExceptionHandler; ServiceCount := 0;
    ServiceCount := 0; for i := 0 to ComponentCount - 1 do
    for i := 0 to ComponentCount - 1 do if Components[i] is TService then Inc(ServiceCount);
      if Components[i] is TService then Inc(ServiceCount); SetLength(ServiceStartTable, ServiceCount + 1);
    SetLength(ServiceStartTable, ServiceCount + 1); FillChar(ServiceStartTable[0], SizeOf(TServiceTableEntry) * (ServiceCount + 1), 0);
    FillChar(ServiceStartTable[0], SizeOf(TServiceTableEntry) * (ServiceCount + 1), 0); J := 0;
    J := 0; for i := 0 to ComponentCount - 1 do
    for i := 0 to ComponentCount - 1 do if Components[i] is TService then
      if Components[i] is TService then begin
      begin ServiceStartTable[J].lpServiceName := PChar(Components[i].Name);
        ServiceStartTable[J].lpServiceName := PChar(Components[i].Name); ServiceStartTable[J].lpServiceProc := @ServiceMain;
        ServiceStartTable[J].lpServiceProc := @ServiceMain; Inc(J);
        Inc(J); end;
      end; StartThread := TServiceStartThread.Create(ServiceStartTable);
    StartThread := TServiceStartThread.Create(ServiceStartTable); try
    try while (not Forms.Application.Terminated) and FContinueHandlingMessages do
      while (not Forms.Application.Terminated) and FContinueHandlingMessages do Forms.Application.HandleMessage;
        Forms.Application.HandleMessage; // Application start as standalone application?
      // Application start as standalone application? if ((StartThread.ReturnValue = ERROR_FAILED_SERVICE_CONTROLLER_) or
      if ((StartThread.ReturnValue = ERROR_FAILED_SERVICE_CONTROLLER_) or (StartThread.ReturnValue = ERROR_CALL_NOT_IMPLEMENTED)) and (not Forms.Application.Terminated)
         (StartThread.ReturnValue = ERROR_CALL_NOT_IMPLEMENTED)) and (not Forms.Application.Terminated) then
      then begin
      begin raise EServiceError.Create('Not as service');
        raise EServiceError.Create('Not as service'); end
      end else if StartThread.ReturnValue <> 0 then
      else if StartThread.ReturnValue <> 0 then begin
      begin FEventLogger.LogMessage(SysErrorMessage(GetLastError));
        FEventLogger.LogMessage(SysErrorMessage(GetLastError)); end;
      end; finally
    finally StartThread.Free;
      StartThread.Free; end;
    end; end;
  end; end;
end;
 procedure InitApplication;
procedure InitApplication; begin
begin SvcMgr.Application.Free;
  SvcMgr.Application.Free; SvcMgr.Application := TxtServiceApplication.Create(nil);
  SvcMgr.Application := TxtServiceApplication.Create(nil); end;
end;
 function Application: TxtServiceApplication;
function Application: TxtServiceApplication; begin
begin Result := TxtServiceApplication(SvcMgr.Application);
  Result := TxtServiceApplication(SvcMgr.Application); end;
end;
 initialization
initialization InitApplication;
  InitApplication; InitServiceDesktop;
  InitServiceDesktop;
 finalization
finalization DoneServiceDesktop;
  DoneServiceDesktop; 
   end.
end.
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号