寻找Delphi 7代码来检测程序是否以管理员权限启动?

时间:2011-06-07 07:24:15

标签: delphi delphi-7 uac elevation

我正在寻找工作显然 Delphi 7代码,以便检查我的程序是否以管理员权限启动

提前致谢

[---重要更新---]

到目前为止已经回答了答案中的代码,我意识到我的问题可能不是那么清楚,或者至少是不完整的:

  • 我想知道我的Delphi 7程序是否以'以管理员身份运行'复选框设置

  • 换句话说:我想知道我的 Delphi 7程序是否可以在c:\ Program Files ...文件夹中创建/更新文件< /强>

只是检查你是否拥有管理员权限是不够的。

7 个答案:

答案 0 :(得分:15)

Windows API(已使用)具有帮助程序功能(IsUserAnAdmin),以告知您是否以管理权限运行。

OS              Account Type   UAC           IsUserAdmin
==============  =============  ============  ===========
Windows XP      Standard       n/a           False
Windows XP      Administrator  n/a           True
Windows Vista   Standard       Disabled      False
Windows Vista   Administrator  Disabled      True
Windows Vista   Standard       Not Elevated  False
Windows Vista   Administrator  Not Elevated  False
Windows Vista   Standard       Elevated      True
Windows Vista   Administrator  Elevated      True

不推荐使用Shell32包装函数;这很好,因为它只是a wrapper around other code, which you can still call你自己:

function IsUserAdmin: Boolean;
var
  b: BOOL;
  AdministratorsGroup: PSID;
begin
  {
    This function returns true if you are currently running with admin privileges.
    In Vista and later, if you are non-elevated, this function will return false 
    (you are not running with administrative privileges).
    If you *are* running elevated, then IsUserAdmin will return true, as you are 
    running with admin privileges.

    Windows provides this similar function in Shell32.IsUserAnAdmin. 
    But the function is deprecated, and this code is lifted
    from the docs for CheckTokenMembership:
      http://msdn.microsoft.com/en-us/library/aa376389.aspx
  }

  {
    Routine Description: This routine returns TRUE if the callers
    process is a member of the Administrators local group. Caller is NOT
    expected to be impersonating anyone and is expected to be able to
    open its own process and process token.
      Arguments: None.
      Return Value:
        TRUE - Caller has Administrators local group.
        FALSE - Caller does not have Administrators local group.
  }
  b := AllocateAndInitializeSid(
      SECURITY_NT_AUTHORITY,
      2, //2 sub-authorities
      SECURITY_BUILTIN_DOMAIN_RID,  //sub-authority 0
      DOMAIN_ALIAS_RID_ADMINS,      //sub-authority 1
      0, 0, 0, 0, 0, 0,             //sub-authorities 2-7 not passed
      AdministratorsGroup);
  if (b) then
  begin
    if not CheckTokenMembership(0, AdministratorsGroup, b) then
      b := False;
      FreeSid(AdministratorsGroup);
  end;

  Result := b;
end;

换句话说:此功能为您提供所需的答案:用户是否可以更新程序文件。

您需要厌倦检查您是否是管理员组成员的代码。您可以成为管理员组的一部分,但不具有任何管理权限。您也可以拥有管理权限,但不能成为管理员组的一部分。

答案 1 :(得分:5)

Project JEDI的JEDI Code Library在JclSecurity单元中有一个IsAdministrator函数可以告诉你。它仍然适用于Delphi 7。

答案 2 :(得分:5)

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows,
  ShellAPI;

// high-level wrapper, see Ian Boyd's answer for details on this function
function IsUserAnAdmin(): BOOL; external shell32;

begin
  if IsUserAnAdmin() then
    Writeln('TEH R00T OMG')
  else
    Writeln('rtfmnoobkthx');

  Readln;
end.

答案 3 :(得分:3)

Microsoft建议的解决此问题的方法:将应用程序拆分为两个。

http://msdn.microsoft.com/en-us/library/aa511445.aspx

第一个应用程序检查是否有必要运行第二个应用程序。

第二个应用程序包含一个“require admin”清单(如David写的那样),然后使用ShellExecuteEx'runas'动词打开它。

如果是网络更新程序,工作流程可能是这样的:

Updater1.exe

  1. 检查是否有可用的更新。
  2. 可选择询问用户是否要安装更新。
  3. 将更新下载到临时位置。
  4. 使用ShellExecuteEx和“runas”动词运行Updater2.exe。
  5. Updater2.exe

    1. 如果用户确认提示或根本不运行,将在UAC上进行评估。
    2. 然后可以将文件从临时位置复制到最终位置。
    3. 这有几个好处:

      • Updater2仅包含必须运行升级的最小操作。
      • Updater2可以是下载文件的一部分。
      • 无需检查任何权限,UAC负责处理。

      它也适用于Windows XP,如果您不是管理员,则会显示登录对话框。

答案 4 :(得分:2)

Jwscl(Jedi Windows安全库)具有以下功能:JwCheckAdministratorAccess

function JwCheckAdministratorAccess: boolean;

用法非常简单:

Uses
  JwsclToken;

IsElevated := JwCheckAdministratorAccess;

如果启用了UAC,此功能也适用于Windows Vista及更高版本。如果当前进程未提升,则即使令牌包含管理员组(然后被禁用),返回值也将为false。此功能检测管理员组中的组成员身份,这意味着用户不需要直接在管理员组中,而是组可以是管理员组的成员。

答案 5 :(得分:2)

我在Windows XP,7和8(管理员和有限帐户)上使用Delphi 7测试了此代码:

Function CheckTokenMembership(TokenHandle: THandle; SIdToCheck: PSID; var IsMember: Boolean): Boolean; StdCall; External AdvApi32;

Function IsAdmin: Boolean;
const
  DOMAIN_ALIAS_RID_ADMINS = $00000220;
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
var
  Admin: Boolean;
  AdmGroup: PSID;
Begin
  Admin := AllocateAndInitializeSid(SECURITY_NT_AUTHORITY,
    2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0, AdmGroup);
  If (Admin) Then
  Begin
    If (not CheckTokenMembership(0, AdmGroup, Admin)) Then
      Admin := False;
    FreeSid(AdmGroup);
  end;
  Result := Admin;
end;

答案 6 :(得分:1)

此代码适用于D7..XE inc。

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;