如何使用QProcess在控制台窗口中启动和终止cmd.exe

How to launch and later terminate cmd.exe in a console window with QProcess

本文关键字:启动 终止 cmd exe 窗口 何使用 QProcess 控制台      更新时间:2023-10-16

我需要通过QProcess运行一个可见的cmd.exe窗口,并最终终止它。shell的控制台窗口必须位于前台,并且必须对用户可见。

如果我使用QProcess::start()启动它,控制台窗口永远不会出现。如果我使用类方法QProcess::startDetached()来启动它,我就不能使用实例方法terminate()来终止它。

在Windows上,QProcess有两种操作模式:

  1. 正常模式,当你使用实例方法,如start()。在这种模式下,QProcess本身是正在运行的应用程序的控制台,如果它请求一个的话。这个控制台是一个逻辑对象(类似于Unix上的伪tty),没有可见的外观。

  2. 使用类方法 startDetached时的分离模式。如果正在运行的进程请求一个控制台,Windows为它提供一个控制台窗口。

因此,要利用windows提供的控制台窗口,唯一的选择是分离启动。

如果您希望一个人在cmd.exe执行您的命令后留下一个打开的控制台窗口,则适用以下命令:

  • 每个传递执行的命令都需要以/k开头

  • /k和命令是单独的参数

要在应用程序退出时终止进程,可以使用以下类的实例,使其成为应用程序实例的子实例:

#include <windows.h>
...
class ProcessKiller : public QObject {
  qint64 m_pid;
public:
  ProcessKiller(qint64 pid, QObject * parent = 0) : 
    QObject(parent), m_pid(pid) {}
  ~ProcessKiller() {
    HANDLE hApp = OpenProcess(PROCESS_QUERY_INFORMATION
                              | PROCESS_TERMINATE, FALSE, m_pid);
    if (hApp == NULL) return;
    TerminateProcess(hApp, NULL);
    CloseHandle(hApp);
  }
}

因此,要在windows提供的控制台窗口中以两个echo命令开始运行cmd.exe,并在应用程序退出时杀死它,将是:

qint64 pid;
QProcess::startDetached("cmd.exe", QStringList()
  << "/k" << "echo foo"
  << "/k" << "echo bar",
  QDir::currentPath(), &pid);
new ProcessKiller(pid, qApp);

下面的代码将解决我的问题:

qint64 pID;
QProcess *myProcess = new QProcess(this);
QStringList arguments;
arguments << "/k cd /d " << "c:path to be opened";
myProcess->startDetached("cmd.exe", arguments, "", &pID);
...
...
QString pidString;
pidString.setNum(pID);
QString killProcessUsingPid = "taskkill /PID ";
killProcessUsingPid.append(pidString);
system(killProcessUsingPid.toStdString().c_str());