IT Notes

QProcess: Примеры использования

Введение

QProcess - одновременно мощный и удобный модуль библиотеки Qt для запуска и управления процессами. Нельзя забывать, что он еще и весьма опасен. Однако здесь мы не будем затрагивать вопросы информационной безопасности, а лишь ограничимся базовыми приемами использования QProcess.

Запуск другого приложения

Допустим, вы хотите, чтобы ваше приложение могло вызывать другую программу в виде независимого процесса. Сделать это очень легко:

Заказать кровлю высокого качества в Симферополе от производителя. Большой выбор металлочерепицы, профнастила, гибкой черепицы. Сотовый поликарбонат. Доборные элементы. Водосточная система. Жизнь по вызову смотри здесь. Адвокат по наркотикам читать дальше.

void runTest() {
    static const QString PROGRAM_NAME = "notepad"; // Для примера - Блокнот
    QProcess::startDetached( PROGRAM_NAME );
}

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

Обратите внимание, что startDetached() - статическая функция-член класса QProcess. При этом она может принимать еще несколько параметров: список аргументов в виде QStringList; рабочую директорию; и указатель на int, в котором возвращает идентификатор нового процесса.

Графический интерфейс для консольного приложения

Это решение является довольно распространенным в мире Linux, где большинство утилит изначально выходят в форме консольных приложений. Однако не всем пользователям это нравится. По этой причине и появляются надстройки с графическим интерфейсом, которые являются посредниками между пользователями и исходной консольной утилитой. Например, QtCreator и многие другие IDE для интеграции компиляторов и систем контроля версий используют именно этот прием.

Получение информации от другого приложения через стандартный поток вывода

В большинстве случаев вам достаточно передать нужные аргументы на вход приложению и дождаться от него ответа:

void readTest() {
    QProcess process;
    process.start( "lsusb", QStringList() << "-t" );
    if( !process.waitForStarted() || !process.waitForFinished() ) {
        return;
    }

    qDebug() << process.readAllStandardError();
    qDebug() << process.readAllStandardOutput();
}

В приведенном примере мы запускаем lsusb -t (утилита для Linux). Поскольку результат выводится мгновенно, мы ждем завершения процесса с помощью waitForFinished() и выводим то, что приложение отправило в стандартные потоки вывода stderr и stdout. Если же приложение выводит результаты не сразу, а постепенно в течение нескольких секунд или минут, то лучше воспользоваться сигналами readyReadStandardError() и readyReadStandardOutput(), организовав работу в асинхронном режиме.

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

Обмен сообщениями с процессом

Вы можете не только читать то, что приложение пишет в стандартные потоки вывода, но и сами писать в поток ввода процесса:

void writeReadTest() {
    QProcess process;
    process.start( "cat" );
    if( !process.waitForStarted() ) {
        return;
    }

    process.write( "Hello, world!" );
    process.closeWriteChannel();

    if( !process.waitForFinished() ) {
        return;
    }

    qDebug() << process.readAllStandardError();
    qDebug() << process.readAllStandardOutput();
}

Принцип работы этого примера очень похож на то, что мы видели раньше. Однако теперь внешнее приложение реагирует на то, что мы подаем ему в поток ввода stdin. Все, что мы отправляем в cat, вернется нам обратно в результате вызова readAllStandardOutput(). Обратите внимание, что завершение процесса происходит после вызова closeWriteChannel() (равносильно нажатию Ctrl+D).

Заключение

Мы рассмотрели два базовых способа использования QProcess. Возможно, в вашей работе они никогда и не понадобятся, но знать о них не будет лишним.

Похожие публикации

Комментарии

Дообрый день. Спасибо за очень полезные обучающие статьи! Расскажите, пожалуйста подробнее (или скажите где можно об этом почитать):

Цитата: "Нельзя забывать, что он еще и весьма опасен. Однако здесь мы не будем затрагивать вопросы информационной безопасности, а лишь ограничимся базовыми приемами…".

Мне очень интересно было бы разобраться в вопросах безопасности потоков.

Здравствуйте. Спасибо за комментарий.

Если Вас интересуют вопросы информационной безопасности, то можете обратиться к книгам 24 смертных греха компьютерной безопасности. Библиотека программиста и Как написать безопасный код на C++ Java Perl PHP ASP.NET.

Если же речь идет именно о работе с потоками в целом, то могу посоветовать книгу Параллельное программирование на С++ в действии. Книга посвящена параллельному программированию на C++11, но очень полезна и с теоретической точки зрения, поскольку в ней рассматриваются все основные вопросы о работе с потоками.

А есть какая-нибудь возможность узнать координаты и размеры запущенного приложения? Лучше, если в linux

Anonymous:

А есть какая-нибудь возможность узнать координаты и размеры запущенного приложения? Лучше, если в linux

Т.е. требуется найти путь к файлу на диске и размер, занимаемый приложением в RAM, по имени процесса?

Mikhail:

Anonymous:

А есть какая-нибудь возможность узнать координаты и размеры запущенного приложения? Лучше, если в linux

Т.е. требуется найти путь к файлу на диске и размер, занимаемый приложением в RAM, по имени процесса?

Нет. Некорректно написал. Имеется в виду визуальное представление (координаты окна и его визуальный размер). В windows можно было использовать функцию FindWindow, а затем уже по полученному дескриптору запросить все остальное. А вот в linux не могу найти, как сделать подобное. Понятно, что это будет зависеть от оконного менеджера.

Это все необходимо для создания бота. Управление мышью уже сделал а вот с координатами пока проблема…

Anonymous:

Нет. Некорректно написал. Имеется в виду визуальное представление (координаты окна и его визуальный размер). В windows можно было использовать функцию FindWindow, а затем уже по полученному дескриптору запросить все остальное. А вот в linux не могу найти, как сделать подобное. Понятно, что это будет зависеть от оконного менеджера.

Да, я понял. Этого можно добиться с помощью XLib. В ближайшие дни постараюсь подготовить небольшую статью на эту тему.