wake-up-neo.com

Konsolenausgabe in einer Qt-GUI-App?

Ich habe eine Qt-GUI-Anwendung, die unter Windows ausgeführt wird und die die Übergabe von Befehlszeilenoptionen ermöglicht. Unter bestimmten Umständen möchte ich eine Nachricht an die Konsole ausgeben und dann beenden.

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  if (someCommandLineParam)
  {
    std::cout << "Hello, world!";
    return 0;
  }

  MainWindow w;
  w.show();

  return a.exec();
}

Die Konsolenmeldungen werden jedoch nicht angezeigt, wenn ich die App von einer Eingabeaufforderung aus ausführen. Weiß jemand, wie ich das zum Laufen bringen kann?

45
Rob

Windows unterstützt Dual-Modus-Anwendungen nicht wirklich. 

Um die Konsolenausgabe anzuzeigen, müssen Sie eine Konsolenanwendung erstellen

CONFIG += console

Wenn Sie jedoch auf das Programm doppelklicken, um die GUI-Modusversion zu starten, wird ein Konsolenfenster angezeigt, das wahrscheinlich nicht Ihren Vorstellungen entspricht. Um zu verhindern, dass das Konsolenfenster angezeigt wird, müssen Sie eine Anwendung im GUI-Modus erstellen. In diesem Fall erhalten Sie keine Ausgabe in der Konsole.

Eine Idee könnte sein, eine zweite kleine Anwendung zu erstellen, die eine Konsolenanwendung ist und die Ausgabe bereitstellt. Dies kann den zweiten aufrufen, um die Arbeit zu erledigen. 

Oder Sie können die gesamte Funktionalität in eine DLL einfügen und dann zwei Versionen der EXE-Datei erstellen, die sehr einfache Hauptfunktionen haben, die in der DLL aufgerufen werden. Eine ist für die GUI und eine für die Konsole.

43
David Dibben

Hinzufügen:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
}
#endif

an der Spitze von main(). Dadurch wird die Ausgabe an die Konsole nur aktiviert, wenn das Programm in einer Konsole gestartet wird. In anderen Situationen wird kein Konsolenfenster angezeigt. Wenn Sie ein Konsolenfenster erstellen möchten, um Meldungen anzuzeigen, wenn Sie die App außerhalb einer Konsole ausführen, können Sie die Bedingung wie folgt ändern:

if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole())
11
patstew
void Console()
{
    AllocConsole();
    FILE *pFileCon = NULL;
    pFileCon = freopen("CONOUT$", "w", stdout);

    COORD coordInfo;
    coordInfo.X = 130;
    coordInfo.Y = 9000;

    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coordInfo);
    SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),ENABLE_QUICK_EDIT_MODE| ENABLE_EXTENDED_FLAGS);
}

int main(int argc, char *argv[])
{
    Console();
    std::cout<<"[email protected]@";
    qDebug()<<"start!";

Sie können std :: cout nicht verwenden, wie andere gesagt haben, mein Weg ist perfekt, auch wenn Code nicht "qdebug" enthalten kann!

5
Gank

Bei Verwendung von QT += gui gibt es keine Möglichkeit, eine Nachricht an die Konsole auszugeben.

fprintf(stderr, ...) kann auch keine Ausgabe drucken.

Verwenden Sie stattdessen QMessageBox, um die Nachricht anzuzeigen.

5
raidsan

Sie können eine Nachricht ausgeben, wenn Sie QT += gui und CONFIG += console verwenden.

Sie brauchen printf("foo bar"), aber cout << "foo bar" funktioniert nicht

4
Seb

Ich habe diesen Header für meine Projekte verwendet. Ich hoffe es hilft.

#ifndef __DEBUG__H
#define __DEBUG__H

#include <QtGui>    

static void myMessageOutput(bool debug, QtMsgType type, const QString & msg) {

    if (!debug) return;

    QDateTime dateTime = QDateTime::currentDateTime();
    QString dateString = dateTime.toString("yyyy.MM.dd hh:mm:ss:zzz");

    switch (type) {

        case QtDebugMsg:
            fprintf(stderr, "Debug: %s\n", msg.toAscii().data());
            break;
        case QtWarningMsg:
            fprintf(stderr, "Warning: %s\n", msg.toAscii().data());
            break;
        case QtCriticalMsg:
            fprintf(stderr, "Critical: %s\n", msg.toAscii().data());
            break;
        case QtFatalMsg:
            fprintf(stderr, "Fatal: %s\n", msg.toAscii().data());
            abort();
    }
}

#endif

PS: Sie können dateString zur Ausgabe hinzufügen, wenn Sie dies in Zukunft wünschen.

2
mosg

Etwas, das Sie zumindest für Windows untersuchen möchten, ist die Funktion AllocConsole () in der Windows-API. Es ruft GetStdHandle einige Male auf, um stdout, stderr usw. umzuleiten. (Ein kurzer Test zeigt, dass dies nicht ganz das tut, was wir wollen. Sie erhalten ein Konsolenfenster neben den anderen Qt-Elementen, aber Sie können es nicht Da das Konsolenfenster offen ist, gibt es eine Möglichkeit, auf es zuzugreifen, einen Griff zu bekommen oder irgendwie darauf zuzugreifen und es zu manipulieren. Hier ist die MSDN-Dokumentation für alle, die daran interessiert sind, dies herauszufinden:

AllocConsole (): http://msdn.Microsoft.com/en-us/library/windows/desktop/ms681944%28v=vs.85%29.aspx

GetStdHandle (...): http://msdn.Microsoft.com/de-de/library/windows/desktop/ms683231%28v=vs.85%29.aspx

(Ich würde dies als Kommentar hinzufügen, aber die Regeln hindern mich daran ...)

2
Josh

In Ihrem .pro hinzufügen

CONFIG          += console
0

So viele Antworten auf dieses Thema. 0.0

Also habe ich es mit Qt5.x von Win7 auf Win10 versucht. Ich habe einige Stunden gebraucht , um eine gute funktionierende Lösung zu finden, die irgendwo in der Kette keine Probleme verursacht:

#include "mainwindow.h"

#include <QApplication>

#include <windows.h>
#include <stdio.h>
#include <iostream>

//
// Add to project file:
// CONFIG += console
//

int main( int argc, char *argv[] )
{
    if( argc < 2 )
    {
    #if defined( Q_OS_WIN )
        ::ShowWindow( ::GetConsoleWindow(), SW_HIDE ); //hide console window
    #endif
        QApplication a( argc, argv );
        MainWindow *w = new MainWindow;
        w->show();
        int e = a.exec();
        delete w; //needed to execute deconstructor
        exit( e ); //needed to exit the hidden console
        return e;
    }
    else
    {
        QCoreApplication a( argc, argv );
        std::string g;
        std::cout << "Enter name: ";
        std::cin >> g;
        std::cout << "Name is: " << g << std::endl;
        exit( 0 );
        return a.exec();
    }
}


Ich habe es auch ohne die "CONFIG + = Konsole" versucht, aber dann musst du die Streams umleiten und die Konsole selbst erstellen:

#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()){
    freopen("CONOUT$", "w", stdout);
    freopen("CONOUT$", "w", stderr);
    freopen("CONIN$", "r", stdin);
}
#endif

[~ # ~] aber [~ # ~] dies funktioniert nur, wenn Sie es über einen Debugger starten, ansonsten werden alle Eingaben auch zum System geleitet. Bedeutet, wenn Sie einen Namen über std :: cin eingeben, versucht das System, den Namen als Befehl auszuführen. (sehr eigenartig)

Zwei weitere Warnungen zu diesem Versuch wäre, dass Sie :: FreeConsole () nicht verwenden können, es wird nicht geschlossen und wenn Sie es über eine Konsole starten, wird die App nicht geschlossen.



Zuletzt gibt es ein Qt-Hilfeabschnitt in QApplication zu diesem Thema. Ich habe das Beispiel dort mit einer Anwendung ausprobiert und es funktioniert nicht für die GUI , es steckt irgendwo in einer Endlosschleife und die GUI wird nicht funktionieren gerendert oder es stürzt einfach ab:

QCoreApplication* createApplication(int &argc, char *argv[])
{
    for (int i = 1; i < argc; ++i)
        if (!qstrcmp(argv[i], "-no-gui"))
            return new QCoreApplication(argc, argv);
    return new QApplication(argc, argv);
}

int main(int argc, char* argv[])
{
    QScopedPointer<QCoreApplication> app(createApplication(argc, argv));

    if (qobject_cast<QApplication *>(app.data())) {
       // start GUI version...
    } else {
       // start non-GUI version...
    }

    return app->exec();
}


Wenn Sie also Windows verwenden und Qt einfach die Konsolenoption verwenden, blenden Sie die Konsole aus, wenn Sie die GUI benötigen, und schließen Sie sie über das Beenden.

0
Pixtar

Zunächst einmal, warum müssen Sie die Ausgabe in einem Release-Modus auf der Konsole ausgeben? Niemand wird denken, dort nachzusehen, wenn es eine gui gibt ...

Zweitens ist qDebug fantastisch :)

Drittens können Sie versuchen, console zu Ihrer CONFIG Ihres .pro hinzuzufügen, es könnte funktionieren.

0
rubenvb

Ich spielte auch damit und entdeckte, dass das Umleiten der Ausgabe funktioniert hat, aber ich habe nie eine Ausgabe im Konsolenfenster gesehen, das für jede Windows-Anwendung vorhanden ist. Dies ist meine Lösung, bis ich einen Ersatz für ShowWindow und GetConsoleWindow finde.

Führen Sie dies über eine Eingabeaufforderung ohne Parameter aus - rufen Sie das Fenster auf. Führen Sie den Befehl Eingabeaufforderung mit Parametern aus (z. B. cmd aaa bbb ccc) - Sie erhalten die Textausgabe im Eingabeaufforderungsfenster - genau wie Sie es von Windows-Konsolenanwendungen erwarten.

Bitte entschuldigen Sie das lahme Beispiel - es stellt ungefähr 30 Minuten des Bastelns dar.

#include "mainwindow.h"
#include <QTextStream>
#include <QCoreApplication>
#include <QApplication>
#include <QWidget>
#include <windows.h>

QT_USE_NAMESPACE

int main(int argc, char *argv[])
{
    if (argc > 1)   {
        // User has specified command-line arguments
        QCoreApplication a(argc, argv);
        QTextStream  out(stdout);
        int     i;

        ShowWindow (GetConsoleWindow(),SW_NORMAL);
        for (i=1; i<argc; i++)
             out << i << ':' << argv [i] << endl;
        out << endl << "Hello, World" << endl;
        out << "Application Directory Path:" << a.applicationDirPath() << endl;
        out << "Application File Path:" << a.applicationFilePath() << endl;
        MessageBox (0,(LPCWSTR)"Continue?",(LPCWSTR)"Silly Question",MB_YESNO);
        return 0;
    } else  {
        QApplication a(argc, argv);
        MainWindow w;

        w.setWindowTitle("Simple example");
        w.show();
        return a.exec();
    }
}
0
David Athersych

Es kann ein Versehen anderer Antworten gewesen sein oder es ist vielleicht eine Anforderung des Benutzers, die Konsolenausgabe tatsächlich zu benötigen, aber die naheliegendste Antwort ist für mich, ein sekundäres Fenster zu erstellen, das angezeigt oder ausgeblendet werden kann (mit einem Kontrollkästchen oder einer Schaltfläche). Zeigt alle Nachrichten an, indem Sie Textzeilen an ein Textfeld-Widget anhängen und als Konsole verwenden?

Die Vorteile einer solchen Lösung sind:

  • Eine einfache Lösung (wenn nur alles angezeigt wird, ist ein einfaches Protokoll).
  • Die Möglichkeit, das Widget 'Konsole' an das Hauptfenster der Anwendung anzudocken. (In Qt jedenfalls).
  • Die Möglichkeit, viele Konsolen zu erstellen (wenn mehr als ein Thread usw.).
  • Eine ziemlich einfache Änderung von der Ausgabe der lokalen Konsole zum Senden eines Protokolls über das Netzwerk an einen Client.

Ich hoffe, dies gibt Ihnen Anlass zum Nachdenken, auch wenn ich noch nicht dazu qualifiziert bin, zu postulieren, wie Sie dies tun sollten. Ich kann mir vorstellen, dass dies für jeden von uns etwas Erreichbares mit ein wenig Recherche/Lesen ist!

0
Tech1337

Stellen Sie sicher, dass sich Qt5Core.dll im selben Verzeichnis befindet wie Ihre Anwendung.

Ich hatte in Qt5 mit einer Konsolenanwendung ein ähnliches Problem: Wenn ich die Anwendung von Qt Creator aus starte, ist der Ausgabetext sichtbar. Wenn ich cmd.exe öffne und dort dieselbe Anwendung starte, ist keine Ausgabe sichtbar .Sehr eigenartig!

Ich löste es, indem ich Qt5Core.dll in das Verzeichnis mit der ausführbaren Anwendung kopierte. 

Hier ist meine kleine Konsolenanwendung:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    int x=343;
    QString str("Hello World");
    qDebug()<< str << x<<"lalalaa";

    QTextStream out(stdout);
    out << "aldfjals alsdfajs...";
}
0
user5157912