Я пытаюсь запустить PowerShell от имени администратора, используя ShellExecute в программе Qt, но аргументы, похоже, не передаются.
QString ruleName = QCoreApplication::applicationName();
QString exePath = QCoreApplication::applicationFilePath();
// Define the embedded PowerShell scripts as strings
const QString checkFirewallScript = QString(
"param([string]$ruleName,[string]$exePath)"
"a powershell script of 70 lines"
).arg(ruleName, exePath);
// Construct the PowerShell command with the script
QString command = QString("powershell.exe -Command \"%1\"").arg(checkFirewallScript);
// Convert the command to a wide string
LPCWSTR commandC = (const wchar_t*) command.utf16();
// Use ShellExecute to run the command as administrator
HINSTANCE exitCode = ShellExecute(NULL, L"runas", L"powershell.exe", commandC, NULL, SW_SHOWNORMAL);
Мой код выхода всегда 42, хотя я читал, что выше 32, это просто номер экземпляра. Я получаю предупреждение в поле ошибки Qt «QString::arg: 2 аргумента(ов) отсутствует», и оно выдает сценарий. У меня нет знаков процента, и сценарий работает в PowerShell сам по себе (когда я добавляю два «отсутствующих» аргумента непосредственно в сценарий). Это также работало без проблем, когда я использовал Qt Process, но я хочу, чтобы UAC вызывался, поэтому я использую ShellExecute (который, согласно заголовкам, является ShellExecuteW).
Правильный способ использования Qt — это API QProcess. Вам следует удалить теги Qt из вашего вопроса или переформулировать его с помощью QProcess.
@Йенс Йенс Ты прав. Я пытаюсь подключить UAC, поэтому на самом деле я не использую Qt, кроме некоторых начальных строк.





// Get the application file path and name
QString ruleName = QCoreApplication::applicationName();
QString exePath = QCoreApplication::applicationFilePath();
// Define the embedded PowerShell scripts as strings
const QString checkFirewallScript = R"(param(
[Parameter(Mandatory=$true)][string]$ruleName,
[Parameter(Mandatory=$true)][string]$exePath
)
$rules = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue |
...
)";
// Construct the command to run PowerShell with the script
QString command = QString("-ExecutionPolicy Bypass -F \"%1\" -ruleName \"%2\" -exePath \"%3\"")
.arg(tempScriptPath)
.arg(ruleName)
.arg(exePath);
// Convert the command to a wide string
std::wstring commandW = command.toStdWString();
// Initialize the SHELLEXECUTEINFO structure
SHELLEXECUTEINFOW sei = {0};
sei.cbSize = sizeof(SHELLEXECUTEINFOW);
sei.fMask = SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = NULL;
sei.lpVerb = L"runas";
sei.lpFile = L"powershell.exe";
sei.lpParameters = commandW.c_str();;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOWNORMAL;
sei.hInstApp = NULL;
//run
if (!ShellExecuteExW(&sei)) { ...
WaitForSingleObject(sei.hProcess, 10000); // 10 seconds
DWORD exitCode;
GetExitCodeProcess(sei.hProcess, &exitCode);
CloseHandle(sei.hProcess);
if (exitCode == 18000) {
Это потребовало некоторых усилий, пришлось отказаться от запуска всего сценария в качестве аргумента, потому что я продолжал сталкиваться со слишком большим количеством проблем. Это позволяет мне запускать powershell в отдельном окне, а также запрашивать разрешения администратора для выполнения некоторого обслуживания брандмауэра. Спасибо
IInspectable для рекомендации ShellExecuteExW, я могу использовать собственные коды ошибок в сценарии. Я не публиковал весь скрипт + функцию, но здесь представлены хорошие стороны.
пришлось ждать 2 дня
commandповторяет имя исполняемого файла. Это неправильно. Для правильного сообщения об ошибках вместо этого вызовите ShellExecuteExW. Ни вызов API (ниCreateProcessW, если уж на то пошло) не сообщит о результатах вновь созданного процесса.