2010년 1월 13일 수요일

윈도우즈 서비스 설치, 삭제, 시작, 종료 등을 제어하는 유닛

윈도우즈 서비스를 설치, 삭제, 시작, 종료 등을 제어하는 유닛

{-------------------------------------------------------------------------------
 Description    : Windows Service Managing Unit
 Version        : Delphi 5, 6, 7, 200...9
 Author         : Changmin Koo,
 Email          : Koochangmin@empal.com
 Notes          :
-------------------------------------------------------------------------------}



unit uServiceManager;

interface

uses
  Windows, Classes, SysUtils, SvcMgr, ComObj, WinSvc, Types;

const
  NET_FW_PROFILE_DOMAIN = 0;
  NET_FW_PROFILE_STANDARD = 1;
  NET_FW_IP_VERSION_ANY = 2;
  NET_FW_IP_PROTOCOL_UDP = 17;
  NET_FW_IP_PROTOCOL_TCP = 6;
  NET_FW_SCOPE_ALL = 0;
  NET_FW_SCOPE_LOCAL_SUBNET = 1;

  
  SERVICE_CONFIG_DESCRIPTION      = 1;
  SERVICE_CONFIG_FAILURE_ACTIONS  = 2;

type
  SERVICE_DESCRIPTION = packed record
    //lpDescription : LPTSTR;
    lpDescription : PChar;
  end;
  PSERVICE_DESCRIPTION = ^SERVICE_DESCRIPTION;

var
  ssStatus: TServiceStatus;

function ChangeServiceConfig2(hService: SC_HANDLE; dwInfoLevel: DWORD; lpInfo: Pointer):BOOL;stdcall;external 'advapi32.dll' name 'ChangeServiceConfig2W';

procedure AddApplicationToFirewall(EntryName: string; ApplicationPathAndExe: string);
function IsStartService(ServiceName: PChar): Boolean;
function IsInstallService(ServiceName: PChar): Boolean;
function ServiceStart(sService: string): Boolean;
function ServiceStop(sService: string): Boolean;
procedure InstallService(ServiceName: PChar; ServiceDisplayName: PChar; ExeName: PChar);
procedure UnInstallService(ServiceName: PChar; ServiceDisplayName: PChar);
function SetServiceConfig(ServiceName: PChar; Description: string): Boolean;

implementation

function SetServiceConfig(ServiceName: PChar; Description: string): Boolean;
var
  SvcMgr, Svc : SC_HANDLE;
  desc : SERVICE_DESCRIPTION;
begin
  Result := False;
  SvcMgr := 0;  Svc := 0;
  try
    SvcMgr := OpenSCManager(nilnil, SC_MANAGER_ALL_ACCESS);
    if 0 = SvcMgr then
      exit;
    Svc := OpenService(SvcMgr, ServiceName, SERVICE_CHANGE_CONFIG);
    if 0 = Svc then
      exit;
    Desc.lpDescription := PChar(Description); 
    Result := ChangeServiceConfig2(Svc, SERVICE_CONFIG_DESCRIPTION, @desc);
  finally
    if 0 <> Svc then
      CloseServiceHandle(Svc);
    if 0 <> SvcMgr then
      CloseServiceHandle(SvcMgr);
  end;
end;

//MSDN : http://msdn.microsoft.com/en-us/library/aa366421(VS.85).aspx
procedure AddApplicationToFirewall(EntryName: string; ApplicationPathAndExe: string);
var
  fwMgr, App: OleVariant;
  profile: OleVariant;
begin
  fwMgr := CreateOLEObject('HNetCfg.FwMgr');
  profile := fwMgr.LocalPolicy.CurrentProfile;
  app := CreateOLEObject('HNetCfg.FwAuthorizedApplication');
  app.ProcessImageFileName := ApplicationPathAndExe;
  app.Name := EntryName;
  app.Scope := NET_FW_SCOPE_ALL;
  app.IpVersion := NET_FW_IP_VERSION_ANY;
  app.Enabled := True;
  profile.AuthorizedApplications.Add(app);
end;

function IsStartService(ServiceName: PChar): Boolean;
var
  schService: SC_HANDLE;
  schSCManager: SC_HANDLE;
  Status: TServiceStatus;
begin
  Result := False;
  schSCManager := OpenSCManager(nilnil, SC_MANAGER_CONNECT);
  if (schSCManager > 0) then
  begin
    schService := OpenService(schSCManager, ServiceName, SERVICE_QUERY_STATUS);
    if (schService > 0) then
    begin
      QueryServiceStatus(schService, Status);
      Result := (Status.dwCurrentState = SERVICE_RUNNING);
    end;
    CloseServiceHandle(schService);
  end;
  CloseServiceHandle(schSCManager);
end;

function IsInstallService(ServiceName: PChar): Boolean;
var
  schService: SC_HANDLE;
  schSCManager: SC_HANDLE;
begin
  Result := False;
  schSCManager := OpenSCManager(nilnil, SC_MANAGER_ALL_ACCESS);
  if (schSCManager > 0) then
  begin
    schService := OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (schService > 0) then
      Result := True;
    CloseServiceHandle(schService);
  end;
  CloseServiceHandle(schSCManager);
end;

function ServiceStart(sService: string): Boolean;
var
  SvcManager, SvcHandle: SC_Handle;
  SvcStatus: TServiceStatus;
  psTemp: PChar;
  dwChkP: DWord;
begin
  SvcStatus.dwCurrentState := DWORD(-1);
  SvcManager := OpenSCManager(nilnil, SC_MANAGER_CONNECT);

  if (SvcManager > 0) then
  begin
    SvcHandle := OpenService(SvcManager, PChar(sService), SERVICE_START or SERVICE_QUERY_STATUS);
    if (SvcHandle > 0) then
    begin
      psTemp := nil;
      if (StartService(SvcHandle, 0, psTemp)) then
      begin
        if (QueryServiceStatus(SvcHandle, SvcStatus)) then
        begin
          while (SERVICE_RUNNING <> SvcStatus.dwCurrentState) do
          begin
            dwChkP := SvcStatus.dwCheckPoint;
            Sleep(SvcStatus.dwWaitHint);
            if (not QueryServiceStatus(SvcHandle, SvcStatus)) then
              break;
            if (SvcStatus.dwCheckPoint < dwChkP) then
              break;
          end;
        end;
      end;
      CloseServiceHandle(SvcHandle);
    end;
    CloseServiceHandle(SvcManager);
  end;
  Result := SERVICE_RUNNING = SvcStatus.dwCurrentState;
end;

function ServiceStop(sService: string): Boolean;
var
  SvcManager, SvcHandle: SC_Handle;
  SvcStatus: TServiceStatus;
  dwChkP: DWord;
begin
  SvcManager := OpenSCManager(nilnil, SC_MANAGER_CONNECT);
  if (SvcManager > 0) then
  begin
    SvcHandle := OpenService(SvcManager, PChar(sService), SERVICE_STOP or SERVICE_QUERY_STATUS);
    if (SvcHandle > 0) then
    begin
      if (ControlService(SvcHandle, SERVICE_CONTROL_STOP, SvcStatus)) then
      begin
        if (QueryServiceStatus(SvcHandle, SvcStatus)) then
        begin
          while (SERVICE_STOPPED <> SvcStatus.dwCurrentState) do
          begin
            dwChkP := SvcStatus.dwCheckPoint;
            Sleep(SvcStatus.dwWaitHint);
            if (not QueryServiceStatus(SvcHandle, SvcStatus)) then
              break;
            if (SvcStatus.dwCheckPoint < dwChkP) then
              break;
          end;
        end;
      end;
      CloseServiceHandle(SvcHandle);
    end;
    CloseServiceHandle(SvcManager);
  end;
  Result := SERVICE_STOPPED = SvcStatus.dwCurrentState;
end;

procedure InstallService(ServiceName: PChar; ServiceDisplayName: PChar; ExeName: PChar);
var
  schService: SC_HANDLE;
  schSCManager: SC_HANDLE;
begin
  schSCManager := OpenSCManager(nilnil, SC_MANAGER_ALL_ACCESS);
  if (schSCManager > 0) then
  begin
    schService := CreateService(
      schSCManager,
      ServiceName,
      ServiceDisplayName,
      SERVICE_ALL_ACCESS,
      SERVICE_INTERACTIVE_PROCESS or SERVICE_WIN32_OWN_PROCESS,
      SERVICE_DEMAND_START,
      SERVICE_ERROR_NORMAL,
      ExeName,
      nil,
      nil,
      nil,
      nil,
      nil);
    if (schService > 0) then
    begin
      MessageBox(0, 'Install Successfull.''확인', MB_OK or MB_ICONINFORMATION);
      CloseServiceHandle(schService)
    end
    else
      MessageBox(0, PChar('Unable to install ' + ServiceName + ',CreateServiceFail.'), '확인', MB_OK or MB_ICONINFORMATION)
  end
  else
    MessageBox(0, PChar('Unable to install ' + ServiceName + ',OpenSCManagerFail.'), '확인', MB_OK or MB_ICONINFORMATION)
end;

procedure UnInstallService(ServiceName: PChar; ServiceDisplayName: PChar);
var
  schService: SC_HANDLE;
  schSCManager: SC_HANDLE;
begin
  schSCManager := OpenSCManager(nilnil, SC_MANAGER_ALL_ACCESS);
  if (schSCManager > 0) then
  begin
    schService := OpenService(schSCManager, ServiceName, SERVICE_ALL_ACCESS);
    if (schService > 0) then
    begin
      // Try to stop service at first
      if ControlService(schService, SERVICE_CONTROL_STOP, ssStatus) then
      begin
        Write('Stopping Service ');
        Sleep(1000);
        while (QueryServiceStatus(schService, ssStatus)) do
        begin
          if ssStatus.dwCurrentState = SERVICE_STOP_PENDING then
          begin
            Write('.');
            Sleep(1000)
          end
          else
            break
        end;

        if ssStatus.dwCurrentState = SERVICE_STOPPED then
          Writeln('Service Stop Now')
        else
        begin
          CloseServiceHandle(schService);
          CloseServiceHandle(schSCManager);
          Writeln('Service Stop Fail');
          exit
        end
      end;

      // Remove the service
      if (DeleteService(schService)) then
        MessageBox(0, 'Uninstall Successful.''확인', MB_OK or MB_ICONINFORMATION)
      else
        MessageBox(0, PChar('DeleteService fail (' + SysErrorMessage(GetLastError) + ').'), '확인', MB_OK or MB_ICONINFORMATION);

      CloseServiceHandle(schService);
    end
    else
      MessageBox(0, PChar('OpenService fail (' + SysErrorMessage(GetLastError) + ').'), '확인', MB_OK or MB_ICONINFORMATION);

    CloseServiceHandle(schSCManager)
  end
  else
    MessageBox(0, PChar('OpenSCManager fail (' + SysErrorMessage(GetLastError) + ').'), '확인', MB_OK or MB_ICONINFORMATION)
end;

end.

댓글 없음:

댓글 쓰기