QProcess – процессы в Qt


В том случае, когда пользователь или программа производят запуск другой программы, операционная система всегда создает новый процесс. Процесс — это экземпляр программы, загруженной в память компьютера для выполнения.

По своей сути, процессы — это независимые друг от друга программы, обладающие своими собственными данными. Коротко процесс можно охарактеризовать как общность кода, данных и ресурсов, необходимых для его работы. Под ресурсами подразумеваются объекты, запрашиваемые и используемые процессами в период их работы. Любая прикладная программа, запущенная на вашем компьютере, представляет собой не что иное, как процесс.

Создание процесса может оказаться полезным для использования функциональных возможностей программ, не имеющих графического интерфейса и работающих с командной строкой. Другое полезное свойство — довольно простой запуск других программ из текущей программы. Особенно он полезен для запуска команд или программ, действия которых непродолжительны по времени.

Процессы можно создавать с помощью класса QProcess, который определен в заголовочном файле QProcess. Благодаря тому, что этот класс унаследован от класса QIODevice, объекты этого класса в состоянии считывать информацию, выводимую запущенными процессами, и даже подтверждать их запросы на ввод информации. Этот класс содержит методы для манипулирования системными переменными процесса. Работа с объектами класса QProcess производится в асинхронном режиме, что позволяет сохранять работоспособность графического интерфейса программы в моменты, когда запущенные процессы находятся в работе. При появлении данных или других событий объекты класса QProcess высылают сигналы. Например, при возникновении ошибок объект процесса вышлет сигнал error() с кодом этой ошибки.

Для создания процесса его нужно запустить. Запуск процесса выполняется методом start(), в который необходимо передать имя команды и список ее аргументов, либо все вместе — команду и аргументы одной строкой. Как только процесс будет запущен, высылается сигнал started(), а после завершения его работы высылается сигнал finished(). Вместе с сигналом finished() высылается код и статус завершения работы процесса. Для получения статуса выхода можно вызвать метод exitStatis(), который возвращает только два значения: NormaiExit (нормальное завершение) и CrashExit (аварийное завершение).

{рисунок}

Для чтения данных запущенного процесса класс QProcess предоставляет два разделенных канала: канал стандартного вывода (stdout) и канал ошибок (stderr). Эти каналы можно переключать с помощью метода setReadChannel(). Если процесс готов предоставить данные по текущему установленному каналу, то высылается сигнал readyRead(). Также высылаются сигналы для каждого канала в отдельности: readyReadStandardOutput() и readyReadStandardError().

Считывать и записывать данные в процесс можно с помощью методов класса QIODevice::write(), read(), readLine() и getChar() . Также для чтения можно воспользоваться методами, привязанными к конкретным каналам: readAllStandardOutput() и readAllStandardError(). Эти методы считывают данные в объекты класса QByteArray.

Приложение, изображенное на рисунке, иллюстрирует применение некоторых методов класса QProcess. В текстовом поле Command (Команда) может быть введена любая команда, соответствующая операционной системе. Если запущенная команда или программа осуществляют вывод на консоль, то отображение будет производиться в виджете многострочного тестового поля.


class Shell : public QWidget {
Q_OBJECT
private:
    QProcess*  m_process;
    QLineEdit* m_ptxtCommand;
    QTextEdit* m_ptxtDisplay;

public:
    Shell(QWidget* pwgt = 0) : QWidget(pwgt)
    {
        m_process     = new QProcess(this);
        m_ptxtDisplay = new QTextEdit;

        QLabel* plbl = new QLabel("&Command:");

        m_ptxtCommand = new QLineEdit("dir");
        plbl->setBuddy(m_ptxtCommand);

        QPushButton* pcmd = new QPushButton("&Enter");

        connect(m_process, 
                SIGNAL(readyReadStandardOutput()), 
                SLOT(slotDataOnStdout())
               );
        connect(m_ptxtCommand, 
                SIGNAL(returnPressed()), 
                SLOT(slotReturnPressed())
               );
        connect(pcmd, SIGNAL(clicked()), SLOT(slotReturnPressed()));

        //Layout setup
        QHBoxLayout* phbxLayout = new QHBoxLayout;    
        phbxLayout->addWidget(plbl);
        phbxLayout->addWidget(m_ptxtCommand);
        phbxLayout->addWidget(pcmd);

        QVBoxLayout* pvbxLayout = new QVBoxLayout;    
        pvbxLayout->addWidget(m_ptxtDisplay);
        pvbxLayout->addLayout(phbxLayout);
        setLayout(pvbxLayout);
    }

public slots:
    void slotDataOnStdout()
    {
        m_ptxtDisplay->append(m_process->readAllStandardOutput());
    }

    void slotReturnPressed()
    {
        QString strCommand = "";
#ifdef Q_WS_WIN
        strCommand = "cmd /C ";
#endif
        strCommand += m_ptxtCommand->text();
        m_process->start(strCommand);
    }
};

В конструкторе класса Shell производится создание объекта класса QProgress. Его сигнал readyReadStandardOutput() соединяется со слотом slotDataOnStdout(), в котором вызывается метод readAllstandardOutput() для считывания всего содержимого стандартного потока. После считывания эти данные добавляются, вызовом метода append(), в виджет многострочного текстового поля m_ptxtDisplay.

Слот slotReturnPressed() соединен с сигналом кнопки clicked() (указатель pcmd) и с сигналом однострочного текстового поля returnPressed() (указатель m_txtCommand). Некоторые команды ОС Windows, например — dir, не являются отдельными программами, поэтому они должны быть исполнены посредством командного интерпретатора cmd. Поэтому для ОС Windows в командную строку сначала добавляется строка "cmd /С". Во всех остальных, введенная в однострочном текстовом поле строка передается как есть, без дополнений. Для запуска процесса вызывается метод start().

Читать далее: QThread – потоки в Qt