关于C#:Qt5:使用QProcess :: startDetached调用.bat文件在System32中找不到程序

Qt5: Calling .bat file with QProcess::startDetached doesn't find program in System32

我有一个带按钮的小型Qt GUI程序,该程序会启动.bat文件。

调用.bat的重要部分是:

1
2
3
4
5
6
7
8
9
10
11
12
void MainWindow::on_pushButton_clicked()
{
    int r = QMessageBox::warning(this, tr("Shutdown System"),
    tr("Do you want to close the program and the system?"),
    QMessageBox::Yes | QMessageBox::Default,
    QMessageBox::No,
    QMessageBox::Cancel | QMessageBox::Escape);

    if (r == QMessageBox::Yes){
        QProcess::startDetached("cmd /C shutdown_all.bat");
    }
}

我打算呼叫C:\\Windows\\System32\\psshutdown.exe中的PSShutdown,当然也要呼叫PATH

出于测试目的,我将其放在.bat中:

1
2
3
cd C:\\Windows\\System32
psshutdown
PAUSE

当单独调用.bat文件时,似乎可以找到该程序并打印有关它的信息,但是当我使用该按钮调用该程序时,它找不到psshutdown.exe

结果捕获:

使用Qt程序调用.bat:
.bat

双击调用.bat(预期结果):
enter


psshutdown.exe是Windows上通常不存在的可执行文件。它是Windows Sysinternals的工具,需要手动下载并复制到任何目录。

在64位Windows上,64位应用程序访问%SystemRoot%\\System32中的64位应用程序和动态链接库。

但是,在访问%SystemRoot%\\System32以运行可执行文件或加载DLL时,Windows文件系统重定向器会将在64位Windows上运行的x86应用程序重定向到32位系统目录%SystemRoot%\\SysWOW64

一种解决方案是在批处理文件中使用以下代码:

1
2
3
4
5
6
7
8
9
10
if exist %SystemRoot%\\System32\\psshutdown.exe (
    %SystemRoot%\\System32\\psshutdown.exe
) else if exist %SystemRoot%\\Sysnative\\psshutdown.exe (
    %SystemRoot%\\Sysnative\\psshutdown.exe
) else if %SystemRoot%\\SysWOW64\\psshutdown.exe (
    %SystemRoot%\\SysWOW64\\psshutdown.exe
) else (
    echo Error: Can't find psshutdown.exe in system directory of Windows.
    pause
)

此批处理代码独立于将Qt应用程序编译为32位和64位Windows的x64或x86应用程序,并且独立于以前将系统目录psshutdown.exe复制到其中的方式起作用。

第一个IF条件适用于仅具有System32的32位Windows上的32位应用程序以及具有64位System32和32位SysWOW64的64位Windows上的64位应用程序。 >

第二个IF条件适用于64位Windows上的32位应用程序,用于访问64位System32

第三个IF条件适用于64位Windows上的64位应用程序,用于访问32位SysWOW64

另一种解决方案是使用Windows资源管理器之类的64位文件管理器将文件psshutdown.exe复制到两个目录中

1
2
%SystemRoot%\\System32
%SystemRoot%\\SysWOW64