使用 ShellExecute 将参数传递到使用 admin 的 Powershell

问题描述 投票:0回答:1

我尝试在 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)。

powershell winapi
1个回答
0
投票
// 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,我可以在脚本中执行自定义错误代码。我没有发布整个脚本+函数,但这代表了好的部分。

© www.soinside.com 2019 - 2024. All rights reserved.