После того, как вы запустили приложение с правами администратора, программы, выполненные с использованием ShellExecute
в этом приложении, наследуют разрешение администратора. Но это не то, что я хочу: он просто должен запускаться регулярно без дополнительных разрешений. ShellExecute
принимает параметр OPEN
(обычный) и RUNAS
(Администратор). Но если вы используете OPEN
после того, как вы запустили приложение в качестве администратора, оно все равно действует как RUNAS
.Запуск приложения без прав администратора
Следующий пример демонстрирует это: если вы запустите его с помощью обычных разрешений, то он говорит: «Начал обычный». Как только вы нажмете 1 для «admin», он начнется с администратора. Если вы нажмете 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: http://stackoverflow.com/a/28572886/1870208
function IsAdministrator: 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;
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, nil, SW_SHOWNORMAL);
Break;
end;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Проголосовало за повторное открытие, поскольку ответ в вопросе, на который ссылается, является неправильным способом, правильным способом было бы получить токен процесса, вызов 'GetTokenInformation' с параметром« TokenLinkedToken », чтобы получить неэлавированный токен. Используйте этот токен для запуска нового процесса. Очевидно, также проверить, действительно ли UAC включен (http://www.remkoweijnen.nl/blog/2011/08/11/gettokeninformation-with-tokenlinkedtoken-returns-error-1312/). – Remko