Я запускаю программу командной строки из Delphi.
Я использую CreateProcess, так как мне нужно зафиксировать вывод и отобразить его в заметке.
Моя проблема сейчас в том, что программа, которую я выполняю, должна работать «от имени администратора», чтобы работать правильно. Если я запускаю его в командной строке «от имени администратора», он выполняется нормально.
Как указать CreateProcess работать от имени администратора? Я вижу, что в ShellExecute есть параметр lpVerb, для которого можно установить значение «runas», чтобы это работало, но мне нужно, чтобы CreateProcess мог захватить вывод командной строки и отобразить его.
Я думал, что если я запущу свой exe от имени администратора, эти права будут переданы команде CreateProcess, но, похоже, этого не происходит.
Любые идеи о том, как я могу сказать CreateProcess, что я хочу запустить процесс с повышенными правами?
Вот рабочий код, который отлично запускает командную строку (только не от имени администратора)
var
SA: TSecurityAttributes;
SI: TStartupInfo;
PI: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
Handle: Boolean;
begin
with SA do begin
nLength := SizeOf(SA);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
try
with SI do
begin
FillChar(SI, SizeOf(SI), 0);
cb := SizeOf(SI);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_HIDE;
hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
hStdOutput := StdOutPipeWrite;
hStdError := StdOutPipeWrite;
end;
Handle := CreateProcess(nil, PWideChar('cmd.exe /C ' + CommandLine),
nil, nil, True, 0, nil,
PWideChar(WorkDir), SI, PI);
Об этом задавали в течение 15 лет после выпуска Vista. Конечно, веб-поиск привел бы вас к одному из многих существующих сообщений?
программа, которую я выполняю, должна работать «от имени администратора», чтобы работать правильно.
Если это так, то у этой программы должен быть манифест UAC, в котором указано requestedExecutionLevel
из requireAdministrator
. В этом случае CreateProcess()
завершится ошибкой с кодом ERROR_ELEVATION_REQUIRED
, если ваша программа не запущена от имени администратора с повышенными правами. Если это не так, то эта другая программа не разработана должным образом.
Как указать CreateProcess работать от имени администратора?
Вы не можете, так как у него нет такой возможности.
Ваши варианты:
запустите свою программу как администратор с повышенными правами, чтобы вызов CreateProcess()
запускал команду в том же контексте с повышенными правами администратора.
используйте ShellExecute/Ex()
с глаголом "runas"
, чтобы запустить команду от имени администратора с повышенными правами (как вы уже знаете). Но тогда вы не сможете зафиксировать выходные данные нового процесса, если только вы не дадите команду передать свои выходные данные во временный файл, который вы затем сможете прочитать после завершения команды.
пусть ваша основная программа использует ShellExecute/Ex("runas")
для запуска отдельной копии себя в качестве администратора с повышенными правами, а затем этот процесс может вызвать CreateProcess()
, захватить вывод и отправить его обратно в ваш основной процесс через механизм IPC по вашему выбору.
реорганизуйте код захвата CreateProcess
+ в отдельный объект COM, а затем используйте прозвище COM Elevation Moniker для создания экземпляра этого объекта в контексте с повышенными правами администратора, когда это необходимо.
используйте неофициальный CreateProcessElevated()
API, который описан в этой статье: Vista UAC: Полное руководство
Я думал, что если я запущу свой exe от имени администратора, эти права будут переданы команде CreateProcess, но, похоже, этого не происходит.
Да, это будет.
Я использовал это в своих программах
function RunAsAdmin(hWnd: hWnd; filename: string; Parameters: string; Visible: Boolean = true): Boolean;
{
See Step 3: Redesign for UAC Compatibility (UAC)
http://msdn.microsoft.com/en-us/library/bb756922.aspx
This code is released into the public domain. No attribution required.
}
var
sei: TShellExecuteInfo;
begin
ZeroMemory(@sei, SizeOf(sei));
sei.cbSize := SizeOf(TShellExecuteInfo);
sei.Wnd := hWnd;
sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI;
sei.lpVerb := PChar('runas');
sei.lpFile := PChar(filename); // PAnsiChar;
if Parameters <> '' then
sei.lpParameters := PChar(Parameters); // PAnsiChar;
if Visible then
sei.nShow := SW_SHOWNORMAL // Integer;
else
sei.nShow := SW_HIDE;
Result := ShellExecuteEx(@sei);
end;
это помогает?