使用changeserviceconfig2的权限错误设置恢复选项

时间:2016-01-24 13:16:56

标签: delphi service

我正在安装服务并想要设置服务恢复选项(在XP环境中使用admin)。我可以愉快地更改描述,但是如果sfa.cActions不是零,则会因错误87(参数错误)而失败。

//
// Actions to take on service failure
//
  {$EXTERNALSYM _SC_ACTION_TYPE}
  _SC_ACTION_TYPE = (SC_ACTION_NONE, SC_ACTION_RESTART, SC_ACTION_REBOOT, SC_ACTION_RUN_COMMAND);
  {$EXTERNALSYM SC_ACTION_TYPE}
  SC_ACTION_TYPE = _SC_ACTION_TYPE;

  PServiceAction = ^TServiceAction;
  {$EXTERNALSYM _SC_ACTION}
  _SC_ACTION = record
    aType : SC_ACTION_TYPE;
    Delay : DWORD;
  end;
  {$EXTERNALSYM SC_ACTION}
  SC_ACTION = _SC_ACTION;
  TServiceAction = _SC_ACTION;


procedure TXyz_Service_Module.SetDescription(const Desc: ansistring);
var
  hSCM: SC_HANDLE;
  hService: SC_HANDLE;
  sd: SERVICE_DESCRIPTION;
begin
  hSCM := WinSvc.OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCM = 0 then Exit;
  hService := WinSvc.OpenService(hSCM, PChar(Self.Name), SERVICE_CHANGE_CONFIG);
  if hService = 0 then Exit;
  sd.lpDescription := PAnsiChar(Desc);
  ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, @sd);
  WinSvc.CloseServiceHandle(hService);
  WinSvc.CloseServiceHandle(hSCM);
end;

procedure TXyz_Service_Module.SetRecovery;
var
  hSCM: SC_HANDLE;
  hService: SC_HANDLE;
  sfa: SERVICE_FAILURE_ACTIONS;
  actions: array [0 .. 2] of SC_ACTION;
begin
  hSCM := WinSvc.OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if hSCM = 0 then Exit;
  hService := WinSvc.OpenService(hSCM, PChar(Self.Name), SERVICE_ALL_ACCESS);
  if hService = 0 then Exit;

  sfa.dwResetPeriod := 999; //INFINITE;
  sfa.lpCommand := nil;
  sfa.lpRebootMsg := nil;
  sfa.cActions := 1;
  sfa.lpsaActions := @actions[0];

  actions[0].aType := SC_ACTION_RESTART;
  actions[0].Delay := 5000;
  (*actions[1].aType := SC_ACTION_RESTART;
  actions[1].Delay := 5000;
  actions[2].aType := SC_ACTION_RESTART;
  actions[2].Delay := 5000;*)

  if not changeserviceconfig2(hservice,SERVICE_CONFIG_FAILURE_ACTIONS,@sfa) then begin
     showmessage('Error : '+inttostr(getlasterror));
  end;
  WinSvc.CloseServiceHandle(hService);
  WinSvc.CloseServiceHandle(hSCM);
end;

procedure TXyz_Service_Module.ServiceAfterInstall(Sender: TService);
begin
  self.SetDescription('Bananas are yellow');
  self.SetRecovery;
end;

2 个答案:

答案 0 :(得分:0)

来自ChangeServiceConfig2()文档:

  

hService [in]
  服务的句柄。此句柄由OpenServiceCreateService函数返回,必须具有SERVICE_CHANGE_CONFIG访问权限。有关更多信息,请参阅Service Security and Access Rights

     

如果服务控制器处理SC_ACTION_RESTART操作,则hService 必须具有SERVICE_START访问权限

因此,SetRecovery()至少需要使用此功能:

hService := WinSvc.OpenService(hSCM, PChar(Self.Name), SERVICE_CHANGE_CONFIG or SERVICE_START);

答案 1 :(得分:0)

这是枚举值。

 _SC_ACTION_TYPE = (SC_ACTION_NONE, SC_ACTION_RESTART, SC_ACTION_REBOOT, SC_ACTION_RUN_COMMAND);

需要

{$MinEnumSize=4}
 _SC_ACTION_TYPE = (SC_ACTION_NONE, SC_ACTION_RESTART, SC_ACTION_REBOOT, SC_ACTION_RUN_COMMAND);

根据David Heffernan的评论中的建议。