目 录CONTENT

文章目录
QT

Windows平台Qt设置qInstallMessageHandler日志无法显示

DevWiki
2024-09-30 / 0 评论 / 0 点赞 / 14 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

0. 问题

在学习Qt 开发时,为了方便输出日志以查看问题, Google了优化方法,即:

QApplication a(argc, argv);
qInstallMessageHandler(myMessageOutput);

使用 qInstallMessageHandler函数添加自定义的日志处理, 基本网上搜到的代码如下:

void LogManager::CustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toLocal8Bit();
    switch (type) {
        case QtDebugMsg:
            fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtInfoMsg:
            fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtWarningMsg:
            fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtCriticalMsg:
            fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtFatalMsg:
            fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            abort();
    }
}

然后在 main.cpp中测试:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qInstallMessageHandler(LogManager::CustomMessageHandler);

    qDebug("Debug Message");
    qInfo("Info Message");
    qWarning("Warning Message");
    qCritical("Critical Message");
    qFatal("Fata Message");

    MainWindow w;
    w.show();
    return a.exec();
}

点击debug 运行,打开 应用程序输出, 然后你会惊奇的发现:

没有任何日志!!!

没有任何日志!!!

没有任何日志!!!

1. 分析

首先对比测试不设置 qInstallMessageHandler 是否能正常显示, 于是修改代码如下:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // qInstallMessageHandler(LogManager::CustomMessageHandler);

    qDebug("Debug Message");
    qInfo("Info Message");
    qWarning("Warning Message");
    qCritical("Critical Message");
    // qFatal("Fata Message");

    MainWindow w;
    w.show();
    return a.exec();
}

运行,查看"应用程序输出" :

image-20240927173712019

上图说明能正常输出日志.那么问题就出在 qInstallMessageHandler的函数中。

2. 解决

经过Google搜索:

image-20240927174003352

中文的结果几乎全是如何设置自定义日志输出的, 也有的说把 stderr 换成 stdout, 根据建议修改,运行,然后不出意外的出意外了, 还是不显示!

随机改为英文搜索:

image-20240927174059614

还是英文比较好一些, 第一个就是类似的问题,在 Qt的官方论坛中有人同样有此问题

qInstallMessageHandler not showing anything when in debug mode | Qt Forum
https://forum.qt.io/topic/136623/qinstallmessagehandler-not-showing-anything-when-in-debug-mode

最佳答案是:

Hi, I also use qInstallMessageHandler and I remember also having problems with debug output: inside Qt there is a check for recursive calls to a custom message handler (in case there's a qDebug() call inside your message handler for example) so I ended up calling the Win32 OutputDebugString() directly in my message handler, like this:

    ::OutputDebugStringA(qUtf8Printable(msg + "\n"));

In Linux and on the Mac fprintf() and fflush() work fine, it's just Windows that needs this workaround. Maybe it can solve your problem too...

翻译过来就是在Windows平台有bug, 使用fprintf + fflush不输出, 建议使用 ::OutputDebugStringA(qUtf8Printable(msg + "\n"));, 于是改造函数为:

#ifdef WIN32
#include "windows.h"
#endif

#include "LogManager.h"

void LogManager::CustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QByteArray localMsg = msg.toUtf8();
#ifdef WIN32

    QString outputMsg;
    switch (type) {
    case QtDebugMsg:
        outputMsg = QString("Debug: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
        break;
    case QtInfoMsg:
        outputMsg = QString("Info: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
        break;
    case QtWarningMsg:
        outputMsg = QString("Warning: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
        break;
    case QtCriticalMsg:
        outputMsg = QString("Critical: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
        break;
    case QtFatalMsg:
        outputMsg = QString("Fatal: %1 (%2:%3, %4)").arg(localMsg.constData()).arg(context.file).arg(context.line).arg(context.function);
        abort();
    }
    // 使用 OutputDebugStringA 输出消息
    ::OutputDebugStringA(qUtf8Printable(outputMsg + "\n"));
#else
    switch (type) {
        case QtDebugMsg:
            fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtInfoMsg:
            fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtWarningMsg:
            fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtCriticalMsg:
            fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            break;
        case QtFatalMsg:
            fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
            abort();
    }
#endif
}

运行效果如下:

image-20240927174815675

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论