2

ドメイン管理者がインストールを実行すると、以下の「IsWindowsAdministrator」のコードが FALSE を返すことを示すエラーが、お客様からインストール中にアプリケーションから報告されています。ローカル管理者としてログオンすると、すべて正常に動作します。インストーラー (Innosetup) は、一部のサービス コントロール マネージャー操作 (以下を参照) を実行する exe ファイルを呼び出しますが、以下の IsWindowsAdministrator が呼び出されてユーザー ステータスを確認した後です。

私が管理者ステータスを確認したい理由は、サービス マネージャー タスクを呼び出してドライバーを操作する前に適切なエラーを提供するためです (以下のドライバー インストール コードを参照)。これらは、Innosetup 内で簡単に実行できないタスクであり、インストーラーによって呼び出される小さな exe にラップすることにしました。

CHECK ADMIN CODE のコードはこのタスクに有効ですか? それとも、単純にそれを放棄して、サービス コントロール マネージャーへの呼び出しを try-except でラップし、より適切なエラー メッセージを表示する必要がありますか?

ありがとう

===================== ドライバーインストールコード ========================

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

========= 管理者コードを確認 ================

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;
4

2 に答える 2

8

ユーザーが管理者かどうかを確認するのではなく、 OpenSCManager()and/orのエラー コードを確認するだけOpenService()です。ユーザーが十分な権限を持っていない場合、次のGetLastError()ように返さERROR_ACCESS_DENIEDれます。

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; 

ほとんどの操作で管理者権限を必要としないアプリでこの手法を使用して、十分な権限を取得するために Vista 以降で UAC プロンプトを手動で呼び出すタイミングを検出しましたが、非常にうまく機能します。

于 2011-12-01T18:17:19.637 に答える
3

インストーラーから実行可能ファイルを実行しているため、昇格を要求する実行可能ファイルのマニフェストを作成する必要があります。あなたがどんな特権を持っているかを尋ねないでください。Windows に必要な特権を要求します。

Windows インストーラーのマニフェストを作成するにはどうすればよいですか?

于 2011-12-02T03:21:32.143 に答える