我尝试在 Qt 程序中使用 ShellExecute 在管理员中运行 PowerShell,但参数似乎没有传输。
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 argument(s) Missing in”的警告,并吐出脚本。我没有百分号,并且脚本本身可以在 powershell 中运行(当我将 2 个“缺失”参数直接添加到脚本中时)。当我使用 Qt Process 时,这也没有问题,但我希望调用 UAC,所以我使用 ShellExecute(根据标头是 ShellExecuteW)。
// 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,我可以在脚本中执行自定义错误代码。我没有发布整个脚本+函数,但这代表了好的部分。