参见英文答案 >
How to start a new process without administrator privileges from a process with administrator privileges?9个
一旦启动具有管理员权限的应用程序,在该应用程序中使用ShellExecute执行的程序将继承管理员权限.但这不是我想要的:它只需要在没有额外权限的情况下定期启动. ShellExecute接受参数OPEN(常规)和RUNAS(管理员).但是,如果在以管理员身份启动应用程序后使用OPEN,它仍然像RUNAS一样.
一旦启动具有管理员权限的应用程序,在该应用程序中使用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.