I have created a simple service application for testing with QtService. This can be easily executed in the QtCreator using the command line arguments:
-exec: This allows me to debug the service in QtCreator
-install: This allows the service to be installed (Alternatively, I can also install the service via cmd with the sc command).
After I have installed the service, I try to start it in the Windows service management. However, the error message appears: The service "MyService" on "Local computer" could not be started. Error 1053: The service did not respond to the start or control request in time.
This error message appears immediately without trying to start the service for 30 seconds. I tried debug and release mode.
My guess is that Qt dlls must also be next to the EXE. But I don't know which.
simpleService.pro
QT -= gui
CONFIG += c++11 console
CONFIG -= app_bundle
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
myservice.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
include(qtservice/src/qtservice.pri)
HEADERS += \
myservice.h
myservice.h
#ifndef MYSERVICE_H
#define MYSERVICE_H
#include <qtservice.h>
#include <QCoreApplication>
#include <QDebug>
#include <QObject>
class MyService: public QtService<QCoreApplication>
{
public:
MyService(int argc, char **argv);
~MyService();
protected:
void start();
void pause();
void resume();
void stop();
void createApplication(int &argc, char **argv);
private:
QStringList _args;
};
#endif // MYSERVICE_H
myservice.cpp
#include "myservice.h"
MyService::MyService(int argc, char **argv) : QtService<QCoreApplication>(argc, argv, "MyService7")
{
try {
qDebug() << "CONSTRUCTOR";
setServiceDescription("This is my service. ");
setServiceFlags(QtServiceBase::CanBeSuspended); // able to resume
qDebug() << "CONSTRUCTOR 1";
} catch (...) {
qCritical() << "An unknown error occured in constructor";
}
}
MyService::~MyService()
{
qDebug() << "DECONSTRUCTOR";
}
void MyService::start()
{
qDebug() << "START";
try {
QCoreApplication *app = application(); // nessesary for windows
qDebug() << "Service started";
qDebug() << app->applicationDirPath();
} catch (...) {
qCritical() << "An unknown error occured in start";
}
}
void MyService::pause()
{
qDebug() << "PAUSE";
}
void MyService::resume()
{
qDebug() << "RESUME";
}
void MyService::stop()
{
qDebug() << "STOP";
}
void MyService::createApplication(int &argc, char **argv)
{
for (int i = 0; i < argc; i++)
{
_args.append(QString(argv[i]));
qDebug() << "Arg: " << argv[i];
}
QtService::createApplication(argc, argv);
}
main.cpp
#include "myservice.h"
#include <QCoreApplication>
int main(int argc, char *argv[])
{
MyService service(argc, argv);
return service.exec();
}
I found a solution:
In Qt 5.13.1(MinGW 7.3.0 64-bit) Compiler (In my case) change the directory to exe file. Then enter following command: windeployqt.exe .
Put the QtSolutions_service-head.dll next to exe file.
Now I can start the service.
on win10,if you want it to work as service ,you should install it in powershell in admin mode, or it would not work!
Related
Сalling a dialog resets a message handler in debian like linux
And yes, no details are required here anymore, but I have to add this text to go through the smart bot
#include <QApplication>
#include <QFileDialog>
#include <QDebug>
QtMessageHandler defaultHandler;
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
auto str = msg;
str.append(" handled");
defaultHandler(type, context, str);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug() << "test0";
defaultHandler = qInstallMessageHandler(messageHandler);
qDebug() << "test1";
QFileDialog::getSaveFileName();
qDebug() << "test2";
}
output in windows
test0
test1 handled
test2 handled
output in debian like linux
test0
test1 handled
warning: QFSFileEngine::open: No file name specified
debug: test2
I can run an external application using the following command:
system("/home/felippe/Área\\ de\\ Trabalho/Felippe/Mestrado/C_plus_plus/Codigos/build-Registration_ITK_CMAKE-Desktop_Qt_5_12_3_GCC_64bit-Default/Registration_ITK_CMAKE")
And the application runs successfully. But the system(.) command blocks the other commands until the application finishes. So I tried to implement this command in QT using the following code:
.h
#ifndef FOO_H
#define FOO_H
#include <QObject>
#include <iostream>
#include <QProcess>
class foo : public QObject
{
Q_OBJECT
public:
explicit foo(QObject *parent = nullptr);
signals:
public slots:
void process_started();
void processError(QProcess::ProcessError error);
private:
QProcess *process;
};
#endif // FOO_H
.cpp
#include "foo.h"
foo::foo(QObject *parent) : QObject(parent)
{
process = new QProcess();
bool status = QObject::connect( process, SIGNAL( started() ), this, SLOT( process_started() ) );
connect(process, &QProcess::errorOccurred, this, &foo::processError);
QString file = "/home/felippe/Área de Trabalho/Felippe/Mestrado/C_plus_plus/Codigos/build-Registration_ITK_CMAKE-Desktop_Qt_5_12_3_GCC_64bit-Default/Registration_ITK_CMAKE";
process->start(file);
std::cout << file.toStdString() << std::endl;
std::cout << "status: " << status << std::endl;
}
void foo::process_started()
{
std::cout << "It worked" << std::endl;
}
void foo::processError(QProcess::ProcessError error)
{
std::cout << "error enum val = " << error << std::endl;
}
main
#include <QCoreApplication>
#include <iostream>
#include "foo.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
foo *f = new foo();
return a.exec();
}
When I run the process->start(file); I receive a error with value of 0, but when I run process->start(file, {"sudo"}); I receive a signal that the program run successfully, but anything is showed on the screen.
I'm trying to run on UBUNTU 16.04.
So, what is happening?
The most obvious difference is that system passes your string to the shell, while QProcess::start takes a command and argument list separately.
I bet you will get "file not found" if you hook to the errorOccurred signal.
Solution: remove the \\ from your string, as those are only needed if a shell is involved.
I'm having a problem with my application, in which I'm trying to get all network configurations of the system that it runs on. The final goal is to find the MAC address with highest priority.
The code runs ok and works when I run it with QtCreator and also runs ok when I create a folder containing the dll files and the exe file.
But the problem is that when I run this program on other windows machines (7 and 10) it runs but does not return or show anything. I tried running it as an Administrator, that didn't work neither and this code should be able to work on all windows platforms.
Any suggestions?
I'm currently on Windows 10 and using Qt 5.8 MSVC 2015
The exe file runs with these dlls on Windows 10:
Qt5Core.dll
Qt5Network.dll
msvcp140.dll
msvcr120.dll
vcruntime140.dll
These dlls should be also there for windows 7:
api-ms-win-core-file-l1-2-0.dll
api-ms-win-core-file-l2-1-0.dll
api-ms-win-core-localization-l1-2-0.dll
api-ms-win-core-processthreads-l1-1-1.dll
api-ms-win-core-string-l1-1-0.dll
api-ms-win-core-synch-l1-2-0.dll
api-ms-win-core-timezone-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-environment-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-multibyte-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
Link below is the exe and dll files together:
https://ufile.io/e9htu
here's my code if needed:
main.cpp
#include <QCoreApplication>
#include "macfinder.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MACFinder macFinder;
macFinder.findMAC();
return a.exec();
}
macfinder.h
#ifndef MACFINDER_H
#define MACFINDER_H
#include <QObject>
#include <QNetworkConfiguration>
#include <QNetworkConfigurationManager>
#include <QNetworkInterface>
#include <QNetworkSession>
#include <QDebug>
class MACFinder : public QObject
{
Q_OBJECT
public:
explicit MACFinder(QObject *parent = 0);
void findMAC();
private:
QNetworkConfigurationManager ncm;
QString filterMAC(QList<QNetworkConfiguration> configs);
signals:
void foundMAC(QString MAC);
private slots:
void configurationsUpdateCompleted();
};
#endif // MACFINDER_H
macfinder.cpp
#include "macfinder.h"
MACFinder::MACFinder(QObject *parent) : QObject(parent)
{
}
QString MACFinder::filterMAC(QList<QNetworkConfiguration> configs)
{
qDebug() << "MAC and Index: ";
QString MAC;
int index;
QNetworkConfiguration nc;
foreach(nc,configs)
{
QNetworkSession networkSession(nc);
QNetworkInterface netInterface = networkSession.interface();
QString debugStr = QString::number(netInterface.index())
+ " | " + netInterface.humanReadableName() + " | "
+ nc.name() + " | " + netInterface.hardwareAddress();
if(netInterface.hardwareAddress().isEmpty())
{
qDebug() << "--> No MAC: " << debugStr;
continue;
}
if(netInterface.name().isEmpty())
{
qDebug() << "--> NO NAME: " << debugStr;
continue;
}
if(netInterface.index() == 0)
{
qDebug() << "--> NO INDEX: " << debugStr;
continue;
}
if(netInterface.flags() & QNetworkInterface::IsLoopBack)
{
qDebug() << "--> loopBack: " << debugStr;
continue;
}
if(netInterface.flags() & (QNetworkInterface::IsRunning | QNetworkInterface::IsUp))
{
qDebug() << "*** Accepted: " << debugStr;
if(MAC.isEmpty())
{
qDebug() << "setting MAC:" << debugStr;
MAC = netInterface.hardwareAddress();
index = netInterface.index();
}
else
{
if(netInterface.index() < index)
{
qDebug() << "setting MAC:" << debugStr;
MAC = netInterface.hardwareAddress();
index = netInterface.index();
}
else
qDebug() << "index is not lower: " << debugStr;
}
}
}
return MAC;
}
void MACFinder::findMAC()
{
qDebug() << "MACFinder::findMAC | updating all configurations";
connect(&ncm,SIGNAL(updateCompleted()),this,SLOT(configurationsUpdateCompleted()));
ncm.updateConfigurations();
}
void MACFinder::configurationsUpdateCompleted()
{
qDebug() << "MACFinder::configurationsUpdateCompleted";
disconnect(&ncm,SIGNAL(updateCompleted()),this,SLOT(configurationsUpdateCompleted()));
QNetworkConfiguration nc;
QList<QNetworkConfiguration> configs = ncm.allConfigurations(QNetworkConfiguration::Active);
qDebug() << "\nAllConfigs: ";
foreach (nc,configs)
{
qDebug() << nc.identifier() << nc.name() << nc.state();
}
QString MAC = filterMAC(configs);
qDebug() << "\nMAC:" << MAC;
if(MAC.isEmpty())
{
qDebug("no MAC address found");
}
emit foundMAC(MAC);
}
I downloaded your app and analyze it on my computer.
problem is you missing some dlls, your app running without error but not working properly. (qgenericbearer.dll , qnativewifibearer.dll with folder bearer are missing ).
you can use windeploy command to deploy your project.
go to Qt, compiler directory on your OS for example:
C:\Qt\Qt5.7.0\5.7\msvc2013\bin
press Shift+right click mouse then click open command window here
type windeployqt.exe c:\Your app directory for example:
windeployqt.exe C:\Users\Mofrad\Downloads\macfindertest\macFinderTest\macAddressTest.exe
now some dlls will copy to your app directory.
Now try your app again and you'll see it's working.
I am new in Qt development and developing Qt DLL which start TCP Server.When i am calling dll from my another app it will not receive any new connection socket.
So please guide me if i am doing any wrong step.
Server.h
extern "C" SERVERSHARED_EXPORT void CallServer();
class SERVERSHARED_EXPORT Server : public QObject
{
Q_OBJECT
public:
Server();
void CallServer();
void CallServer1();
QTcpServer *server;
QTcpSocket *socket ;
signals:
public slots:
void myConnection();
void closingClient();
};
Server.cpp
Server::Server()
{
}
void CallServer()
{
Server server_Obj;
server_Obj.CallServer1();
while (true)
::sleep(1000);
}
void Server::CallServer1()
{
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()),this, SLOT(myConnection()));
QHostAddress hostadd(ServerIP);
qDebug() << ServerIP;
qDebug() << Port;
if(!server->listen(hostadd,Port.toInt())) qDebug() << "\nWeb server could not start";
else qDebug() <<"\nWeb server is waiting for a connection";
}
void Server::myConnection()
{
qDebug() << "Detected Connection";
QByteArray Rdata;
socket = server->nextPendingConnection();
qDebug() << "Wait for connect = " << socket->waitForConnected();
while (socket->waitForReadyRead(10))
{
while(socket->bytesAvailable() > 0)
{
Rdata.append(socket->readAll());
}
}
qDebug() << "Final Testing is size = " << Rdata.size();
qDebug() << "Final Testing is" << Rdata;
}
.pro file
QT += core
QT += network
QT += widgets
QT -= gui
TARGET = Server
TEMPLATE = lib
DEFINES += SERVER_LIBRARY
SOURCES += server.cpp
HEADERS += server.h\
server_global.h
Another App:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QLibrary library("Server.dll");
if (!library.load())
qDebug() << library.errorString();
if (library.load())
qDebug() << "library loaded";
typedef int(*pf)(void);
pf cwf = (pf)library.resolve("CallServer");
if (cwf) {
int x = cwf();
} else {
qDebug() << "Could not show widget from the loaded library";
}
qDebug() << "After call";
return a.exec();
}
Looks like it's not working because you are using QTcpSocket (your Server class) in asynchronous (signals/slots) way WITHOUT event loop - so it'll not work. You should add an event loop or use sockets in a blocking manner. For more details look at - http://doc.qt.io/qt-5/qtnetwork-blockingfortuneclient-example.html
I have an application that when run through terminal, the user has the option between command-line mode or GUI mode.
There doesn't seem to be any output to the console at all when using std::cout. std::cout statements don't work in the main event loop.
I have added CONFIG += console to my .pro file.
For now, I have been using QTextStream() which works fine:
QTextStream(cout) << "Hello World" << std::endl;
My question is:
Why can I not use std::cout? Does this have something to do with Qt affecting input and output streams? I couldn't find any documentation in Qt's docs on this.
int main(int argc, char *argv[])
{
std::cout << argv[1] << std::endl; //This is being outputted.
//if(argc == 2 && !strcmp(argv[1],"-win")){
if(true){ //Just for this example's sake
QApplication a(argc, argv);
std::cout << "Hello" << std::endl; //This is not being ouputted.
MainWindow w;
w.show();
return a.exec();
}
else
{
qDebug() << "Console Mode.\n";
std::cout << "Console Mode.\n";
//Do stuff
}
}
This is not a Qt issue, but how std::cout works. You seem to blow up your std::cout in here:
std::cout << argv[1] << std::endl;
Your issue can be reproduced even with a simple program like this:
main.pro
TEMPLATE = app
TARGET = main
CONFIG -= qt
SOURCES += main.cpp
main.cpp
#include <iostream>
int main(int /*argc*/, char **argv)
{
std::cout << argv[1] << std::endl;
std::cout << "Hello stdout!" << std::endl;
if (std::cout.bad())
std::cerr << "I/O error while reading\n";
return 0;
}
Build and Run
Success: qmake && make && ./main foo
Failure: qmake && make && ./main
In your case argv[1] is nil and so this makes std::cout not to print anything more. I would suggest to either pass an argument all the time and/or check against argc with some help usage print. The best would be to use the builtin command line parser in QtCore these days.
You could ask why? Because it is undefined behavior. You can read the details from the documentation:
basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);
After constructing and checking the sentry object, checks if sb is a null pointer. If it is, executes setstate(badbit) and exits.
If you happen to have an issue with the IDE itself, for instance QtCreator, then follow these steps in case of QtCreator:
Projects -> Select a kit -> Run tab -> Run section -> Arguments
Works OK for me:
QT += core
QT -= gui
TARGET = untitled
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
main.cpp:
#include <QCoreApplication>
#include <QTextStream>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout << "Hello World" << std::endl;
return a.exec();
}
EDIT:
#include <QCoreApplication>
#include <QTextStream>
#include <QtWidgets/QWidget>
#include <QDebug>
#include <iostream>
int main(int argc, char *argv[]) {
std::cout << "test" << std::endl; // <--- THE PROBLEM IS HERE...IF YOU TRY A SIMPLE STRING IT WORKS FINE SO THE PROBLEM IS argv[1] IS AN EMPTY STRING
//if(argc == 2 && !strcmp(argv[1],"-win")){
if(true){
//Just for this example's sake
QCoreApplication a(argc, argv);
std::cout << "Hello" << std::endl; //This is not being ouputted.
return a.exec();
}
else
{
qDebug() << "Console Mode.\n";
std::cout << "Console Mode.\n";
//Do stuff
} }