C++ Qt開發:QProcess進程管理模塊

Qt 是一個跨平臺C++圖形界面開發庫,利用Qt可以快速開發跨平臺窗體應用程序,在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現圖形化開發極大的方便了開發效率,本章將重點介紹如何運用QProcess組件實現針對進程的控制管理等。

當你在使用Qt進行跨平臺應用程序開發時,經常需要與外部進程進行交互,這時就可以利用Qt的QProcess模塊。QProcess模塊提供了啓動和控制外部進程的功能,能夠執行外部命令、運行其他可執行文件,以及與外部進程進行通信。通過QProcess,可以方便地執行命令行命令、調用系統工具、執行腳本等。QProcess還可以捕獲外部進程的輸出,以及監視外部進程的運行狀態,從而實現更靈活、高效的進程管理。

以下是QProcess類的一些常用函數及其解釋的表格:

函數 描述
start(const QString &program, const QStringList &arguments) 啓動一個新的進程,program參數指定要執行的程序,arguments參數指定傳遞給程序的參數列表。
startDetached(const QString &program, const QStringList &arguments) 啓動一個新的進程,但不會等待進程退出,也不會將輸出傳遞給調用進程。
waitForStarted(int msecs = 30000) 等待進程啓動,如果在指定時間內進程沒有啓動,將返回false。
waitForFinished(int msecs = 30000) 等待進程退出,如果在指定時間內進程沒有退出,將返回false。
readAllStandardOutput() 讀取進程的標準輸出,並返回爲QByteArray
readAllStandardError() 讀取進程的標準錯誤輸出,並返回爲QByteArray
write(const QByteArray &data) 向進程的標準輸入寫入數據。
closeWriteChannel() 關閉進程的標準輸入。
kill() 終止進程。
terminate() 終止進程。
start(const QString &program) 啓動一個新的進程,program參數指定要執行的程序。
setWorkingDirectory(const QString &dir) 設置進程的工作目錄。
state() 返回進程的當前狀態。
error() 返回進程的錯誤狀態。
pid() 返回進程的進程ID。
waitForBytesWritten(int msecs = 30000) 等待寫入到進程的數據已經被完全寫入。
waitForReadyRead(int msecs = 30000) 等待進程有數據可讀。
startDetached(const QString &program) 啓動一個新的進程,但不會等待進程退出,也不會將輸出傳遞給調用進程。
setProcessChannelMode(QProcess::ProcessChannelMode mode) 設置進程通信模式,可選值包括QProcess::SeparateChannelsQProcess::MergedChannels

這些函數提供了控制進程的各種方法,可以實現啓動、監視、控制和與外部進程進行交互的功能。

進程控制模塊可以實現對特定進程的啓動關閉,本章將以執行命令行爲例,通過調用Start()可以拉起一個第三方進程。

QProcess類的start()函數有幾種不同的重載形式,但最常用的是以下形式:

bool QProcess::start(
    const QString &program, 
    const QStringList &arguments, 
    QIODevice::OpenMode mode = ReadWrite
)

函數用於啓動一個新的進程,並執行指定的程序(program參數)。arguments參數指定了傳遞給程序的參數列表,它是一個QStringList類型的參數,可以爲空。mode參數指定了啓動進程時打開的模式,默認爲ReadWrite。函數返回一個bool類型的值,表示進程是否成功啓動。

當調用start()執行命令後,我們則可以通過readAllStandardOutput()函數從進程的標準輸出中讀取所有可用的數據,並將其返回爲 QByteArray 對象。

QByteArray QProcess::readAllStandardOutput()

這個函數沒有參數,它會立即返回當前可用的標準輸出數據,並將輸出數據作爲字節數組返回。如果沒有可用的輸出數據,它將返回一個空的字節數組。

當然了,與之對應的readAllStandardError()是函數,該函數可以用於從進程的標準錯誤輸出中讀取所有可用的數據,並將其返回爲 QByteArray 對象。

QByteArray QProcess::readAllStandardError()

該函數同樣沒有參數,它會立即返回當前可用的標準錯誤輸出數據,並將輸出數據作爲字節數組返回。如果沒有可用的錯誤輸出數據,它將返回一個空的字節數組。

1.1 獲取進程信息

此處我們以輸出系統進程信息爲例,通常可以調用tasklist /FO CSV來獲取系統中的進程列表,並將其輸出爲CSV格式,通過調用如下函數則可以獲取到系統進程信息。

process.start("tasklist", QStringList() << "/FO" << "CSV");

此時通過調用readAllStandardOutput函數我們可以將緩衝區內的數據讀出並將其放入到一個QString類型變量內;

QString output = process.readAllStandardOutput();

當具備了這個列表後,就可以根據冒號來逐行讀入並切割,通過循環的方式將其追加到treeWidget組件內,並以此來實現展示的效果;

void MainWindow::on_pushButton_clicked()
{
    CallProcess();

    ui->treeWidget->clear();

    QProcess process;
    process.start("tasklist", QStringList() << "/FO" << "CSV");

    if (process.waitForFinished())
    {
        QString output = process.readAllStandardOutput();
        output.replace("\"", "");

        QStringList lines = output.split("\n");

        // 跳過第一行標題
        for(int i = 1; i < lines.size(); ++i)
        {
            QStringList fields = lines[i].split(",");

            // 確保至少有五個字段
            if(fields.size() >= 5)
            {
                QStringList rowData;
                for(int j = 0; j < 5; ++j)
                {
                    rowData << fields[j].trimmed();
                }
                ui->treeWidget->addTopLevelItem(new QTreeWidgetItem(rowData));
            }
        }

        // 設置列標題
        ui->treeWidget->setHeaderLabels(QStringList() << "進程名稱" << "PID" << "會話名稱" << "Session"<< "內存佔用");
    } else
    {
        QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
        item->setText(0, "Failed to execute tasklist command.");
    }
}

運行後當點擊輸出系統進程時則可以看到完整的進程輸出效果,如下圖所示;

使用此方法我們可以很好的讀取到系統中的各種信息,只要能夠合理的過濾出想要的字段即可,當需要輸出系統信息時我們可以通過process.start("systeminfo")調用系統命令獲取到,如下代碼所示;

void MainWindow::on_pushButton_2_clicked()
{
    ui->treeWidget->clear();

    // 獲取系統信息
    QProcess process;
    process.start("systeminfo");

    if (process.waitForFinished())
    {
     QByteArray output = process.readAllStandardOutput();

     // 使用正確的文本編碼對輸出進行解碼
     QTextCodec *codec = QTextCodec::codecForName("GBK");
     QString text = codec->toUnicode(output);

     QStringList lines = text.split("\n");
     for (const QString &line : lines)
     {
         // 解析系統信息,添加到 QTreeWidget 中
         QStringList fields = line.split(":", Qt::SkipEmptyParts);
         if (fields.size() >= 2)
         {
             QString property = fields[0].trimmed();
             QString value = fields[1].trimmed();

             QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
             item->setText(0, property);
             item->setText(1, value);
         }
     }

     // 設置列標題
     ui->treeWidget->setHeaderLabels(QStringList() << "系統信息" << "數值");
    } else
    {
     QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
     item->setText(0, "Failed to execute systeminfo command.");
    }
}

運行後當用戶點擊輸出系統信息按鈕時,因systeminfo運行時間較長所以需要等待一段時間,輸出效果如下圖所示;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章