Повышающие привилегии не работают с UseShellExecute = false
Я хочу запустить дочерний процесс (действительно то же самое, консольное приложение) с повышенными привилегиями, но со скрытым окном.
Далее:
var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location)
{
UseShellExecute = true, // !
Verb = "runas",
};
var process = new Process
{
StartInfo = info
};
process.Start();
и это работает:
var identity = new WindowsPrincipal(WindowsIdentity.GetCurrent());
identity.IsInRole(WindowsBuiltInRole.Administrator); // returns true
Но UseShellExecute = true
создает новое окно, и я также не могу перенаправить вывод.
Итак, когда я сделаю следующее:
var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location)
{
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false, // !
Verb = "runas"
};
var process = new Process
{
EnableRaisingEvents = true,
StartInfo = info
};
DataReceivedEventHandler actionWrite = (sender, e) =>
{
Console.WriteLine(e.Data);
};
process.ErrorDataReceived += actionWrite;
process.OutputDataReceived += actionWrite;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
Это не повышает привилегии и код выше возвращает false. Почему??
Ответы
Ответ 1
ProcessStartInfo.Verb будет иметь эффект только в том случае, если процесс запускается с помощью ShellExecuteEx(). Для чего требуется UseShellExecute = true. Перенаправление ввода-вывода и скрытие окна могут работать, только если процесс запускается CreateProcess(). Для этого требуется UseShellExecute = false.
Ну, почему это не работает. Не уверен, что запрет запуска скрытого процесса, который обходит UAC, был намеренным. Вероятно. Очень вероятно.
Отметьте этот Q + A для манифеста, который вам нужно отобразить приглашение повышения UAC.
Ответ 2
В моем случае было нормально получать выходные данные после того, как завершился дочерний процесс. Вот решение, которое я придумал. Он использует временный файл:
var output = Path.GetTempFileName();
var process = Process.Start(new ProcessStartInfo
{
FileName = "cmd",
Arguments = "/c echo I'm an admin > " + output, // redirect to temp file
Verb = "runas", // UAC prompt
UseShellExecute = true,
});
process.WaitForExit();
string res = File.ReadAllText(output);
// do something with the output
File.Delete(output);
Ответ 3
Отметьте этот ответ.
Это, как представляется, обеспечивает обходное решение. Но я рекомендую попробовать другие методы, такие как Named Pipes, когда у вас есть доступ к исходному коду дочернего процесса.