Friday, April 10, 2015

Отладочный вывод в консоль для GUI приложений

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

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

Более красивый способ - это лог, который пишет всю информацию в файл. Но такой вариант не всегда удобен. Часто нужно оперативно наблюдать за тем, что произошло некоторое событие. Постоянно просматривать лог может оказаться непрактично.

Для меня удачным решением оказалось написать консольное приложение, которое запускает GUI приложение, перехватывает его вывод в stdout и stderr, и выводит в свою консоль. При использовании Qt5, реализация такого приложения оказывается элементарной:

int main(int argc, char *argv[])
{
    if (!isArgsValid(argc, argv))
        return -1;

    QString appName = getAppName(argc, argv);
    QStringList appArgs = getAppArgs(argc, argv);
    bool printStdout = isPrintStdout(argc, argv);
    bool printStderr = isPrintStderr(argc, argv);

    QTextStream out(stdout);
    printInfo(&out, appName, appArgs, printStdout, printStderr);

    QCoreApplication a(argc, argv);
    QTimer::singleShot(0, [&out, 
                           appName, 
                           appArgs, 
                           printStdout, 
                           printStderr] ()
    {
        QProcess process;

        if (printStdout)
            QObject::connect(&process, 
                             &QProcess::readyReadStandardOutput, 
                             [&out, &process] () {
                out << process.readAllStandardOutput();
                out.flush();
            });
        if (printStderr)
            QObject::connect(&process, 
                             &QProcess::readyReadStandardError, 
                             [&out, &process] () {
                out << process.readAllStandardError();
                out.flush();
            });

        process.start(appName, appArgs);
        process.waitForStarted(-1);

        if (process.error() != QProcess::UnknownError)
        {
            out << "Error: " << process.errorString() << endl;
            QCoreApplication::exit(-2);
            return;
        }

        process.waitForFinished(-1);

        if (process.error() != QProcess::UnknownError)
        {
            out << "Error: " << process.errorString() << endl;
            QCoreApplication::exit(-3);
            return;
        }
        else
        {
            out << "Exit code: " << process.exitCode() << endl;
            QCoreApplication::exit(0);
            return;
        }
    });

    return a.exec();
}
Собранный вариант для Windows можно найти на github

No comments:

Post a Comment