目前,我正在学习QThread和QProcess,所以我想制作一个进程监控demo。但是,我遇到了两个无法解决的问题。
问题:
QProcess 可以成功启动一个进程(例如 cmd.exe),但是当我调用 stopProcess() 时,出现两个错误,或者有时主进程崩溃。
错误:
QProcess: Destroyed while process ("cmd.exe") is still running.
QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread.
使用 ProcessId() 获取进程 ID 后,我尝试使用 taskkill 命令终止它。但是,如果没有 /F 参数,我收到以下错误:
Error: Unable to terminate process 18668.
Reason: This process can only be forcefully terminated (use the /F option).
这是我的代码。您能帮我审核一下吗?谢谢!
主.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "processmonitor.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
ProcessMonitor *pm;
void setupConnection();
private slots:
void handleReadyReadStandardOutput(const QString& data);
void handleReadyReadStandardError(const QString& data);
void handleStarted(const QString& message);
void handleStateChanged(QProcess::ProcessState newState);
void handleStopped(const QString& message);
void on_start_process_clicked();
void on_stop_process_clicked();
};
#endif // MAINWINDOW_H
主窗口.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), pm(new ProcessMonitor)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
if(!pm) {
qDebug() << "ProcessMonitor Start Failed,Exit!";
QApplication::quit();
}
setupConnection();
}
MainWindow::~MainWindow()
{
if(pm) {
pm->stopProcess();
delete pm;
}
delete ui;
}
void MainWindow::setupConnection() {
connect(pm, &ProcessMonitor::readyReadStandardOutput, this, &MainWindow::handleReadyReadStandardOutput);
connect(pm, &ProcessMonitor::readyReadStandardError, this, &MainWindow::handleReadyReadStandardError);
connect(pm, &ProcessMonitor::started, this, &MainWindow::handleStarted);
connect(pm, &ProcessMonitor::stateChanged, this, &MainWindow::handleStateChanged);
connect(pm, &ProcessMonitor::stopped, this, &MainWindow::handleStopped);
}
// 'outInfo' component is a QPlainTextEdit
void MainWindow::handleReadyReadStandardOutput(const QString& data){
this->ui->outInfo->appendPlainText(data);
}
void MainWindow::handleReadyReadStandardError(const QString& data){
this->ui->outInfo->appendPlainText("Error:" + data );
}
// 'selfInfo' component is a QPlainTextEdit
void MainWindow::handleStarted(const QString& message){
this->ui->selfInfo->appendPlainText(message);
}
void MainWindow::handleStateChanged(QProcess::ProcessState newState) {
QString stateString;
switch(newState) {
case QProcess::NotRunning:
stateString = "Not Running";
break;
case QProcess::Starting:
stateString = "Starting";
break;
case QProcess::Running:
stateString = "Running";
break;
default:
stateString = "Unknown State";
break;
}
this->ui->selfInfo->appendPlainText("State Changed: " + stateString);
}
void MainWindow::handleStopped(const QString& message){
this->ui->selfInfo->appendPlainText(message);
}
void MainWindow::on_start_process_clicked()
{
this->pm->start();
}
void MainWindow::on_stop_process_clicked()
{
this->pm->stopProcess();
}
processmonitor.h
#ifndef PROCESSMONITOR_H
#define PROCESSMONITOR_H
#include <QThread>
#include <QProcess>
#include <QDebug>
class ProcessMonitor : public QThread
{
Q_OBJECT
public:
ProcessMonitor();
~ProcessMonitor();
void run() override;
void stopProcess();
signals:
void readyReadStandardOutput(QString output);
void readyReadStandardError(QString error);
void started(QString message);
void stateChanged(QProcess::ProcessState newState);
void stopped(QString message);
private:
QProcess *process;
private slots:
void handleReadyReadStandardOutput();
void handleReadyReadStandardError();
void handleStarted();
void handleStateChanged(QProcess::ProcessState newState);
};
#endif // PROCESSMONITOR_H
进程监视器.cpp
#include "processmonitor.h"
ProcessMonitor::ProcessMonitor()
: process(nullptr)
{
}
ProcessMonitor::~ProcessMonitor() {
stopProcess(); // Stop the process before destruction
}
void ProcessMonitor::run() {
if (this->process) {
delete this->process;
}
this->process = new QProcess();
if (!this->process) {
qDebug() << "Error: unable to instantiate QProcess";
return;
}
// this->process->setWorkingDirectory("E:\\test"); // set work dir
connect(this->process, &QProcess::readyReadStandardOutput, this, &ProcessMonitor::handleReadyReadStandardOutput);
connect(this->process, &QProcess::readyReadStandardError, this, &ProcessMonitor::handleReadyReadStandardError);
connect(this->process, &QProcess::started, this, &ProcessMonitor::handleStarted);
connect(this->process, &QProcess::stateChanged, this, &ProcessMonitor::handleStateChanged);
this->process->start("cmd.exe");
qDebug() << "ProcessID:" << this->process->processId();
this->exec();
}
void ProcessMonitor::stopProcess() {
if (!this->process) {
emit stopped("[ProcessMonitor] No Process Created");
return;
}
// this->process->close();
this->process->terminate();
// this->process->kill();
if (this->process->waitForFinished(3000)) {
emit stopped("[ProcessMonitor] Process Stopped");
} else {
this->process->kill();
emit stopped("[ProcessMonitor] Process terminated failed, Killing");
}
delete this->process; // Release the pointer after a safety check
this->process = nullptr;
this->quit();
}
void ProcessMonitor::handleReadyReadStandardOutput() {
if (!this->process) return;
QByteArray data = this->process->readAllStandardOutput();
emit readyReadStandardOutput(QString::fromLocal8Bit(data));
}
void ProcessMonitor::handleReadyReadStandardError() {
if (!this->process) return;
QByteArray data = this->process->readAllStandardError();
emit readyReadStandardError(QString::fromLocal8Bit(data));
}
void ProcessMonitor::handleStarted() {
emit started("[ProcessMonitor] Process Started");
}
void ProcessMonitor::handleStateChanged(QProcess::ProcessState newState) {
emit stateChanged(newState);
}
我尝试在 process->terminate() 之前调用 process->close(),但仍然出现此错误。有时,主进程也会崩溃。
QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread
尝试:
process.terminate();
if (!process.waitForFinished(5000)) { // Timeout di 5 secondi
process.kill(); // Forza l'arresto se non termina in tempo
}
然后检查:
connect(&process, &QProcess::finished, [](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << "Process terminated with code:" << exitCode
<< "Status:" << exitStatus;
});