加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 无管理员权限启动应用程序

发布时间:2020-12-15 04:11:37 所属栏目:大数据 来源:网络整理
导读:参见英文答案 How to start a new process without administrator privileges from a process with administrator privileges?9个 一旦启动具有管理员权限的应用程序,在该应用程序中使用ShellExecute执行的程序将继承管理员权限.但这不是我想要的:它只需要
参见英文答案 > How to start a new process without administrator privileges from a process with administrator privileges?9个
一旦启动具有管理员权限的应用程序,在该应用程序中使用ShellExecute执行的程序将继承管理员权限.但这不是我想要的:它只需要在没有额外权限的情况下定期启动. ShellExecute接受参数OPEN(常规)和RUNAS(管理员).但是,如果在以管理员身份启动应用程序后使用OPEN,它仍然像RUNAS一样.

以下示例演示了这一点:如果您使用常规权限启动它,则会显示“Started regular”.一旦你为’admin’按1,它将以管理员身份启动.如果在新创建的提示中按2,它将不会启动“常规”提示,而是再次启动“管理员”提示.

我在RUNAS(https://superuser.com/a/374866)中找到了一些关于某些参数的东西,但它们不能在ShellExecute中传递.有任何想法吗?

program WindowsPrivilegeTest;
{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,Winapi.Windows,Winapi.ShellAPI;

function CheckTokenMembership(TokenHandle: THANDLE; SidToCheck: Pointer; var 
  IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership';

// Source: https://stackoverflow.com/a/28572886/1870208
function IsAdministrator: Boolean;
var
  psidAdmin: Pointer;
  B: BOOL;
const
  SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (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,psidAdmin));

    if CheckTokenMembership(0,psidAdmin,B) then
      Result := B
    else
      Result := False;
  finally
    if psidAdmin <> nil then
      FreeSid(psidAdmin);
  end;
end;

var
  lLine : String;
  lOperation : PChar;
begin
  try
    if IsAdministrator then
    begin
      Writeln('Started as administrator');
    end
    else
    begin
      Writeln('Started regular');
    end;

    while True do
    begin
      Writeln('');
      Writeln('How to start? 1 = admin,2 = regular user. Type number and press enter');
      ReadLn(lLine);
      lOperation := '';

      if lLine = '1' then
      begin
        lOperation := 'RUNAS';
      end
      else
      if lLine = '2' then
      begin
        lOperation := 'OPEN';
      end;

      if lOperation <> '' then
      begin
        ShellExecute(0,lOperation,PChar(ParamStr(0)),nil,SW_SHOWNORMAL);
        Break;
      end;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName,': ',E.Message);
  end;
end.

解决方法

我曾经在创建安装程序时解决这个难题,这是可能的解决方案之一.

我们的想法是创建一个以用户权限运行的后台进程,主应用程序与之通信并让它知道要启动的程序 – 启动的进程将具有用户权限.

它应该像这样工作:后台进程像往常一样启动,具有用户权限.启动时,它会以管理员身份启动您的主程序.后台进程保持隐藏状态并等待主进程发出的命令.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读