Delphi code pour afficher un message convivial si vous n'êtes pas autorisé à faire quelque chose qui nécessite que comme administrateur possède des privilèges d'installer un service

StackOverflow https://stackoverflow.com/questions/8344751

  •  27-10-2019
  •  | 
  •  

Question

Un client signale une erreur de notre application lors de l'installation qui indique que le code « IsWindowsAdministrator » ci-dessous est de retour FALSE lorsque l'installation est effectuée par un administrateur de domaine. Connecté en tant qu'administrateur locale tout fonctionne très bien. Le programme d'installation (InnoSetup) appelle un fichier exe qui fait des opérations de gestionnaire de contrôle de service (voir ci-dessous), mais après la IsWindowsAdministrator ci-dessous a été appelé pour vérifier l'état de l'utilisateur.

Ma raison de vouloir vérifier l'état d'administration est de fournir une erreur gracieuse avant d'appeler les tâches de gestionnaire de services à travailler avec un pilote (voir ci-dessous CODE DRIVER INSTALLATION). Ce sont des tâches que je ne peux pas facilement faire à l'intérieur InnoSetup et moi avons choisi de les envelopper dans un petit exe appelé par l'installateur.

Le code de vérification Code ADMIN valide pour cette tâche? Ou devrais-je abandonner simplement et envelopper l'appel au gestionnaire de contrôle de service dans un essai, sauf avec un plus joli message d'erreur?

Merci

===================== CONDUCTEUR CODE ======================= INSTALL =

procedure ArtIODriver_Install( AShowSummary : boolean );
var
  hServiceControlManager : THandle;
  hService               : SC_HANDLE;
  ServiceStatus          : TServiceStatus;
  ServiceArgVectors      : PAnsiString;
begin

  If not IsWindowsAdministrator then
    Raise EArtIODriver.Create(
      'Error IODR4 - You must be a windows administrator to perform this action' );

  If not FileExists( ArtIODriver_FilePath ) then
    Raise EArtIODriver.CreateFmt(
      'Error IODR7 - Unable to locate the driver file "%s"',
      [ArtIODriver_FilePath] );

  hService := 0;
  hServiceControlManager := 0;
  try

    hServiceControlManager := OpenSCManager(
      nil,
      nil,
      SC_MANAGER_ALL_ACCESS);
    If hServiceControlManager = 0 then
      Raise EArtIODriver.CreateFmt(
        'Error IOD1 - Unable to open service control manager - %s',
        [GetWinLastErrorStr] );

    // can we see the service?
    hService := OpenService(
      hServiceControlManager,
      JustDriverName,
      SERVICE_ALL_ACCESS);
etc
etc

========= VÉRIFICATION CODE ADMIN ================

function IsWindowsAdministrator: Boolean;
// Returns TRUE if the user has administrator priveleges
// Returns a boolean indicating whether or not user has admin
// privileges. Call only when running under NT. Win9.x will return false!
var
  hAccessToken       : tHandle;
  ptgGroups          : pTokenGroups;
  dwInfoBufferSize   : DWORD;
  psidAdministrators : PSID;
  int                : integer;            // counter
  blnResult          : boolean;            // return flag

const
  SECURITY_NT_AUTHORITY: SID_IDENTIFIER_AUTHORITY =
    (Value: (0,0,0,0,0,5)); // ntifs
  SECURITY_BUILTIN_DOMAIN_RID: DWORD = $00000020;
  DOMAIN_ALIAS_RID_ADMINS: DWORD = $00000220;
  DOMAIN_ALIAS_RID_USERS : DWORD = $00000221;
  DOMAIN_ALIAS_RID_GUESTS: DWORD = $00000222;
  DOMAIN_ALIAS_RID_POWER_: DWORD = $00000223;

begin
  Result := False;
  blnResult := OpenThreadToken( GetCurrentThread, TOKEN_QUERY,
                                True, hAccessToken );
  if ( not blnResult ) then
  begin
    if GetLastError = ERROR_NO_TOKEN then
    blnResult := OpenProcessToken( GetCurrentProcess,
                       TOKEN_QUERY, hAccessToken );
  end;

  ptgGroups := nil;

  if ( blnResult ) then
  try

    GetMem(ptgGroups, 1024);
    blnResult := GetTokenInformation( hAccessToken, TokenGroups,
                                      ptgGroups, 1024,
                                      dwInfoBufferSize );
    CloseHandle( hAccessToken );

    if ( blnResult ) then
    begin

      AllocateAndInitializeSid( SECURITY_NT_AUTHORITY, 2,
                                SECURITY_BUILTIN_DOMAIN_RID,
                                DOMAIN_ALIAS_RID_ADMINS,
                    0, 0, 0, 0, 0, 0,
                    psidAdministrators );
      {$IFOPT R+}
        {$DEFINE RMINUS}
        {$R-}
      {$ENDIF}
      for int := 0 to ptgGroups.GroupCount - 1 do

        if EqualSid( psidAdministrators,
                     ptgGroups.Groups[ int ].Sid ) then
        begin
          Result := True;
          Break;
        end;
      {$IFDEF IMINUS}
        {$R-}
        {$UNDEF IMINUS}
      {$ENDIF}

      FreeSid( psidAdministrators );
    end;

  finally
    If ptgGroups <> nil then
      FreeMem( ptgGroups );
  end;
end;
Était-ce utile?

La solution

Plutôt que de vérifier si l'utilisateur est un administrateur, il vous suffit de vérifier le code d'erreur de OpenSCManager() et / ou OpenService() à la place. Si l'utilisateur ne dispose pas de droits suffisants, GetLastError() retournera ERROR_ACCESS_DENIED, par exemple:

hServiceControlManager := OpenSCManager( 
  nil, 
  nil, 
  SC_MANAGER_ALL_ACCESS); 
If hServiceControlManager = 0 then 
Begin
  If GetLastError() = ERROR_ACCESS_DENIED then
    Raise EArtIODriver.Create('Error IODR4 - You must be a windows administrator to perform this action' ) 
  else
    Raise EArtIODriver.CreateFmt('Error IOD1 - Unable to open service control manager - %s', [GetWinLastErrorStr] );
End; 

J'utilise cette technique dans une application qui ne nécessite pas de droits d'administrateur pour la plupart de ses opérations pour détecter manuellement Invoke une invite UAC sous Vista + pour obtenir des droits suffisants, et cela fonctionne très bien.

Autres conseils

Parce que vous exécutez un exécutable de votre programme d'installation, ce que vous avez probablement besoin de faire est de créer un manifeste pour votre exécutable qui demande l'élévation. Ne demandez pas ce que vous avez des privilèges. Demandez Windows pour les privilèges dont vous avez besoin.

Comment puis-je créer un manifeste pour une fenêtre installateur

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top