DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: monica9612
今日帖子: 0
在线用户: 2
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 15:04:24
标题:
win7 判断当前用户 是否有管理员权限 浏览:1324
加入我的收藏
楼主: 一直用下面的代码,但是,今天有用户反映,软件有提示,就是下面的代码判断失败,但,其实win用户是属于管理员组的。

哪位高手,看看代码还有什么改进的方法吗?或者给我一个例子,我让用户再试试。

function IsAdmin: Boolean;
const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
  DOMAIN_ALIAS_RID_ADMINS = $00000220;
var
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  dwInfoBufferSize: DWORD;
  psidAdministrators: PSID;
  x: Integer;
  bSuccess: BOOL;
begin
  Result := False;
  bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
    hAccessToken);
  if not bSuccess then
  begin
    if GetLastError = ERROR_NO_TOKEN then
      bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
        hAccessToken);
  end;

  if bSuccess then
  begin
    GetMem(ptgGroups, 1024);
    bSuccess := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, 1024,
      dwInfoBufferSize);
    CloseHandle(hAccessToken);

    if bSuccess then
    begin
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
        psidAdministrators);
{$R-}
      for x := 0 to ptgGroups.GroupCount - 1 do
        if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) then
        begin
          Result := True;
          Break;
        end;
{$R+}
      FreeSid(psidAdministrators);
    end;
    FreeMem(ptgGroups);
  end;
end;
此帖子包含附件:
PNG 图像
大小:2.26M
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 15:48:07
1楼: unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  Form1: TForm1;


  function IsAdmin: Boolean;
implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
  if not IsAdmin then
    Memo1.Lines.Add('没有管理员权限')
end;

function IsAdmin: Boolean;
const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
  DOMAIN_ALIAS_RID_ADMINS = $00000220;
var
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  dwInfoBufferSize: DWORD;
  psidAdministrators: PSID;
  x: Integer;
  bSuccess: BOOL;
begin
  Result := False;
  bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
    hAccessToken);
  if bSuccess then  Form1.Memo1.Lines.Add('测试1 成功') else  Form1.Memo1.Lines.Add('测试1 失败');

  if not bSuccess then
  begin
     Form1.Memo1.Lines.Add('GetLastError ' + IntToStr(GetLastError));
    if GetLastError = ERROR_NO_TOKEN then
      bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
        hAccessToken);
  end;
  if bSuccess then  Form1.Memo1.Lines.Add('测试2 成功') else  Form1.Memo1.Lines.Add('测试2 失败');
  if bSuccess then
  begin
    GetMem(ptgGroups, 1024);
    bSuccess := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, 1024,
      dwInfoBufferSize);
    CloseHandle(hAccessToken);
    if bSuccess then  Form1.Memo1.Lines.Add('测试3 成功') else Form1.Memo1.Lines.Add('测试3 失败');
    if bSuccess then
    begin
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
        psidAdministrators);
{$R-}
      for x := 0 to ptgGroups.GroupCount - 1 do
        if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) then
        begin
          Result := True;
          Form1.Memo1.Lines.Add('成功Sid ' + IntToStr(Integer(ptgGroups.Groups[x].Sid)))  ;
          Break;
        end
        else
          Form1.Memo1.Lines.Add(IntToStr(Integer(ptgGroups.Groups[x].Sid)))  ;
{$R+}
      FreeSid(psidAdministrators);
    end;
    FreeMem(ptgGroups);
  end;
end;

end.
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 15:48:20
2楼: program Project1;

{$R 'WinXpAndUAC.res' 'WinXpAndUAC.rc'}

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 15:48:43
3楼: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="CodeGear RAD Studio"
    version="11.0.2902.10471" 
    processorArchitecture="*"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 luckyrandom (luckyrandom) ★☆☆☆☆ -
普通会员
2018/12/17 15:51:11
4楼: 十多年前曾写过获取组、用户,应该可以判断了
当时是为了便于管理用户帐号、密码
----------------------------------------------
SQL SERVER DBA QQ:315054403 曾经的Delphier  缘在上海
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 15:51:43
4楼: 奇怪的是,把我A软件里代码复制出来,新建一个测试的project,在自己电脑上IsAdmin返回False。单步调试后 GetLastError是 5 (〖5〗-拒绝访问。)
 
但是,我调试 正常的A软件,单步调试后,GetLastError 是1008 =ERROR_NO_TOKEN  〖1008〗-试图引用不存在的令牌。 
IsAdmin 返回 True。

https://blog.csdn.net/theone10211024/article/details/14001943
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 15:55:50
5楼: 大家用我的代码运行一下,谢谢。
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 bjlg (蓝天) ★☆☆☆☆ -
盒子活跃会员
2018/12/17 16:00:23
6楼: 这个问题对弈delphi,可能比较常见,大不了就重建一个项目
----------------------------------------------
http://delphi.icm.edu.pl/ftp/http://delphi-z.ru
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 16:16:23
7楼:  我自己刚才换个文件夹, 把 代码文件 复制过去,编译,还是 不行。
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 redboy136 (redboy136) ★☆☆☆☆ -
盒子活跃会员
2018/12/17 16:36:32
7楼: 下面代码通过:
var
  Form1: TForm1;
function CheckTokenMembership(TokenHandle: THANDLE; SidToCheck: Pointer; var IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership';
implementation

{$R *.dfm}

function IsAdmin: Boolean;
var

  psidAdmin: Pointer;

  B: BOOL;

const

  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));

  SECURITY_BUILTIN_DOMAIN_RID  = $00000020;

  DOMAIN_ALIAS_RID_ADMINS      = $00000220;

  SE_GROUP_USE_FOR_DENY_ONLY  = $00000010;

begin

  psidAdmin := nil;

  try

    Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,

      SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,

      psidAdmin));

    if CheckTokenMembership(0, psidAdmin, B) then

      Result := B

    else

      Result := False;

  finally

    if psidAdmin <> nil then

      FreeSid(psidAdmin);

  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  if not IsAdmin then
    Memo1.Lines.Add('没有管理员权限');
end;
----------------------------------------------
你梦我圆
作者:
男 redboy136 (redboy136) ★☆☆☆☆ -
盒子活跃会员
2018/12/17 16:48:59
8楼: function IsAdministratorAccount: Boolean;

var

  psidAdmin: Pointer;

  Token: THandle;

  Count: DWORD;

  TokenInfo: PTokenGroups;

  HaveToken: Boolean;

  I: Integer;

const

  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));

  SECURITY_BUILTIN_DOMAIN_RID  = $00000020;

  DOMAIN_ALIAS_RID_ADMINS      = $00000220;

  SE_GROUP_USE_FOR_DENY_ONLY  = $00000010;

begin

  Result := Win32Platform <> VER_PLATFORM_WIN32_NT;

  if Result then

    Exit;

  psidAdmin := nil;

  TokenInfo := nil;

  HaveToken := False;

  try

    Token := 0;

    HaveToken := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, Token);

    if (not HaveToken) and (GetLastError = ERROR_NO_TOKEN) then

      HaveToken := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, Token);

    if HaveToken then

    begin

      Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,

        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,

        psidAdmin));

      if GetTokenInformation(Token, TokenGroups, nil, 0, Count) or

         (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then

        RaiseLastOSError;

      TokenInfo := PTokenGroups(AllocMem(Count));

      Win32Check(GetTokenInformation(Token, TokenGroups, TokenInfo, Count, Count));

      for I := 0 to TokenInfo^.GroupCount - 1 do

      begin

        Result := EqualSid(psidAdmin, TokenInfo^.Groups[I].Sid);

        if Result then

          Break;

      end;

    end;

  finally

    if TokenInfo <> nil then

      FreeMem(TokenInfo);

    if HaveToken then

      CloseHandle(Token);

    if psidAdmin <> nil then

      FreeSid(psidAdmin);

  end;

end;
----------------------------------------------
你梦我圆
作者:
男 redboy136 (redboy136) ★☆☆☆☆ -
盒子活跃会员
2018/12/17 16:49:36
9楼: 上面管理员权限也测试通过。
----------------------------------------------
你梦我圆
作者:
男 dbyoung (dbyoung) ★☆☆☆☆ -
普通会员
2018/12/17 17:04:28
10楼: Windows权限问题,不应该用代码来控制。

打安装包时,将安装包设置为管理员权限才能安装。
安装后,程序就自动获得管理员权限了。

优点:
1、代码不用关心权限,更简洁了;
2、也不用关心WIN7、WIN10、Server等,各个操作系统的差异;
3、用户只要能安装上,就能运行。责任就扔给技术支持了。
----------------------------------------------
武汉天气不好
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/17 18:11:57
11楼: 找到原因了,我自己的低级错误。

我当时为了测试的程序,在用户电脑上看出具体哪个步骤返回False,是先在原来的函数里 增加了几行代码,然后再编译,运行的。

下面这行代码,运行时,else后面的语句会执行,但是会导致后面 GetLastError返回值发生变化。

if bSuccess then  Form1.Memo1.Lines.Add('测试1 成功') else  Form1.Memo1.Lines.Add('测试1 失败');


估计原因是,OpenThreadToken后,必须立即调用 GetLastError 来判断。

也许Form1.Memo1.Lines.Add('测试1 失败');内部是调用过其他WIN API了。


这个在自己电脑上测试的问题解决了。

但是,在用户电脑上 为何返回False,明天再查。
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/18 9:23:21
12楼: 那个用户的电脑,是加入公司 Windows域的,是不是 和这个有关?
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 earthsbest (全能中间件) ▲▲▲▲△ -
普通会员
2018/12/18 9:29:25
12楼: 如果是高版本 Delphi(貌似XE8后),工程设置-Execution Level 为 Require Administrator 就可以了,会自动编译一个 Manifest 文件到 EXE 里面,图标就会有个小盾牌了,很方便。
此帖子包含附件:
PNG 图像
大小:277.2K
----------------------------------------------
Delphi4Linux Delphi三层/FireDAC 技术群:734515869 http://www.cnblogs.com/rtcmw
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/18 9:33:22
13楼: 这个我手工加入了,而且用户家里电脑上能运行的。用户公司电脑上,以前也能运行的,昨天突然发现不行了。
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
作者:
男 xlonger (xlonger) ★☆☆☆☆ -
普通会员
2018/12/18 10:36:29
14楼: 似乎用下面这个函数的方法,也不行。
CheckTokenMembership 


不知道用户那个电脑 有什么特殊情况。
----------------------------------------------
我打的是酱油,而不是别的什么油。
我灌的是口水,而不是别的什么水。
我聊的折腾不是那个不折腾的折腾。
我说的阿娇不是那个邓玉娇的阿娇。
3个代表,6个为什么,9个肠胃炎。
D性强的领导干部都不喜欢热比娅。
我特别要讲的是,屁民网黄色论坛是我经常上网必选的 网站之一
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行171.875毫秒 RSS