Same application executed as console app or QML GUI
-
Hello,
I am looking for a way to make my app executable either as a terminal application or as a QML GUI app (depends on the user preferences).
My problem is that with my current main.cpp (code is below) when I try to execute the exe as a GUI it also opens the terminal/Windows console.
I have checked for a solution and I found that I should add the following in CMakeLists:if (WIN32) set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE true) else () set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE false) endif ()
In that way the terminal is not opened together with the GUI, but there is another problem that here when I start the app from the terminal with options the output is not printed in the terminal but in a popup dialog box.
main.cpp
int main(int argc, char *argv[]) { bool hasUi = false; if (argc > 1) { hasUi = false; } else { hasUi = true; } if (hasUi) { QGuiApplication guiApp(argc, argv); QQmlApplicationEngine engine; GuiConext guiContext; auto rootContext = engine.rootContext(); rootContext->setContextProperty("Gui", &guiContext); // This adds the QML library that is used for the GUI. engine.addImportPath(QString("qrc:/")); MaterialPlugin materialPlugin; materialPlugin.registerTypes("Material"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return guiApp.exec(); } else { // The application runs as terminal app. QCoreApplication coreApp(argc, argv); int status = 0; //The following is because there is a need for EventLoop to be executed in the console application. QTimer::singleShot(0, [&]() { { TerminalRunner runner(&coreApp); if (!runner.setUpPtcManager()) { status = 1; coreApp.exit(status); return; } runner.uploadConfiguration(); } coreApp.exit(status); }); return coreApp.exec(); } }
-
Hello,
I am looking for a way to make my app executable either as a terminal application or as a QML GUI app (depends on the user preferences).
My problem is that with my current main.cpp (code is below) when I try to execute the exe as a GUI it also opens the terminal/Windows console.
I have checked for a solution and I found that I should add the following in CMakeLists:if (WIN32) set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE true) else () set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE false) endif ()
In that way the terminal is not opened together with the GUI, but there is another problem that here when I start the app from the terminal with options the output is not printed in the terminal but in a popup dialog box.
main.cpp
int main(int argc, char *argv[]) { bool hasUi = false; if (argc > 1) { hasUi = false; } else { hasUi = true; } if (hasUi) { QGuiApplication guiApp(argc, argv); QQmlApplicationEngine engine; GuiConext guiContext; auto rootContext = engine.rootContext(); rootContext->setContextProperty("Gui", &guiContext); // This adds the QML library that is used for the GUI. engine.addImportPath(QString("qrc:/")); MaterialPlugin materialPlugin; materialPlugin.registerTypes("Material"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return guiApp.exec(); } else { // The application runs as terminal app. QCoreApplication coreApp(argc, argv); int status = 0; //The following is because there is a need for EventLoop to be executed in the console application. QTimer::singleShot(0, [&]() { { TerminalRunner runner(&coreApp); if (!runner.setUpPtcManager()) { status = 1; coreApp.exit(status); return; } runner.uploadConfiguration(); } coreApp.exit(status); }); return coreApp.exec(); } }
@Rufledore said in Same application executed as console app or QML GUI:
//The following is because there is a need for EventLoop to be executed in the console application.
Why? return coreApp.exec(); starts the event loop.
"the output is not printed in the terminal but in a popup dialog box." - what output and how do you output it?
-
Why? return coreApp.exec(); starts the event loop.
coreApp.exec() is called in the end of the main function but I need some things to be executed after the event loop is started and that's my way.
The console output is printed with std::cout.
Please stick to the topic. Do you have any idea how to help me? -
Why? return coreApp.exec(); starts the event loop.
coreApp.exec() is called in the end of the main function but I need some things to be executed after the event loop is started and that's my way.
The console output is printed with std::cout.
Please stick to the topic. Do you have any idea how to help me?@Rufledore said in Same application executed as console app or QML GUI:
Please stick to the topic. Do you have any idea how to help me?
He is trying to help you.
-
Why? return coreApp.exec(); starts the event loop.
coreApp.exec() is called in the end of the main function but I need some things to be executed after the event loop is started and that's my way.
The console output is printed with std::cout.
Please stick to the topic. Do you have any idea how to help me?@Rufledore said in Same application executed as console app or QML GUI:
Please stick to the topic
Where was I off-topic?
Also, pointing to issues not related to original question isn't a bad thing in my opinion. I always appreciate if others point out issues in my code even if not related to original question.OK, what you are doing with the timer is fine.
I don't see how std::cout output would end-up in a dialog box, unless you implement it by yourself.
Without seeing the code I can't tell more. -
Why? return coreApp.exec(); starts the event loop.
coreApp.exec() is called in the end of the main function but I need some things to be executed after the event loop is started and that's my way.
The console output is printed with std::cout.
Please stick to the topic. Do you have any idea how to help me?@Rufledore said in Same application executed as console app or QML GUI:
Please stick to the topic. Do you have any idea how to help me?
Please take time to understand the question asked.
In your code there is a strange comment:The following is because there is a need for EventLoop to be executed in the console application.
But, as @jsulm already has written, calling
coreApp.exec()
will already start an eventloop.You code don't made sense:
Simple change you code to something like this:// The application runs as terminal app. QCoreApplication coreApp(argc, argv); int status = 0; TerminalRunner runner(&coreApp); // stop application when runner is done QObject::connect(&runner, &TerminalRunner::done, &coreApp, &QCoreApplication::quit); // call TerminalRunner start slot asap QTimer::singleShot(0, &runner, &TerminalRunner::start); // start event loop and wait until finished return coreApp.exec();
Note: I suppose here that your
TerminalRunner
class has a signal calleddone()
which is emitted when all is done and a slot calledstart()
which has to be called to start processing. -
@Rufledore said in Same application executed as console app or QML GUI:
Please stick to the topic
Where was I off-topic?
Also, pointing to issues not related to original question isn't a bad thing in my opinion. I always appreciate if others point out issues in my code even if not related to original question.OK, what you are doing with the timer is fine.
I don't see how std::cout output would end-up in a dialog box, unless you implement it by yourself.
Without seeing the code I can't tell more.@jsulm said in Same application executed as console app or QML GUI:
I don't see how std::cout output would end-up in a dialog box, unless you implement it by yourself.
Without seeing the code I can't tell more.Like that:
With WIN32_EXECUTABLE false it is like that:
-
Hello,
I am looking for a way to make my app executable either as a terminal application or as a QML GUI app (depends on the user preferences).
My problem is that with my current main.cpp (code is below) when I try to execute the exe as a GUI it also opens the terminal/Windows console.
I have checked for a solution and I found that I should add the following in CMakeLists:if (WIN32) set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE true) else () set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE false) endif ()
In that way the terminal is not opened together with the GUI, but there is another problem that here when I start the app from the terminal with options the output is not printed in the terminal but in a popup dialog box.
main.cpp
int main(int argc, char *argv[]) { bool hasUi = false; if (argc > 1) { hasUi = false; } else { hasUi = true; } if (hasUi) { QGuiApplication guiApp(argc, argv); QQmlApplicationEngine engine; GuiConext guiContext; auto rootContext = engine.rootContext(); rootContext->setContextProperty("Gui", &guiContext); // This adds the QML library that is used for the GUI. engine.addImportPath(QString("qrc:/")); MaterialPlugin materialPlugin; materialPlugin.registerTypes("Material"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return guiApp.exec(); } else { // The application runs as terminal app. QCoreApplication coreApp(argc, argv); int status = 0; //The following is because there is a need for EventLoop to be executed in the console application. QTimer::singleShot(0, [&]() { { TerminalRunner runner(&coreApp); if (!runner.setUpPtcManager()) { status = 1; coreApp.exit(status); return; } runner.uploadConfiguration(); } coreApp.exit(status); }); return coreApp.exec(); } }
@Rufledore said in Same application executed as console app or QML GUI:
set_property(TARGET Ptc05Manager PROPERTY WIN32_EXECUTABLE true)
This is to force the creation of a Windows application without console.
So what did you expect what happen when using this? -
@KroMignon said in Same application executed as console app or QML GUI:
So what did you expect what happen when using this?
I would like to have an app that executes as a console application when it is started with parameters and as a GUI when it is started without parameters e.g. the icon or in console. Everything works fine usually except the fact that when I start the GUI from the icon a console is opened too and I don't wont that to happen. The solution that I found was to set WIN32_EXECUTABLE to true, but that stops the console app behavior. So, I would like to find a working solution.
-
@KroMignon said in Same application executed as console app or QML GUI:
So what did you expect what happen when using this?
I would like to have an app that executes as a console application when it is started with parameters and as a GUI when it is started without parameters e.g. the icon or in console. Everything works fine usually except the fact that when I start the GUI from the icon a console is opened too and I don't wont that to happen. The solution that I found was to set WIN32_EXECUTABLE to true, but that stops the console app behavior. So, I would like to find a working solution.
@Rufledore said in Same application executed as console app or QML GUI:
The solution that I found was to set WIN32_EXECUTABLE to true, but that stops the console app behavior. So, I would like to find a working solution.
This is not the solution, is will only allow/disable the Windows application to create a Console.
If there is not console, there will be a Window which will be created to show the stdout message.You can hide console on application startup with something like this:
HWND hWnd = GetConsoleWindow(); ShowWindow( hWnd, SW_HIDE );
Of course, this only works for Windows
-
Windows does not support the same application to be both a console and a GUI app. The major problem is that a GUI application should not have an attached console and a console application should use an existing console when started from the command line instead of opening a new one. This is not possible on Windows.
Here is the next best thing you can do on Windows (I have read that Microsoft's own
devenv
command does it this way): Compile your application both as .exe (GUI application) and .com (console/command line application). This can be done from the same source code if you use a few #ifdef's. If you have amyapp.exe
and amyapp.com
and typemyapp
(without the file extension) on the command line, Windows will do the right thing. In our own application we provided an option to specify you want the GUI. If the console app was started with the GUI option it will just use QProcess to launch the GUI version and exit.Here is a short snippet with the most important information how we do it:
// Windows header #include <windows.h> #include <consoleapi.h> #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) // false warning of unused parameter 'a' #endif void startGui(QApplication &a) { QString currentDir = QDir::currentPath(); QStringList arguments = a.arguments(); arguments.removeFirst(); QDir::setCurrent(QCoreApplication::applicationDirPath()); QProcess::startDetached(QFileInfo(QCoreApplication::applicationFilePath()).completeBaseName() + ".exe", arguments, currentDir); } #ifdef _MSC_VER #pragma warning(pop) #endif void openConsole() { AllocConsole(); std::freopen( "CON", "w", stdout ); std::freopen( "CON", "w", stderr ); std::freopen( "CON", "r", stdin ); } int main(int argc, char *argv[]) { QApplication a(argc, argv); CommandLineArgs args = parseCommandLine(a); #ifdef CONSOLE_APP if(args.gui) { startGui(a); return 0; } #else if(args.gui) { QString filename; Dialog w(filename); w.show(); return a.exec(); } openConsole(); #endif return processWithArgs(args); }
The difference is that we don't have an event loop when run as a pure console application.