0
点赞
收藏
分享

微信扫一扫

学习网络编程No.11【传输层协议之UDP】

IT程序员 03-03 17:00 阅读 2

有的时候我们需要在自己程序运行过程中调用其他进程,那么就需要用到QProcess。

首先可以了解一些关于进程的相关知识:线程与进程,你真得理解了吗_进程和线程的区别-CSDN博客

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础。 

如何查看系统中正在运行的进程以及如何杀死进程:

Windows:

启动进程:tasklist

杀死进程:taskkill /F /PID 4204(进程id) 

 

Linux:

查看进程:ps -ef

杀死进程:kill -9 4341(进程id)

 QProces的使用:

QProcess通过start和startDetached两个方法都可以启动进程,其中前者是一体式启动,即外部程序启动后,将随主程序的退出而退出。后者是分离式启动,即外部程序启动后,当主程序退出时并不退出,而是继续运行。

这次主要说start这个方法:
void 
start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode = ReadWrite) 

主要需要注意第一个参数和第二个参数,第一个参数是要执行的命令或者程序,第二个参数是这个程序的运行参数。关于这两个先看一个最简单的qt程序代码:

#include <QCoreApplication>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    return a.exec();
}

这个代码大家再熟悉不过来,就是一个最简单的qt控制台程序,不知道大家有没有注意过main函数的两个参数argc和argv[]。

  1. int argc:代表命令行参数的数量,即传递给程序的参数个数。通常情况下,argc至少为1,因为第一个参数通常是程序本身的名称。

  2. char *argv[]:是一个指向字符指针数组的指针,其中每个元素是一个指向表示一个命令行参数的C风格字符串的指针。argv[0]通常是程序的名称,后续元素是传递给程序的其他参数。

试着打印一下:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  for (int i = 0; i < argc; ++i) {
    qDebug() << argv[i];
  }
  return a.exec();
}

编译运行查看打印:

打印了一个参数,即程序的名称。试着给这个控制台程序启动时加几个参数:

 

使用QtCreator传入运行参数也可以这样设置:

 

 运行查看结果:

 也可以使用QCoreApplication::arguments()打印参数:

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  for (int i = 0; i < argc; ++i) {
    qDebug() << argv[i];
  }
  QStringList args = QCoreApplication::arguments();
  for (const QString &arg : args) {
    qDebug() << arg;
  }
  return a.exec();
}

编译运行查看:

QProcess使用start传入对应参数,这是要启动的程序:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
  ui->setupUi(this);
  for (const QString &arg : QCoreApplication::arguments()) {
    ui->textEdit->append(arg);
  }
}

MainWindow::~MainWindow() { delete ui; }

将程序参数显示到对应QTextEdit上:

#include <QCoreApplication>
#include <QDebug>
#include <QProcess>
int main(int argc, char *argv[]) {
  QCoreApplication a(argc, argv);
  QProcess *p = new QProcess;
  QStringList args;
  args << "1"
       << "2"
       << "3";
  p->start("G:\\qtprojects\\ConsoleP\\debug\\ConsoleP.exe", args);
  return a.exec();
}

编译查看运行结果:

QProcess通过processId来获取对应进程id。 

关于QProcess的信号:

 其中readyReadStandardError()与readyReadStandardOutput()收到对应信号后通过readAllStandardOutput()与readAllStandardError()来获取对应程序标准输出以及异常输出,进程运行完成后会触发finished()信号,进程状态改变会触发stateChanged信号。写一个例子:

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class QProcess;
class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    void appendLog(const QString &text);

private slots:
    void on_open_clicked();

    void on_cmd_clicked();

    void on_clear_clicked();

private:
    Ui::MainWindow *ui;
    QProcess *m_Process;
};
#endif // MAINWINDOW_H

源文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QFileDialog>
#include <QProcess>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);
    m_Process = new QProcess;
    connect(m_Process, &QProcess::readyReadStandardOutput, [=]() {
        QByteArray output = m_Process->readAllStandardOutput();
        QString outputString = QString::fromLocal8Bit(output);
        appendLog("output:" + outputString);
    });
    connect(m_Process, &QProcess::readyReadStandardError, [=]() {
        QByteArray output = m_Process->readAllStandardError();
        QString outputString = QString::fromLocal8Bit(output);
        appendLog("error:" + outputString);
    });
    connect(m_Process, &QProcess::stateChanged,
            [=](QProcess::ProcessState newState) {
                appendLog("stateChanged:" + QString::number(newState));
            });
    connect(m_Process, &QProcess::errorOccurred,
            [=](QProcess::ProcessError error) {
                appendLog("errorOccurred:" + QString::number(error));
            });
    connect(m_Process,
            static_cast<void (QProcess::*)(int exitCode,
                                           QProcess::ExitStatus exitStatus)>(
                &QProcess::finished),
            [=](int exitCode, QProcess::ExitStatus exitStatus) {
                appendLog("finished:" + QString::number(exitCode) + ":" +
                          QString::number(exitStatus));
            });
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::appendLog(const QString &text) {
    ui->textEdit->append(QString("%1:program=%2:pid=%3:%4")
                             .arg(QDateTime::currentDateTime().toString(
                                 "yyyy/MM/dd hh:mm:ss.zzz"))
                             .arg(m_Process->program())
                             .arg(m_Process->processId())
                             .arg(text));
}

void MainWindow::on_open_clicked() {
    QString pragramName =
        QFileDialog::getOpenFileName(nullptr, nullptr, QString());
    ui->program->setText(pragramName);
}

void MainWindow::on_cmd_clicked() {
    if (ui->program->text().isEmpty()) return;
    m_Process->setProgram(ui->program->text());
    QStringList arguments;
    arguments << ui->arguments->text();
    m_Process->setArguments(arguments);
    m_Process->start();
}

void MainWindow::on_clear_clicked() {
    ui->textEdit->clear();
}

ui:

编译运行然后再对应输入框输入程序路径以及对应参数,以刚刚写的例子为例:

 然后关闭启动的进程:

可以看到关闭后触发了对应finished()信号,然后通过打印可以看到状态从打开到关闭的变化情况是:1(Starting)->2(Running)->0(NotRunning) 。并且触发finished()信号时由于进程已经关闭,所以获取不到对应的进程id,但是stateChanged(NotRunning)会先于finished(),并且这时进程没有完全关闭所有能获取到对应进程id。也可以输入一些cmd命令:

举报

相关推荐

0 条评论