├── .gitignore ├── PluginManager ├── .gitignore ├── MyPluginOne │ ├── MyPluginOne.json │ ├── MyPluginOne.pro │ ├── mypluginone.cpp │ ├── mypluginone.h │ └── mypluginone_global.h ├── PM.pri ├── PM.pro ├── PluginManager │ ├── PluginManager.pro │ └── main.cpp └── README.txt ├── TestLaunchBrowser ├── TestLaunchBrowser.pro ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h └── mainwindow.ui ├── TestLoadDependencies ├── TestLoadDependencies.pro ├── dependencyList.txt └── main.cpp ├── TestQMutexQThread ├── TestQMutexQThread.pro ├── main.cpp ├── worker.cpp └── worker.h ├── TestQSystemSemaphore ├── MyExe │ ├── MyExe.pro │ └── main.cpp ├── TestMyExeWithQSystemSemaphore │ ├── TestMyExeWithQSystemSemaphore.pro │ └── main.cpp └── TestQSystemSemaphore.pro ├── TestSignalTrigger ├── PluginOne │ ├── PluginOne.h │ ├── PluginOne.json │ ├── PluginOne.pro │ ├── pluginone.cpp │ └── pluginone_global.h ├── PluginTwo │ ├── PluginTwo.json │ ├── PluginTwo.pro │ ├── plugintwo.cpp │ ├── plugintwo.h │ └── plugintwo_global.h ├── README.txt ├── TestPluginOnePluginTwo │ ├── TestPluginOnePluginTwo.pro │ └── main.cpp ├── TestQtService │ ├── TestQtService.pro │ ├── TestQtService.pro.user │ ├── main.cpp │ ├── message_handler.cpp │ ├── message_handler.h │ ├── mydaemon.cpp │ ├── mydaemon.h │ ├── myservice.cpp │ ├── myservice.h │ ├── process_loader.cpp │ ├── process_loader.h │ └── qtservice │ │ ├── INSTALL.TXT │ │ ├── README.TXT │ │ ├── buildlib │ │ └── buildlib.pro │ │ ├── common.pri │ │ ├── configure │ │ ├── configure.bat │ │ ├── doc │ │ ├── html │ │ │ ├── classic.css │ │ │ ├── images │ │ │ │ └── qt-logo.png │ │ │ ├── index.html │ │ │ ├── qtservice-example-controller.html │ │ │ ├── qtservice-example-interactive.html │ │ │ ├── qtservice-example-server.html │ │ │ ├── qtservice-members.html │ │ │ ├── qtservice.dcf │ │ │ ├── qtservice.html │ │ │ ├── qtservice.index │ │ │ ├── qtservice.qhp │ │ │ ├── qtservicebase-members.html │ │ │ ├── qtservicebase.html │ │ │ ├── qtservicecontroller-members.html │ │ │ └── qtservicecontroller.html │ │ ├── images │ │ │ └── qt-logo.png │ │ └── index.qdoc │ │ ├── qtservice.pro │ │ ├── qtservice.pro.user │ │ └── src │ │ ├── QtService │ │ ├── QtServiceBase │ │ ├── QtServiceController │ │ ├── qtservice.cpp │ │ ├── qtservice.h │ │ ├── qtservice.pri │ │ ├── qtservice_p.h │ │ ├── qtservice_unix.cpp │ │ ├── qtservice_win.cpp │ │ ├── qtunixserversocket.cpp │ │ ├── qtunixserversocket.h │ │ ├── qtunixsocket.cpp │ │ └── qtunixsocket.h ├── TestSignalTrigger.pri └── TestSignalTrigger.pro ├── TestWindowsService ├── .gitignore ├── README.txt ├── TestWindowsService.pri ├── TestWindowsService.pro ├── main.cpp ├── message_handler.cpp ├── message_handler.h ├── my_windows_service.cpp ├── my_windows_service.h ├── qt-service-lib │ ├── debug │ │ ├── QtSolutions_Service-headd.dll │ │ ├── QtSolutions_Service-headd.lib │ │ └── qtsolutions_service-headd.pdb │ ├── include │ │ └── qtservice.h │ └── release │ │ ├── QtSolutions_Service-head.dll │ │ └── QtSolutions_Service-head.lib ├── windowassist.cpp └── windowassist.h └── TestWindowsServiceWithLibrarySource ├── TestWindowsServiceWithLibrarySource.pri ├── TestWindowsServiceWithLibrarySource.pro ├── main.cpp ├── my_windows_service.cpp ├── my_windows_service.h └── qtservice ├── qtservice.cpp ├── qtservice.h ├── qtservice.pri ├── qtservice_p.h ├── qtservice_unix.cpp ├── qtservice_win.cpp ├── qtunixserversocket.cpp ├── qtunixserversocket.h ├── qtunixsocket.cpp └── qtunixsocket.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | build/ 3 | build-* 4 | -------------------------------------------------------------------------------- /PluginManager/.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | -------------------------------------------------------------------------------- /PluginManager/MyPluginOne/MyPluginOne.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/PluginManager/MyPluginOne/MyPluginOne.json -------------------------------------------------------------------------------- /PluginManager/MyPluginOne/MyPluginOne.pro: -------------------------------------------------------------------------------- 1 | include(../PM.pri) 2 | 3 | QT -= gui 4 | 5 | TARGET = MyPluginOne 6 | TEMPLATE = lib 7 | 8 | DEFINES += MYPLUGINONE_LIBRARY 9 | 10 | SOURCES += mypluginone.cpp 11 | 12 | HEADERS += mypluginone.h\ 13 | mypluginone_global.h 14 | 15 | unix { 16 | target.path = /usr/lib 17 | INSTALLS += target 18 | } 19 | -------------------------------------------------------------------------------- /PluginManager/MyPluginOne/mypluginone.cpp: -------------------------------------------------------------------------------- 1 | #include "mypluginone.h" 2 | 3 | 4 | MyPluginOne::MyPluginOne(int data, QString name) 5 | : data(data) 6 | , dataName(name) 7 | { 8 | } 9 | 10 | MyPluginOne::~MyPluginOne() 11 | {} 12 | 13 | void MyPluginOne::setData(int data) 14 | { 15 | this->data = data; 16 | emit dataChanged(data); 17 | } 18 | 19 | void MyPluginOne::setDataName(QString name) 20 | { 21 | dataName = name; 22 | emit dataNameChanged(name); 23 | } 24 | 25 | int MyPluginOne::getData() 26 | { 27 | return data; 28 | } 29 | 30 | QString MyPluginOne::getDataName() 31 | { 32 | return dataName; 33 | } 34 | -------------------------------------------------------------------------------- /PluginManager/MyPluginOne/mypluginone.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPLUGINONE_H 2 | #define MYPLUGINONE_H 3 | 4 | #include "mypluginone_global.h" 5 | 6 | #include 7 | 8 | class MYPLUGINONESHARED_EXPORT MyPluginOne : public QObject 9 | { 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "mypluginone" FILE "MyPluginOne.json") 12 | 13 | public: 14 | MyPluginOne(int data=-1, QString name="InitialName"); 15 | ~MyPluginOne(); 16 | 17 | public slots: 18 | void setData(int data); 19 | void setDataName(QString name); 20 | 21 | public: 22 | int getData(); 23 | QString getDataName(); 24 | 25 | signals: 26 | void dataChanged(int data); 27 | void dataNameChanged(QString name); 28 | 29 | private: 30 | int data; 31 | QString dataName; 32 | }; 33 | 34 | Q_DECLARE_METATYPE(MyPluginOne*) 35 | 36 | #endif // MYPLUGINONE_H 37 | -------------------------------------------------------------------------------- /PluginManager/MyPluginOne/mypluginone_global.h: -------------------------------------------------------------------------------- 1 | #ifndef MYPLUGINONE_GLOBAL_H 2 | #define MYPLUGINONE_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(MYPLUGINONE_LIBRARY) 7 | # define MYPLUGINONESHARED_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define MYPLUGINONESHARED_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // MYPLUGINONE_GLOBAL_H 13 | -------------------------------------------------------------------------------- /PluginManager/PM.pri: -------------------------------------------------------------------------------- 1 | CONFIG(debug, debug|release) { 2 | DR_CONFIG_NAME = debug 3 | } else { 4 | DR_CONFIG_NAME = release 5 | } 6 | 7 | DESTDIR = $$PWD/../build/$$DR_CONFIG_NAME 8 | 9 | LIBS += -L$$DESTDIR 10 | -------------------------------------------------------------------------------- /PluginManager/PM.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS += \ 4 | MyPluginOne \ 5 | PluginManager 6 | 7 | PluginManager.depends = \ 8 | MyPluginOne 9 | -------------------------------------------------------------------------------- /PluginManager/PluginManager/PluginManager.pro: -------------------------------------------------------------------------------- 1 | include(../PM.pri) 2 | 3 | QT += core 4 | QT -= gui 5 | 6 | CONFIG += c++11 7 | 8 | TARGET = PluginManager 9 | CONFIG += console 10 | CONFIG -= app_bundle 11 | 12 | TEMPLATE = app 13 | 14 | SOURCES += main.cpp 15 | 16 | INCLUDEPATH += $$PWD/../MyPluginOne 17 | 18 | LIBS += -lMyPluginOne 19 | -------------------------------------------------------------------------------- /PluginManager/PluginManager/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "MyPluginOne.h" 8 | 9 | QObject* retrievePackage(const QString& pkgName) 10 | { 11 | QString name = pkgName.toLower(); 12 | 13 | QFile file(name); 14 | QPluginLoader loader(file.fileName()); 15 | 16 | if (!loader.load()) 17 | { 18 | qDebug() << "Failed to load " << name << "........"; 19 | } 20 | 21 | QObject* packageObj = loader.instance(); 22 | return packageObj; 23 | } 24 | 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | QCoreApplication a(argc, argv); 29 | 30 | QObject* pkgObj = retrievePackage("MyPluginOne"); 31 | MyPluginOne* mpo = qobject_cast(pkgObj); 32 | 33 | QObject::connect(mpo, &MyPluginOne::dataChanged, 34 | [](int data){ 35 | qDebug() << "Get dataChanged() Notification! It is " << data; 36 | }); 37 | QObject::connect(mpo, &MyPluginOne::dataNameChanged, 38 | [](QString name){ 39 | qDebug() << "Get dataNameChanged() Notification! It is " << name; 40 | }); 41 | 42 | if (mpo) 43 | { 44 | mpo->setData(100); 45 | qInfo() << "Data = " << mpo->getData(); 46 | mpo->setDataName("GoodBoy"); 47 | qInfo() << "Name = " << mpo->getDataName(); 48 | } 49 | else 50 | { 51 | qDebug() << "Failed to do qobject_cast"; 52 | } 53 | 54 | return a.exec(); 55 | } 56 | -------------------------------------------------------------------------------- /PluginManager/README.txt: -------------------------------------------------------------------------------- 1 | A very simple project to test QtPlugin, loading QtPlugin and connect signal after loading QtPlugin. -------------------------------------------------------------------------------- /TestLaunchBrowser/TestLaunchBrowser.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2016-04-27T14:55:54 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = TestBrowser2 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += main.cpp\ 16 | mainwindow.cpp 17 | 18 | HEADERS += mainwindow.h 19 | 20 | FORMS += mainwindow.ui 21 | -------------------------------------------------------------------------------- /TestLaunchBrowser/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | MainWindow w; 8 | w.show(); 9 | 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /TestLaunchBrowser/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | 4 | #include 5 | #include 6 | 7 | MainWindow::MainWindow(QWidget *parent) : 8 | QMainWindow(parent), 9 | ui(new Ui::MainWindow) 10 | { 11 | ui->setupUi(this); 12 | } 13 | 14 | MainWindow::~MainWindow() 15 | { 16 | delete ui; 17 | } 18 | 19 | void MainWindow::on_pushButton_clicked() 20 | { 21 | QDesktopServices::openUrl(QUrl("http://www.bing.com")); 22 | } 23 | -------------------------------------------------------------------------------- /TestLaunchBrowser/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class MainWindow; 8 | } 9 | 10 | class MainWindow : public QMainWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit MainWindow(QWidget *parent = 0); 16 | ~MainWindow(); 17 | 18 | private slots: 19 | void on_pushButton_clicked(); 20 | 21 | private: 22 | Ui::MainWindow *ui; 23 | }; 24 | 25 | #endif // MAINWINDOW_H 26 | -------------------------------------------------------------------------------- /TestLaunchBrowser/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 170 21 | 100 22 | 91 23 | 41 24 | 25 | 26 | 27 | Bing 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0 35 | 0 36 | 400 37 | 21 38 | 39 | 40 | 41 | 42 | 43 | TopToolBarArea 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /TestLoadDependencies/TestLoadDependencies.pro: -------------------------------------------------------------------------------- 1 | QT += core 2 | QT -= gui 3 | 4 | CONFIG += c++11 5 | 6 | TARGET = TestLoadDependencies 7 | CONFIG += console 8 | CONFIG -= app_bundle 9 | 10 | TEMPLATE = app 11 | 12 | SOURCES += main.cpp 13 | -------------------------------------------------------------------------------- /TestLoadDependencies/dependencyList.txt: -------------------------------------------------------------------------------- 1 | # This is a comment line. 2 | 3 | C:/Users/Finix/AppData/Local/Fortis/bin/proapi_touchmat-0.2.3/win32-msvc2013-x64-d/touchmat2.dll 4 | 5 | C:\\Users\\Finix\\AppData\\Local\\Fortis\\bin\\proapi_hal-0.2.3\\win32-msvc2013-x64-d\\hal.dll 6 | 7 | C:/Users/Finix/AppData/Local/Fortis/bin/proapi_leds-0.2.3/win32-msvc2013-x64-d/leds.dll 8 | 9 | C:\\Users\\Finix\\AppData\\Local\\Fortis\\bin\\proapi_hal-0.2.3\\win32-msvc2013-x64-d\\hal.dll 10 | 11 | C:/Users/Finix/AppData/Local/Fortis/bin/proapi_touchmat-0.2.3/win32-msvc2013-x64-d/touchmat.dll 12 | -------------------------------------------------------------------------------- /TestLoadDependencies/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void readDependencyConfigFile(const QString& filePath, QVector& vec) 11 | { 12 | QFile file(filePath); 13 | if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) 14 | { 15 | qCritical() << "Warning: Cannot open " << filePath; 16 | } 17 | 18 | QTextStream in(&file); 19 | QString line; 20 | while(in.readLineInto(&line)) 21 | { 22 | vec.push_back(line); 23 | } 24 | 25 | file.close(); 26 | } 27 | 28 | 29 | bool goodLibPath(const QString& libPath) 30 | { 31 | bool result = true; 32 | 33 | if (libPath.size() == 0) { 34 | result = false; 35 | } 36 | else if (libPath.at(0) == '#') { 37 | result = false; 38 | } 39 | else { 40 | QFile file(libPath); 41 | if (!file.exists()) 42 | { 43 | qDebug() << "The file does not exists: " << libPath; 44 | result = false; 45 | } 46 | } 47 | 48 | return result; 49 | } 50 | 51 | 52 | // Load the library as a QtPlugin 53 | QObject* loadQtPlugin(const QString& libPath) 54 | { 55 | QPluginLoader loader(libPath); 56 | 57 | if (!loader.load()) 58 | { 59 | qCritical() << "Failed to load " << libPath << "....................."; 60 | } 61 | 62 | QObject* libObj = loader.instance(); 63 | return libObj; 64 | } 65 | 66 | 67 | // Load all the libraries as QtPlugin 68 | void loadLibrariesAsQtPlugin(const QString& configFile) 69 | { 70 | QVector libraryList; 71 | readDependencyConfigFile(configFile, libraryList); 72 | 73 | for(int i=0; i>>>>>>>>> " << "Loading " << libPath << "............"; 80 | QObject* lib = loadQtPlugin(libPath); 81 | if (!lib) 82 | { 83 | qCritical() << "Failed to load: " << libPath; 84 | } 85 | } 86 | else 87 | { 88 | qCritical() << "Ignore the line: " << libPath; 89 | } 90 | qDebug() << ""; 91 | } 92 | } 93 | 94 | 95 | void loadLibraries(const QString& configFile) 96 | { 97 | QVector libraryList; 98 | readDependencyConfigFile(configFile, libraryList); 99 | 100 | for(int i=0; i>>>>>>>> " << "Loading QtPlugin: " << libPath << "............."; 112 | loadQtPlugin(libPath); 113 | } 114 | else 115 | { 116 | qDebug() << ">>>>>>>>>> " << "Loading normal library: " << libPath << "............"; 117 | QLibrary lib(libPath); 118 | if (!lib.load()) 119 | { 120 | qCritical() << "Failed to load: " << libPath; 121 | } 122 | } 123 | 124 | qDebug() << ""; 125 | } 126 | } 127 | } 128 | 129 | QString getEnvVar(const QString& envVar) 130 | { 131 | QString value(qgetenv(envVar.toStdString().c_str())); 132 | 133 | if (value == "") { 134 | qCritical() << "No such environment variable: " << envVar; 135 | } else { 136 | qDebug() << "The value of environment variable " << envVar << " is " << value; 137 | } 138 | 139 | return value; 140 | } 141 | 142 | int main(int argc, char *argv[]) 143 | { 144 | QCoreApplication a(argc, argv); 145 | 146 | QString configFile = "C:/Users/Finix/Desktop/dependencyList.txt"; 147 | 148 | // loadLibrariesAsQtPlugin(configFile); 149 | loadLibraries(configFile); 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /TestQMutexQThread/TestQMutexQThread.pro: -------------------------------------------------------------------------------- 1 | QT += core 2 | QT -= gui 3 | 4 | CONFIG += c++11 5 | 6 | TARGET = TestQSemaphore 7 | CONFIG += console 8 | CONFIG -= app_bundle 9 | 10 | TEMPLATE = app 11 | 12 | SOURCES += main.cpp \ 13 | worker.cpp 14 | 15 | HEADERS += \ 16 | worker.h 17 | -------------------------------------------------------------------------------- /TestQMutexQThread/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "worker.h" 5 | 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QCoreApplication a(argc, argv); 10 | 11 | QThread* t1 = new QThread; 12 | QThread* t2 = new QThread; 13 | 14 | Worker* w1 = new Worker; 15 | Worker* w2 = new Worker; 16 | 17 | w1->moveToThread(t1); 18 | w2->moveToThread(t2); 19 | 20 | QObject::connect(t1, &QThread::started, w1, &Worker::run); 21 | QObject::connect(w1, &Worker::finished, t1, &QThread::quit); 22 | QObject::connect(w1, &Worker::finished, [](){qInfo() << "w1 quit......";}); 23 | QObject::connect(w1, &Worker::finished, w1, &Worker::deleteLater); 24 | QObject::connect(t1, &QThread::finished, t1, &QThread::deleteLater); 25 | 26 | QObject::connect(t2, &QThread::started, w2, &Worker::run); 27 | QObject::connect(w2, &Worker::finished, t2, &QThread::quit); 28 | QObject::connect(w2, &Worker::finished, [](){qInfo() << "w2 quit......";}); 29 | QObject::connect(w2, &Worker::finished, w2, &Worker::deleteLater); 30 | QObject::connect(t2, &QThread::finished, t2, &QThread::deleteLater); 31 | 32 | 33 | t1->start(); 34 | t2->start(); 35 | 36 | t1->wait(300); 37 | t2->wait(300); 38 | 39 | qInfo() << "At the end of main thread..."; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /TestQMutexQThread/worker.cpp: -------------------------------------------------------------------------------- 1 | #include "worker.h" 2 | #include 3 | 4 | 5 | int Worker::myValue = 0; 6 | QMutex Worker::leds_mutex; 7 | 8 | Worker::Worker(QObject* parent) 9 | : QObject(parent) 10 | , m_id(QUuid::createUuid().toString()) 11 | { 12 | } 13 | 14 | Worker::~Worker() 15 | { 16 | } 17 | 18 | void Worker::run() 19 | { 20 | int count = 0; 21 | while (count < 5) { 22 | ++count; 23 | Worker::leds_mutex.lock(); 24 | 25 | QFile file; 26 | QDir::setCurrent("C:/Users/Finix/Desktop"); 27 | file.setFileName("1.txt"); 28 | if (!file.open(QIODevice::Append | QIODevice::Text)) { 29 | qCritical() << "Failed to open file"; 30 | Worker::leds_mutex.unlock(); 31 | break; 32 | } 33 | 34 | QTextStream out(&file); 35 | out << "id: " << m_id << ", myValue = " << Worker::myValue << '\n'; 36 | qInfo() << "id: " << m_id << ", myValue = " << Worker::myValue; 37 | ++Worker::myValue; 38 | 39 | Worker::leds_mutex.unlock(); 40 | } 41 | 42 | emit finished(); 43 | } 44 | -------------------------------------------------------------------------------- /TestQMutexQThread/worker.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTHREAD_H 2 | #define MYTHREAD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | class Worker : public QObject 12 | { 13 | Q_OBJECT 14 | 15 | private: 16 | static int myValue; 17 | static QMutex leds_mutex; 18 | QString m_id; 19 | 20 | public: 21 | Worker(QObject* parent = nullptr); 22 | ~Worker(); 23 | 24 | public slots: 25 | void run(); 26 | 27 | signals: 28 | void finished(); 29 | void error(QString err); 30 | }; 31 | 32 | #endif // MYTHREAD_H 33 | -------------------------------------------------------------------------------- /TestQSystemSemaphore/MyExe/MyExe.pro: -------------------------------------------------------------------------------- 1 | QT += core 2 | QT -= gui 3 | 4 | CONFIG += c++11 5 | 6 | TARGET = MyExe 7 | CONFIG += console 8 | CONFIG -= app_bundle 9 | 10 | TEMPLATE = app 11 | 12 | SOURCES += main.cpp 13 | 14 | DESTDIR = $$PWD/../build 15 | -------------------------------------------------------------------------------- /TestQSystemSemaphore/MyExe/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | QCoreApplication a(argc, argv); 13 | 14 | QUuid uuid = QUuid::createUuid(); 15 | QString id = uuid.toString(); 16 | 17 | QSystemSemaphore qss("MySystemSemaphore", 1); 18 | 19 | int count = 0; 20 | while (count < 5) { 21 | ++count; 22 | qss.acquire(); 23 | 24 | QFile file; 25 | QDir::setCurrent("C:/Users/Finix/Desktop"); 26 | file.setFileName("out.txt"); 27 | if (!file.open(QIODevice::Append | QIODevice::Text)) { 28 | qDebug() << "Failed to open file"; 29 | qss.release(); 30 | break; 31 | } 32 | 33 | QTextStream out(&file); 34 | out << id << ": " << count << "\n"; 35 | qDebug() << id << ": " << count; 36 | QThread::sleep(1); 37 | qss.release(); 38 | } 39 | 40 | qDebug() << "Exit..."; 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /TestQSystemSemaphore/TestMyExeWithQSystemSemaphore/TestMyExeWithQSystemSemaphore.pro: -------------------------------------------------------------------------------- 1 | QT += core 2 | QT -= gui 3 | 4 | CONFIG += c++11 5 | 6 | TARGET = MyExeTest 7 | CONFIG += console 8 | CONFIG -= app_bundle 9 | 10 | TEMPLATE = app 11 | 12 | SOURCES += main.cpp 13 | 14 | DESTDIR = $$PWD/../build 15 | -------------------------------------------------------------------------------- /TestQSystemSemaphore/TestMyExeWithQSystemSemaphore/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QCoreApplication a(argc, argv); 8 | 9 | std::thread t1([](){QProcess::execute("./MyExe.exe");}); 10 | std::thread t2([](){QProcess::execute("./MyExe.exe");}); 11 | 12 | t1.join(); 13 | t2.join(); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /TestQSystemSemaphore/TestQSystemSemaphore.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS += \ 4 | MyExe \ 5 | TestMyExeWithQSystemSemaphore 6 | 7 | TestMyExeWithQSystemSemaphore.depends = MyExe 8 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginOne/PluginOne.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGINONE_H 2 | #define PLUGINONE_H 3 | 4 | #include 5 | #include "pluginone_global.h" 6 | 7 | class PLUGINONESHARED_EXPORT PluginOne : public QObject 8 | { 9 | Q_OBJECT 10 | Q_PLUGIN_METADATA(IID "pluginone" FILE "PluginOne.json") 11 | 12 | public: 13 | PluginOne(int d = 0); 14 | ~PluginOne(); 15 | 16 | Q_INVOKABLE int getData(); 17 | 18 | public slots: 19 | void setData(int x); 20 | 21 | signals: 22 | void dataChanged(int x); 23 | 24 | 25 | private: 26 | int data; 27 | }; 28 | 29 | Q_DECLARE_METATYPE(PluginOne*) 30 | 31 | #endif // PLUGINONE_H 32 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginOne/PluginOne.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestSignalTrigger/PluginOne/PluginOne.json -------------------------------------------------------------------------------- /TestSignalTrigger/PluginOne/PluginOne.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2016-04-14T15:41:09 4 | # 5 | #------------------------------------------------- 6 | 7 | include(../TestSignalTrigger.pri) 8 | 9 | QT -= gui 10 | 11 | TARGET = PluginOne 12 | TEMPLATE = lib 13 | 14 | DEFINES += PLUGINONE_LIBRARY 15 | 16 | SOURCES += pluginone.cpp 17 | 18 | HEADERS += pluginone.h\ 19 | pluginone_global.h 20 | 21 | unix { 22 | target.path = /usr/lib 23 | INSTALLS += target 24 | } 25 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginOne/pluginone.cpp: -------------------------------------------------------------------------------- 1 | #include "pluginone.h" 2 | 3 | 4 | PluginOne::PluginOne(int d) : data(d) 5 | { 6 | } 7 | 8 | PluginOne::~PluginOne() 9 | { 10 | } 11 | 12 | int PluginOne::getData() { 13 | return data; 14 | } 15 | 16 | void PluginOne::setData(int x) { 17 | data = x; 18 | emit dataChanged(x); 19 | } 20 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginOne/pluginone_global.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGINONE_GLOBAL_H 2 | #define PLUGINONE_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(PLUGINONE_LIBRARY) 7 | # define PLUGINONESHARED_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define PLUGINONESHARED_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // PLUGINONE_GLOBAL_H 13 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginTwo/PluginTwo.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestSignalTrigger/PluginTwo/PluginTwo.json -------------------------------------------------------------------------------- /TestSignalTrigger/PluginTwo/PluginTwo.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2016-04-14T15:50:26 4 | # 5 | #------------------------------------------------- 6 | 7 | include(../TestSignalTrigger.pri) 8 | 9 | QT -= gui 10 | 11 | TARGET = PluginTwo 12 | TEMPLATE = lib 13 | 14 | DEFINES += PLUGINTWO_LIBRARY 15 | 16 | SOURCES += plugintwo.cpp 17 | 18 | HEADERS += plugintwo.h\ 19 | plugintwo_global.h 20 | 21 | unix { 22 | target.path = /usr/lib 23 | INSTALLS += target 24 | } 25 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginTwo/plugintwo.cpp: -------------------------------------------------------------------------------- 1 | #include "plugintwo.h" 2 | 3 | #include 4 | 5 | 6 | PluginTwo::PluginTwo(const QString name) 7 | : fileName(name), destFile(name) 8 | { 9 | destFile.resize(0); 10 | } 11 | 12 | PluginTwo::~PluginTwo() 13 | { 14 | } 15 | 16 | void PluginTwo::writeFile(int x) 17 | { 18 | qDebug() << "writeFile() slot is triggered " << x; 19 | 20 | if (destFile.open(QFile::WriteOnly | QFile::Append)) { 21 | QTextStream out(&destFile); 22 | out << "Result: " << left << x << "\t" << x << "\n"; 23 | } 24 | 25 | destFile.close(); 26 | } 27 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginTwo/plugintwo.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGINTWO_H 2 | #define PLUGINTWO_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "plugintwo_global.h" 9 | 10 | class PLUGINTWOSHARED_EXPORT PluginTwo : public QObject 11 | { 12 | Q_OBJECT 13 | Q_PLUGIN_METADATA(IID "plugintwo" FILE "PluginTwo.json") 14 | 15 | public: 16 | PluginTwo(const QString name = "PluginTwoFile.txt"); 17 | ~PluginTwo(); 18 | 19 | public slots: 20 | void writeFile(int x); 21 | 22 | private: 23 | QFile destFile; 24 | QString fileName; 25 | }; 26 | 27 | #endif // PLUGINTWO_H 28 | -------------------------------------------------------------------------------- /TestSignalTrigger/PluginTwo/plugintwo_global.h: -------------------------------------------------------------------------------- 1 | #ifndef PLUGINTWO_GLOBAL_H 2 | #define PLUGINTWO_GLOBAL_H 3 | 4 | #include 5 | 6 | #if defined(PLUGINTWO_LIBRARY) 7 | # define PLUGINTWOSHARED_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define PLUGINTWOSHARED_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // PLUGINTWO_GLOBAL_H 13 | -------------------------------------------------------------------------------- /TestSignalTrigger/README.txt: -------------------------------------------------------------------------------- 1 | In TestQtService, a Windows service can be installed, uninstalled, start, paused, or stopped. 2 | In this service, PluginOne's signal is connected to PluginTwo's slot. 3 | 4 | How to handle the service? 5 | -i install 6 | -u uninstal 7 | -s start 8 | -t stop/terminate 9 | -p pause 10 | -h help 11 | 12 | In the folder "qtservice", we use the 3rd party library/source qtsolution/qtservice. 13 | You can refer to qtsolution here: https://github.com/qtproject/qt-solutions 14 | 15 | Log is at C:\Windows\System32\MyService.log 16 | 17 | ----------------------------- 18 | 19 | Note: 20 | Since Windows Vista, Windows Service does not support start a GUI application. Actually, the application has been started, and you can find it in TaskManager, but you cannot see its GUI. That's just because its GUI and the service are in session 0 where GUI cannot be seen. See the articles below for more details. 21 | http://stackoverflow.com/questions/5063731/is-there-any-way-to-start-a-gui-application-from-a-windows-service-on-windows-7 22 | https://msdn.microsoft.com/en-us/library/windows/desktop/ms683502(v=vs.85).aspx 23 | 24 | However, in the practice, Windows Service actually is able to start an application with GUI, e.g. notepad.exe. Please refer to launchGUIApplication() in mydaemon.cpp. 25 | 26 | This article also contains interesting points: http://blog.csdn.net/nirendao/article/details/51194003 27 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestPluginOnePluginTwo/TestPluginOnePluginTwo.pro: -------------------------------------------------------------------------------- 1 | include(../TestSignalTrigger.pri) 2 | 3 | QT += core 4 | QT -= gui 5 | 6 | CONFIG += c++11 7 | 8 | TARGET = TestPluginOnePluginTwo 9 | CONFIG += console 10 | CONFIG -= app_bundle 11 | 12 | INCLUDEPATH += \ 13 | $$PWD/../PluginOne \ 14 | $$PWD/../PluginTwo 15 | 16 | LIBS += \ 17 | -L$$DESTDIR \ 18 | -lPluginOne \ 19 | -lPluginTwo 20 | 21 | TEMPLATE = app 22 | 23 | SOURCES += main.cpp 24 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestPluginOnePluginTwo/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "PluginOne.h" 5 | #include "PluginTwo.h" 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QCoreApplication a(argc, argv); 10 | 11 | PluginOne one(10); 12 | PluginTwo two; 13 | QObject::connect(&one, &PluginOne::dataChanged, &two, &PluginTwo::writeFile); 14 | 15 | int i = 100; 16 | while (i++ < 105) { 17 | one.setData(i); 18 | } 19 | 20 | return a.exec(); 21 | } 22 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/TestQtService.pro: -------------------------------------------------------------------------------- 1 | include(../TestSignalTrigger.pri) 2 | 3 | QT += core network 4 | QT -= gui 5 | 6 | TARGET = TestQtService 7 | TEMPLATE = app 8 | 9 | CONFIG += c++11 10 | CONFIG += console 11 | CONFIG -= app_bundle 12 | 13 | DEFINES += _UNICODE 14 | 15 | 16 | INCLUDEPATH += \ 17 | $$PWD/../PluginOne \ 18 | $$PWD/../PluginTwo 19 | 20 | LIBS += \ 21 | -L$$DESTDIR \ 22 | -lPluginOne \ 23 | -lPluginTwo \ 24 | -lWtsApi32 \ 25 | -lAdvApi32 \ 26 | -lUserEnv 27 | 28 | SOURCES += main.cpp \ 29 | mydaemon.cpp \ 30 | myservice.cpp \ 31 | message_handler.cpp \ 32 | process_loader.cpp 33 | 34 | include(qtservice/src/qtservice.pri) 35 | 36 | HEADERS += \ 37 | mydaemon.h \ 38 | myservice.h \ 39 | message_handler.h \ 40 | process_loader.h 41 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "PluginOne.h" 14 | #include "PluginTwo.h" 15 | 16 | #include "qtservice.h" 17 | #include "myservice.h" 18 | #include "message_handler.h" 19 | 20 | 21 | int main(int argc, char **argv) 22 | { 23 | #ifdef Q_OS_WIN 24 | MessageHandler::setLogFile("C:/MyService.log"); 25 | #endif 26 | qInstallMessageHandler(MessageHandler::FormatMessage); 27 | 28 | #if !defined(Q_OS_WIN) 29 | // QtService stores service settings in SystemScope, which normally require root privileges. 30 | // To allow testing this example as non-root, we change the directory of the SystemScope settings file. 31 | QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); 32 | qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); 33 | #endif 34 | 35 | MyService service(argc, argv); 36 | return service.exec(); 37 | } 38 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/message_handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "message_handler.h" 8 | 9 | 10 | QString MessageHandler::s_log = "C:/MyService.log"; 11 | 12 | void MessageHandler::setLogFile(QString file) 13 | { 14 | s_log = file; 15 | } 16 | 17 | void MessageHandler::FormatMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) 18 | { 19 | static QMutex mutex; 20 | mutex.lock(); 21 | 22 | QFile logFile(MessageHandler::s_log); 23 | logFile.open(QIODevice::WriteOnly | QIODevice::Append); 24 | 25 | QString log(""); 26 | log += QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz") + QString(" "); 27 | 28 | switch(type) 29 | { 30 | case QtDebugMsg: 31 | log += QString("[Debug]"); 32 | break; 33 | 34 | case QtInfoMsg: 35 | log += QString("[Info]"); 36 | break; 37 | 38 | case QtWarningMsg: 39 | log += QString("[Warn]"); 40 | break; 41 | 42 | case QtCriticalMsg: 43 | log += QString("[Critical]"); 44 | break; 45 | 46 | case QtFatalMsg: 47 | log += QString("[Fatal]"); 48 | abort(); 49 | break; 50 | 51 | default: 52 | log += QString("[UnknownLogType]"); 53 | break; 54 | }; 55 | 56 | log += QString(context.file) 57 | + QString(", Line ") 58 | + QString::number(context.line) 59 | + QString(": %1\n").arg(msg); 60 | 61 | QTextStream text_stream(&logFile); 62 | text_stream << log; 63 | logFile.flush(); 64 | logFile.close(); 65 | 66 | mutex.unlock(); 67 | } 68 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/message_handler.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGEHANDLER_H 2 | #define MESSAGEHANDLER_H 3 | 4 | #include 5 | 6 | class MessageHandler 7 | { 8 | private: 9 | MessageHandler(); 10 | ~MessageHandler(); 11 | 12 | public: 13 | static void setLogFile(QString file = "SproutMonitorService.log"); 14 | static void FormatMessage(QtMsgType type , const QMessageLogContext &context , const QString &msg); 15 | 16 | private: 17 | static QString s_log; 18 | }; 19 | 20 | #endif // MESSAGEHANDLER_HPP 21 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/mydaemon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "mydaemon.h" 5 | #include "process_loader.h" 6 | 7 | 8 | MyDaemon::MyDaemon() 9 | { 10 | m_one = new PluginOne; 11 | m_two = new PluginTwo; 12 | 13 | QObject::connect(m_one, &PluginOne::dataChanged, m_two, &PluginTwo::writeFile); 14 | QObject::connect(m_one, &PluginOne::dataChanged, this, &MyDaemon::startProcess); 15 | } 16 | 17 | MyDaemon::~MyDaemon(){} 18 | 19 | void MyDaemon::run() { 20 | qDebug() << "Starting......"; 21 | int i = 100; 22 | while (i++ < 103) { 23 | m_one->setData(i); 24 | } 25 | } 26 | 27 | void MyDaemon::pause() { 28 | qDebug() << "Paused......"; 29 | } 30 | 31 | void MyDaemon::resume() { 32 | qDebug() << "Resuming......"; 33 | } 34 | 35 | void MyDaemon::startProcess() { 36 | qDebug() << "Start Process......"; 37 | 38 | /* 39 | QStringList parameters; 40 | parameters << "1.txt"; 41 | 42 | // Do not use "system()" or "QProcess::execute()" or "QProcess.start()" 43 | // This is because they will suspend the execution of the service. 44 | QProcess::startDetached("notepad.exe", parameters); 45 | */ 46 | 47 | #ifdef Q_OS_WIN 48 | std::wstring command = L"notepad.exe"; 49 | if (ProcessLoader::loadWindowsApplication(command) == false) { 50 | qDebug() << "Failed to launch " << command.c_str(); 51 | } 52 | #endif 53 | } 54 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/mydaemon.h: -------------------------------------------------------------------------------- 1 | #ifndef MYDAEMON_H 2 | #define MYDAEMON_H 3 | 4 | #include 5 | #include "PluginOne.h" 6 | #include "PluginTwo.h" 7 | 8 | class MyDaemon : public QObject 9 | { 10 | Q_OBJECT 11 | public: 12 | MyDaemon(); 13 | ~MyDaemon(); 14 | 15 | void run(); 16 | void pause(); 17 | void resume(); 18 | 19 | void startProcess(); 20 | 21 | private: 22 | PluginOne* m_one; 23 | PluginTwo* m_two; 24 | }; 25 | 26 | #endif // MYDAEMON_H 27 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/myservice.cpp: -------------------------------------------------------------------------------- 1 | #include "myservice.h" 2 | #include 3 | 4 | MyService::MyService(int argc, char **argv) 5 | : QtService(argc, argv, "FinixTestDaemon") 6 | { 7 | setServiceDescription("A dummy service"); 8 | setServiceFlags(QtServiceBase::CanBeSuspended); 9 | } 10 | 11 | void MyService::start() 12 | { 13 | QCoreApplication* app = application(); 14 | Q_UNUSED(app); 15 | 16 | daemon = new MyDaemon(); 17 | 18 | try { 19 | daemon->run(); 20 | } 21 | catch(...){ 22 | qDebug() << "MyDaemon exit!!!"; 23 | app->quit(); 24 | } 25 | } 26 | 27 | void MyService::pause() { 28 | daemon->pause(); 29 | } 30 | 31 | void MyService::resume() { 32 | daemon->resume(); 33 | } 34 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/myservice.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSERVICE_H 2 | #define MYSERVICE_H 3 | 4 | #include "qtservice.h" 5 | #include "mydaemon.h" 6 | 7 | class MyService : public QtService 8 | { 9 | public: 10 | MyService(int argc, char **argv); 11 | 12 | protected: 13 | void start(); 14 | void pause(); 15 | void resume(); 16 | 17 | private: 18 | MyDaemon* daemon; 19 | }; 20 | 21 | #endif // MYSERVICE_H 22 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/process_loader.cpp: -------------------------------------------------------------------------------- 1 | #include "process_loader.h" 2 | 3 | #ifdef Q_OS_WIN 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #endif 12 | 13 | 14 | ProcessLoader::ProcessLoader() 15 | {} 16 | 17 | ProcessLoader::~ProcessLoader() 18 | {} 19 | 20 | 21 | #ifdef Q_OS_WIN 22 | 23 | bool ProcessLoader::loadWindowsApplication(std::wstring command) 24 | { 25 | BOOL bResult = FALSE; 26 | 27 | DWORD dwSessionId = WTSGetActiveConsoleSessionId(); 28 | if (dwSessionId == 0xFFFFFFFF) 29 | { 30 | return false; 31 | } 32 | 33 | HANDLE hUserToken = NULL; 34 | if (WTSQueryUserToken(dwSessionId, &hUserToken) == FALSE) 35 | { 36 | return false; 37 | } 38 | 39 | HANDLE hTheToken = NULL; 40 | if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hTheToken) == TRUE) 41 | { 42 | 43 | if (ImpersonateLoggedOnUser(hTheToken) == TRUE) 44 | { 45 | DWORD dwCreationFlags = HIGH_PRIORITY_CLASS | CREATE_NEW_CONSOLE; 46 | 47 | STARTUPINFO si = { sizeof(si) }; 48 | PROCESS_INFORMATION pi; 49 | SECURITY_ATTRIBUTES Security1 = { sizeof(Security1) }; 50 | SECURITY_ATTRIBUTES Security2 = { sizeof(Security2) }; 51 | 52 | LPVOID pEnv = NULL; 53 | if (CreateEnvironmentBlock(&pEnv, hTheToken, TRUE) == TRUE) 54 | { 55 | dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; 56 | } 57 | 58 | TCHAR commandLine[MAX_PATH]; 59 | _tcscpy_s(commandLine, MAX_PATH, command.c_str()); 60 | 61 | // Launch the process in the client's logon session. 62 | bResult = CreateProcessAsUser( 63 | hTheToken, 64 | NULL, // (LPWSTR)(path), 65 | (LPWSTR)(commandLine), 66 | &Security1, 67 | &Security2, 68 | FALSE, 69 | dwCreationFlags, 70 | pEnv, 71 | NULL, 72 | &si, 73 | &pi 74 | ); 75 | 76 | RevertToSelf(); 77 | 78 | if (pEnv) 79 | { 80 | DestroyEnvironmentBlock(pEnv); 81 | } 82 | } 83 | CloseHandle(hTheToken); 84 | } 85 | CloseHandle(hUserToken); 86 | 87 | return bResult==TRUE; 88 | } 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/process_loader.h: -------------------------------------------------------------------------------- 1 | #ifndef PROCESSLOADER_H 2 | #define PROCESSLOADER_H 3 | 4 | #include 5 | 6 | 7 | class ProcessLoader 8 | { 9 | public: 10 | ProcessLoader(); 11 | ~ProcessLoader(); 12 | 13 | public: 14 | 15 | #ifdef Q_OS_WIN 16 | static bool loadWindowsApplication(std::wstring command); 17 | #endif 18 | 19 | }; 20 | 21 | #endif // PROCESSLOADER_H 22 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/INSTALL.TXT: -------------------------------------------------------------------------------- 1 | INSTALLATION INSTRUCTIONS 2 | 3 | These instructions refer to the package you are installing as 4 | some-package.tar.gz or some-package.zip. The .zip file is intended for use 5 | on Windows. 6 | 7 | The directory you choose for the installation will be referred to as 8 | your-install-dir. 9 | 10 | Note to Qt Visual Studio Integration users: In the instructions below, 11 | instead of building from command line with nmake, you can use the menu 12 | command 'Qt->Open Solution from .pro file' on the .pro files in the 13 | example and plugin directories, and then build from within Visual 14 | Studio. 15 | 16 | Unpacking and installation 17 | -------------------------- 18 | 19 | 1. Unpacking the archive (if you have not done so already). 20 | 21 | On Unix and Mac OS X (in a terminal window): 22 | 23 | cd your-install-dir 24 | gunzip some-package.tar.gz 25 | tar xvf some-package.tar 26 | 27 | This creates the subdirectory some-package containing the files. 28 | 29 | On Windows: 30 | 31 | Unpack the .zip archive by right-clicking it in explorer and 32 | choosing "Extract All...". If your version of Windows does not 33 | have zip support, you can use the infozip tools available 34 | from www.info-zip.org. 35 | 36 | If you are using the infozip tools (in a command prompt window): 37 | cd your-install-dir 38 | unzip some-package.zip 39 | 40 | 2. Configuring the package. 41 | 42 | The configure script is called "configure" on unix/mac and 43 | "configure.bat" on Windows. It should be run from a command line 44 | after cd'ing to the package directory. 45 | 46 | You can choose whether you want to use the component by including 47 | its source code directly into your project, or build the component 48 | as a dynamic shared library (DLL) that is loaded into the 49 | application at run-time. The latter may be preferable for 50 | technical or licensing (LGPL) reasons. If you want to build a DLL, 51 | run the configure script with the argument "-library". Also see 52 | the note about usage below. 53 | 54 | (Components that are Qt plugins, e.g. styles and image formats, 55 | are by default built as a plugin DLL.) 56 | 57 | The configure script will prompt you in some cases for further 58 | information. Answer these questions and carefully read the license text 59 | before accepting the license conditions. The package cannot be used if 60 | you do not accept the license conditions. 61 | 62 | 3. Building the component and examples (when required). 63 | 64 | If a DLL is to be built, or if you would like to build the 65 | examples, next give the commands 66 | 67 | qmake 68 | make [or nmake if your are using Microsoft Visual C++] 69 | 70 | The example program(s) can be found in the directory called 71 | "examples" or "example". 72 | 73 | Components that are Qt plugins, e.g. styles and image formats, are 74 | ready to be used as soon as they are built, so the rest of this 75 | installation instruction can be skipped. 76 | 77 | 4. Building the Qt Designer plugin (optional). 78 | 79 | Some of the widget components are provided with plugins for Qt 80 | Designer. To build and install the plugin, cd into the 81 | some-package/plugin directory and give the commands 82 | 83 | qmake 84 | make [or nmake if your are using Microsoft Visual C++] 85 | 86 | Restart Qt Designer to make it load the new widget plugin. 87 | 88 | Note: If you are using the built-in Qt Designer from the Qt Visual 89 | Studio Integration, you will need to manually copy the plugin DLL 90 | file, i.e. copy 91 | %QTDIR%\plugins\designer\some-component.dll 92 | to the Qt Visual Studio Integration plugin path, typically: 93 | C:\Program Files\Trolltech\Qt VS Integration\plugins 94 | 95 | Note: If you for some reason are using a Qt Designer that is built 96 | in debug mode, you will need to build the plugin in debug mode 97 | also. Edit the file plugin.pro in the plugin directory, changing 98 | 'release' to 'debug' in the CONFIG line, before running qmake. 99 | 100 | 101 | 102 | Solutions components are intended to be used directly from the package 103 | directory during development, so there is no 'make install' procedure. 104 | 105 | 106 | Using a component in your project 107 | --------------------------------- 108 | 109 | To use this component in your project, add the following line to the 110 | project's .pro file (or do the equivalent in your IDE): 111 | 112 | include(your-install-dir/some-package/src/some-package.pri) 113 | 114 | This adds the package's sources and headers to the SOURCES and HEADERS 115 | project variables respectively (or, if the component has been 116 | configured as a DLL, it adds that library to the LIBS variable), and 117 | updates INCLUDEPATH to contain the package's src 118 | directory. Additionally, the .pri file may include some dependencies 119 | needed by the package. 120 | 121 | To include a header file from the package in your sources, you can now 122 | simply use: 123 | 124 | #include 125 | 126 | or alternatively, in pre-Qt 4 style: 127 | 128 | #include 129 | 130 | Refer to the documentation to see the classes and headers this 131 | components provides. 132 | 133 | 134 | 135 | Install documentation (optional) 136 | -------------------------------- 137 | 138 | The HTML documentation for the package's classes is located in the 139 | your-install-dir/some-package/doc/html/index.html. You can open this 140 | file and read the documentation with any web browser. 141 | 142 | To install the documentation into Qt Assistant (for Qt version 4.4 and 143 | later): 144 | 145 | 1. In Assistant, open the Edit->Preferences dialog and choose the 146 | Documentation tab. Click the Add... button and select the file 147 | your-install-dir/some-package/doc/html/some-package.qch 148 | 149 | For Qt versions prior to 4.4, do instead the following: 150 | 151 | 1. The directory your-install-dir/some-package/doc/html contains a 152 | file called some-package.dcf. Execute the following commands in a 153 | shell, command prompt or terminal window: 154 | 155 | cd your-install-dir/some-package/doc/html/ 156 | assistant -addContentFile some-package.dcf 157 | 158 | The next time you start Qt Assistant, you can access the package's 159 | documentation. 160 | 161 | 162 | Removing the documentation from assistant 163 | ----------------------------------------- 164 | 165 | If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later: 166 | 167 | 1. In Assistant, open the Edit->Preferences dialog and choose the 168 | Documentation tab. In the list of Registered Documentation, select 169 | the item com.nokia.qtsolutions.some-package_version, and click 170 | the Remove button. 171 | 172 | For Qt versions prior to 4.4, do instead the following: 173 | 174 | 1. The directory your-install-dir/some-package/doc/html contains a 175 | file called some-package.dcf. Execute the following commands in a 176 | shell, command prompt or terminal window: 177 | 178 | cd your-install-dir/some-package/doc/html/ 179 | assistant -removeContentFile some-package.dcf 180 | 181 | 182 | 183 | Using the component as a DLL 184 | ---------------------------- 185 | 186 | 1. Normal components 187 | 188 | The shared library (DLL) is built and placed in the 189 | some-package/lib directory. It is intended to be used directly 190 | from there during development. When appropriate, both debug and 191 | release versions are built, since the run-time linker will in some 192 | cases refuse to load a debug-built DLL into a release-built 193 | application or vice versa. 194 | 195 | The following steps are taken by default to help the dynamic 196 | linker to locate the DLL at run-time (during development): 197 | 198 | Unix: The some-package.pri file will add linker instructions to 199 | add the some-package/lib directory to the rpath of the 200 | executable. (When distributing, or if your system does not support 201 | rpath, you can copy the shared library to another place that is 202 | searched by the dynamic linker, e.g. the "lib" directory of your 203 | Qt installation.) 204 | 205 | Mac: The full path to the library is hardcoded into the library 206 | itself, from where it is copied into the executable at link time, 207 | and ready by the dynamic linker at run-time. (When distributing, 208 | you will want to edit these hardcoded paths in the same way as for 209 | the Qt DLLs. Refer to the document "Deploying an Application on 210 | Mac OS X" in the Qt Reference Documentation.) 211 | 212 | Windows: the .dll file(s) are copied into the "bin" directory of 213 | your Qt installation. The Qt installation will already have set up 214 | that directory to be searched by the dynamic linker. 215 | 216 | 217 | 2. Plugins 218 | 219 | For Qt Solutions plugins (e.g. image formats), both debug and 220 | release versions of the plugin are built by default when 221 | appropriate, since in some cases the release Qt library will not 222 | load a debug plugin, and vice versa. The plugins are automatically 223 | copied into the plugins directory of your Qt installation when 224 | built, so no further setup is required. 225 | 226 | Plugins may also be built statically, i.e. as a library that will be 227 | linked into your application executable, and so will not need to 228 | be redistributed as a separate plugin DLL to end users. Static 229 | building is required if Qt itself is built statically. To do it, 230 | just add "static" to the CONFIG variable in the plugin/plugin.pro 231 | file before building. Refer to the "Static Plugins" section in the 232 | chapter "How to Create Qt Plugins" for explanation of how to use a 233 | static plugin in your application. The source code of the example 234 | program(s) will also typically contain the relevant instructions 235 | as comments. 236 | 237 | 238 | 239 | Uninstalling 240 | ------------ 241 | 242 | The following command will remove any fils that have been 243 | automatically placed outside the package directory itself during 244 | installation and building 245 | 246 | make distclean [or nmake if your are using Microsoft Visual C++] 247 | 248 | If Qt Assistant documentation or Qt Designer plugins have been 249 | installed, they can be uninstalled manually, ref. above. 250 | 251 | 252 | Enjoy! :) 253 | 254 | - The Qt Solutions Team. 255 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/README.TXT: -------------------------------------------------------------------------------- 1 | Qt Solutions Component: Service 2 | 3 | The QtService component is useful for developing Windows services 4 | and Unix daemons. 5 | 6 | 7 | 8 | Version history: 9 | 10 | 2.0: - Reimplemented for Qt 4 with improved API. 11 | 12 | 2.1: - More feedback while installing / uninstalling. 13 | - Unix: Documentation about installing service improved. 14 | - Windows: Added account and password arguments to install(). 15 | - Windows: Report status correcty when stopping through the 16 | controller. 17 | - Windows: Send command IDs correctly. 18 | 19 | 2.2: - Unix: logMessage() works properly with '%' characters. 20 | - Windows: Dependency on the QtGui library removed. 21 | 22 | 2.3: - Unix: Using QProcess in a service no longer leaves zombie 23 | processes around. 24 | - Windows: Place controller's receiver object in proper thread. 25 | (makes QtService work with Qt 4.2). 26 | - Compilation fixes for MinGW. 27 | 28 | 2.4: - Windows: Do net require Administrator privileges just to 29 | start service. 30 | - Improved command-line help text. 31 | - Document the caveats of using GUI services, including that Vista 32 | does not support it. 33 | - Added -w(ait) argument to controller example 34 | - Added doc about usage on Windows Vista 35 | - Windows: Fix: GUI services would terminate on logoff. 36 | - Windows: internal redesign of threading. Fixes issue where 37 | signal/slot connections created before start() would not work. 38 | Fixes problem/warning about QApplication not created in main 39 | thread. 40 | 41 | 2.5: - Fixes: crash on OS X Leopard. Note: On mac, main() will now 42 | be executed both in the starting process and in the forked, 43 | service process. This is consistent with the behaviour on Windows. 44 | - Fixes: Improved logging of multi-line messages on Unix. 45 | 46 | 2.6: - Misc. minor fixes. 47 | - LGPL release. 48 | 49 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/buildlib/buildlib.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE=lib 2 | CONFIG += qt dll qtservice-buildlib 3 | mac:CONFIG += absolute_library_soname 4 | win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all 5 | include(../src/qtservice.pri) 6 | TARGET = $$QTSERVICE_LIBNAME 7 | DESTDIR = $$QTSERVICE_LIBDIR 8 | win32 { 9 | DLLDESTDIR = $$[QT_INSTALL_BINS] 10 | QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSERVICE_LIBNAME}.dll 11 | } 12 | target.path = $$DESTDIR 13 | INSTALLS += target 14 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/common.pri: -------------------------------------------------------------------------------- 1 | exists(config.pri):infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtservice-uselib 2 | TEMPLATE += fakelib 3 | QTSERVICE_LIBNAME = QtSolutions_Service-head 4 | CONFIG(debug, debug|release) { 5 | mac:QTSERVICE_LIBNAME = $$member(QTSERVICE_LIBNAME, 0)_debug 6 | else:win32:QTSERVICE_LIBNAME = $$member(QTSERVICE_LIBNAME, 0)d 7 | } 8 | TEMPLATE -= fakelib 9 | QTSERVICE_LIBDIR = $$PWD/lib 10 | unix:qtservice-uselib:!qtservice-buildlib:QMAKE_RPATHDIR += $$QTSERVICE_LIBDIR 11 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "x$1" != "x" -a "x$1" != "x-library" ]; then 4 | echo "Usage: $0 [-library]" 5 | echo 6 | echo "-library: Build the component as a dynamic library (DLL). Default is to" 7 | echo " include the component source code directly in the application." 8 | echo 9 | exit 0 10 | fi 11 | 12 | rm -f config.pri 13 | if [ "x$1" = "x-library" ]; then 14 | echo "Configuring to build this component as a dynamic library." 15 | echo "SOLUTIONS_LIBRARY = yes" > config.pri 16 | fi 17 | 18 | echo 19 | echo "This component is now configured." 20 | echo 21 | echo "To build the component library (if requested) and example(s)," 22 | echo "run qmake and your make command." 23 | echo 24 | echo "To remove or reconfigure, run make distclean." 25 | echo 26 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/configure.bat: -------------------------------------------------------------------------------- 1 | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 2 | :: 3 | :: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | :: Contact: http://www.qt-project.org/legal 5 | :: 6 | :: This file is part of the Qt Solutions component. 7 | :: 8 | :: $QT_BEGIN_LICENSE:BSD$ 9 | :: You may use this file under the terms of the BSD license as follows: 10 | :: 11 | :: "Redistribution and use in source and binary forms, with or without 12 | :: modification, are permitted provided that the following conditions are 13 | :: met: 14 | :: * Redistributions of source code must retain the above copyright 15 | :: notice, this list of conditions and the following disclaimer. 16 | :: * Redistributions in binary form must reproduce the above copyright 17 | :: notice, this list of conditions and the following disclaimer in 18 | :: the documentation and/or other materials provided with the 19 | :: distribution. 20 | :: * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | :: of its contributors may be used to endorse or promote products derived 22 | :: from this software without specific prior written permission. 23 | :: 24 | :: 25 | :: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | :: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | :: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | :: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | :: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | :: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | :: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | :: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | :: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | :: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | :: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | :: 37 | :: $QT_END_LICENSE$ 38 | :: 39 | ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 40 | 41 | @echo off 42 | 43 | rem 44 | rem "Main" 45 | rem 46 | 47 | if not "%1"=="" ( 48 | if not "%1"=="-library" ( 49 | call :PrintUsage 50 | goto EOF 51 | ) 52 | ) 53 | 54 | if exist config.pri. del config.pri 55 | if "%1"=="-library" ( 56 | echo Configuring to build this component as a dynamic library. 57 | echo SOLUTIONS_LIBRARY = yes > config.pri 58 | ) 59 | 60 | echo . 61 | echo This component is now configured. 62 | echo . 63 | echo To build the component library (if requested) and example(s), 64 | echo run qmake and your make or nmake command. 65 | echo . 66 | echo To remove or reconfigure, run make (nmake) distclean. 67 | echo . 68 | goto EOF 69 | 70 | :PrintUsage 71 | echo Usage: configure.bat [-library] 72 | echo . 73 | echo -library: Build the component as a dynamic library (DLL). Default is to 74 | echo include the component source directly in the application. 75 | echo A DLL may be preferable for technical or licensing (LGPL) reasons. 76 | echo . 77 | goto EOF 78 | 79 | 80 | :EOF 81 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/classic.css: -------------------------------------------------------------------------------- 1 | BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { 2 | font-family: Arial, Geneva, Helvetica, sans-serif; 3 | } 4 | H1 { 5 | text-align: center; 6 | font-size: 160%; 7 | } 8 | H2 { 9 | font-size: 120%; 10 | } 11 | H3 { 12 | font-size: 100%; 13 | } 14 | 15 | h3.fn,span.fn 16 | { 17 | background-color: #eee; 18 | border-width: 1px; 19 | border-style: solid; 20 | border-color: #ddd; 21 | font-weight: bold; 22 | padding: 6px 0px 6px 10px; 23 | margin: 42px 0px 0px 0px; 24 | } 25 | 26 | hr { 27 | border: 0; 28 | color: #a0a0a0; 29 | background-color: #ccc; 30 | height: 1px; 31 | width: 100%; 32 | text-align: left; 33 | margin: 34px 0px 34px 0px; 34 | } 35 | 36 | table.valuelist { 37 | border-width: 1px 1px 1px 1px; 38 | border-style: solid; 39 | border-color: #dddddd; 40 | border-collapse: collapse; 41 | background-color: #f0f0f0; 42 | } 43 | 44 | table.indextable { 45 | border-width: 1px 1px 1px 1px; 46 | border-style: solid; 47 | border-collapse: collapse; 48 | background-color: #f0f0f0; 49 | border-color:#555; 50 | font-size: 100%; 51 | } 52 | 53 | table td.largeindex { 54 | border-width: 1px 1px 1px 1px; 55 | border-collapse: collapse; 56 | background-color: #f0f0f0; 57 | border-color:#555; 58 | font-size: 120%; 59 | } 60 | 61 | table.valuelist th { 62 | border-width: 1px 1px 1px 2px; 63 | padding: 4px; 64 | border-style: solid; 65 | border-color: #666; 66 | color:white; 67 | background-color:#666; 68 | } 69 | 70 | th.titleheader { 71 | border-width: 1px 0px 1px 0px; 72 | padding: 2px; 73 | border-style: solid; 74 | border-color: #666; 75 | color:white; 76 | background-color:#555; 77 | background-image:url('images/gradient.png')}; 78 | background-repeat: repeat-x; 79 | font-size: 100%; 80 | } 81 | 82 | 83 | th.largeheader { 84 | border-width: 1px 0px 1px 0px; 85 | padding: 4px; 86 | border-style: solid; 87 | border-color: #444; 88 | color:white; 89 | background-color:#555555; 90 | font-size: 120%; 91 | } 92 | 93 | p { 94 | 95 | margin-left: 4px; 96 | margin-top: 8px; 97 | margin-bottom: 8px; 98 | } 99 | 100 | a:link 101 | { 102 | color: #0046ad; 103 | text-decoration: none 104 | } 105 | 106 | a:visited 107 | { 108 | color: #672967; 109 | text-decoration: none 110 | } 111 | 112 | a.obsolete 113 | { 114 | color: #661100; 115 | text-decoration: none 116 | } 117 | 118 | a.compat 119 | { 120 | color: #661100; 121 | text-decoration: none 122 | } 123 | 124 | a.obsolete:visited 125 | { 126 | color: #995500; 127 | text-decoration: none 128 | } 129 | 130 | a.compat:visited 131 | { 132 | color: #995500; 133 | text-decoration: none 134 | } 135 | 136 | body 137 | { 138 | background: #ffffff; 139 | color: black 140 | } 141 | 142 | table.generic, table.annotated 143 | { 144 | border-width: 1px; 145 | border-color:#bbb; 146 | border-style:solid; 147 | border-collapse:collapse; 148 | } 149 | 150 | table td.memItemLeft { 151 | width: 180px; 152 | padding: 2px 0px 0px 8px; 153 | margin: 4px; 154 | border-width: 1px; 155 | border-color: #E0E0E0; 156 | border-style: none; 157 | font-size: 100%; 158 | white-space: nowrap 159 | } 160 | 161 | table td.memItemRight { 162 | padding: 2px 8px 0px 8px; 163 | margin: 4px; 164 | border-width: 1px; 165 | border-color: #E0E0E0; 166 | border-style: none; 167 | font-size: 100%; 168 | } 169 | 170 | table tr.odd { 171 | background: #f0f0f0; 172 | color: black; 173 | } 174 | 175 | table tr.even { 176 | background: #e4e4e4; 177 | color: black; 178 | } 179 | 180 | table.annotated th { 181 | padding: 3px; 182 | text-align: left 183 | } 184 | 185 | table.annotated td { 186 | padding: 3px; 187 | } 188 | 189 | table tr pre 190 | { 191 | padding-top: 0px; 192 | padding-bottom: 0px; 193 | padding-left: 0px; 194 | padding-right: 0px; 195 | border: none; 196 | background: none 197 | } 198 | 199 | tr.qt-style 200 | { 201 | background: #96E066; 202 | color: black 203 | } 204 | 205 | body pre 206 | { 207 | padding: 0.2em; 208 | border: #e7e7e7 1px solid; 209 | background: #f1f1f1; 210 | color: black 211 | } 212 | 213 | table tr.qt-code pre 214 | { 215 | padding: 0.2em; 216 | border: #e7e7e7 1px solid; 217 | background: #f1f1f1; 218 | color: black 219 | } 220 | 221 | span.preprocessor, span.preprocessor a 222 | { 223 | color: darkblue; 224 | } 225 | 226 | span.comment 227 | { 228 | color: darkred; 229 | font-style: italic 230 | } 231 | 232 | span.string,span.char 233 | { 234 | color: darkgreen; 235 | } 236 | 237 | .title 238 | { 239 | text-align: center 240 | } 241 | 242 | .subtitle 243 | { 244 | font-size: 0.8em 245 | } 246 | 247 | .small-subtitle 248 | { 249 | font-size: 0.65em 250 | } 251 | 252 | .qmlitem { 253 | padding: 0; 254 | } 255 | 256 | .qmlname { 257 | white-space: nowrap; 258 | } 259 | 260 | .qmltype { 261 | text-align: center; 262 | font-size: 160%; 263 | } 264 | 265 | .qmlproto { 266 | background-color: #eee; 267 | border-width: 1px; 268 | border-style: solid; 269 | border-color: #ddd; 270 | font-weight: bold; 271 | padding: 6px 10px 6px 10px; 272 | margin: 42px 0px 0px 0px; 273 | } 274 | 275 | .qmlreadonly { 276 | float: right; 277 | color: red 278 | } 279 | 280 | .qmldoc { 281 | } 282 | 283 | *.qmlitem p { 284 | } 285 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestSignalTrigger/TestQtService/qtservice/doc/html/images/qt-logo.png -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Service 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

Service
16 |

17 | 18 |

Description

19 |

The QtService component is useful for developing Windows services and Unix daemons.

20 |

The project provides a QtService template class that can be used to implement service applications, and a QtServiceController class to control a service.

21 |

On Windows systems the implementation uses the Service Control Manager.

22 |

On Unix systems services are implemented as daemons.

23 | 24 |

Classes

25 | 30 | 31 |

Examples

32 | 37 | 38 |

Tested platforms

39 |
    40 |
  • Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
  • 41 |
  • Qt 4.4, 4.5 / Linux / gcc
  • 42 |
  • Qt 4.4, 4.5 / MacOS X 10.5 / gcc
  • 43 |
44 |


45 | 46 | 47 | 48 | 49 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
50 | 51 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice-example-controller.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | A simple Service Controller 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

A simple Service Controller
16 |

17 |

It is a very simple implementation of universal command-line controller. This controller can install and control any service written using QtService component. It demonstrates how to use QtServiceController class. On Windows, this is an alternative to using the "Services" Administrative Tool or the built-in sc.exe command-line tool to control services.

18 |

A note about services on Windows Vista: Installing/uninstalling and starting/stopping services requires security privileges. The simplest way to achieve this is to set the "Run as Administrator" property on the executable (right-click the executable file, select Properties, and choose the Compatibilty tab in the Properties dialog). This applies even if you are logged in as Administrator. Also, the command-line shell should be started with "Run as Administrator". Note that the service itself does not need special privileges to run. Only if you want the service to be able to install itself (the -i option) or similar, then the service will need to be run as Administrator. Otherwise, the recommended procedure is to use a controller such as this example and/or the "Services" Administrative Tool to manage the service.

19 |

A usability hint: in some circumstances, e.g. when running this example on Windows Vista with the "Run as Administrator" property set, output will be sent to a shell window which will close immediately upon termination, not leaving the user enough time to read the output. In such cases, append the -w(ait) argument, which will make the controller wait for a keypress before terminating.

20 |

Here is the complete source code:

21 |
 /****************************************************************************
 22 |  **
 23 |  ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 24 |  ** Contact: http://www.qt-project.org/legal
 25 |  **
 26 |  ** This file is part of the Qt Solutions component.
 27 |  **
 28 |  ** You may use this file under the terms of the BSD license as follows:
 29 |  **
 30 |  ** "Redistribution and use in source and binary forms, with or without
 31 |  ** modification, are permitted provided that the following conditions are
 32 |  ** met:
 33 |  **   * Redistributions of source code must retain the above copyright
 34 |  **     notice, this list of conditions and the following disclaimer.
 35 |  **   * Redistributions in binary form must reproduce the above copyright
 36 |  **     notice, this list of conditions and the following disclaimer in
 37 |  **     the documentation and/or other materials provided with the
 38 |  **     distribution.
 39 |  **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 40 |  **     the names of its contributors may be used to endorse or promote
 41 |  **     products derived from this software without specific prior written
 42 |  **     permission.
 43 |  **
 44 |  ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 45 |  ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 46 |  ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 47 |  ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 48 |  ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 49 |  ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 50 |  ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 51 |  ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 52 |  ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 53 |  ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 54 |  ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 55 |  **
 56 |  ****************************************************************************/
 57 | 
 58 |  #include <QtCore/QStringList>
 59 |  #include <QtCore/QDir>
 60 |  #include <QtCore/QSettings>
 61 |  #include "qtservice.h"
 62 | 
 63 |  int processArgs(int argc, char **argv)
 64 |  {
 65 |      if (argc > 2) {
 66 |          QString arg1(argv[1]);
 67 |          if (arg1 == QLatin1String("-i") ||
 68 |              arg1 == QLatin1String("-install")) {
 69 |              if (argc > 2) {
 70 |                  QString account;
 71 |                  QString password;
 72 |                  QString path(argv[2]);
 73 |                  if (argc > 3)
 74 |                      account = argv[3];
 75 |                  if (argc > 4)
 76 |                      password = argv[4];
 77 |                  printf("The service %s installed.\n",
 78 |                         (QtServiceController::install(path, account, password) ? "was" : "was not"));
 79 |                  return 0;
 80 |              }
 81 |          } else {
 82 |              QString serviceName(argv[1]);
 83 |              QtServiceController controller(serviceName);
 84 |              QString option(argv[2]);
 85 |              if (option == QLatin1String("-u") ||
 86 |                  option == QLatin1String("-uninstall")) {
 87 |                  printf("The service \"%s\" %s uninstalled.\n",
 88 |                              controller.serviceName().toLatin1().constData(),
 89 |                              (controller.uninstall() ? "was" : "was not"));
 90 |                  return 0;
 91 |              } else if (option == QLatin1String("-s") ||
 92 |                         option == QLatin1String("-start")) {
 93 |                  QStringList args;
 94 |                  for (int i = 3; i < argc; ++i)
 95 |                      args.append(QString::fromLocal8Bit(argv[i]));
 96 |                  printf("The service \"%s\" %s started.\n",
 97 |                         controller.serviceName().toLatin1().constData(),
 98 |                              (controller.start(args) ? "was" : "was not"));
 99 |                  return 0;
100 |              } else if (option == QLatin1String("-t") ||
101 |                         option == QLatin1String("-terminate")) {
102 |                  printf("The service \"%s\" %s stopped.\n",
103 |                         controller.serviceName().toLatin1().constData(),
104 |                         (controller.stop() ? "was" : "was not"));
105 |                  return 0;
106 |              } else if (option == QLatin1String("-p") ||
107 |                      option == QLatin1String("-pause")) {
108 |                  printf("The service \"%s\" %s paused.\n",
109 |                         controller.serviceName().toLatin1().constData(),
110 |                         (controller.pause() ? "was" : "was not"));
111 |                  return 0;
112 |              } else if (option == QLatin1String("-r") ||
113 |                         option == QLatin1String("-resume")) {
114 |                  printf("The service \"%s\" %s resumed.\n",
115 |                         controller.serviceName().toLatin1().constData(),
116 |                         (controller.resume() ? "was" : "was not"));
117 |                  return 0;
118 |              } else if (option == QLatin1String("-c") ||
119 |                         option == QLatin1String("-command")) {
120 |                  if (argc > 3) {
121 |                      QString codestr(argv[3]);
122 |                      int code = codestr.toInt();
123 |                      printf("The command %s sent to the service \"%s\".\n",
124 |                             (controller.sendCommand(code) ? "was" : "was not"),
125 |                             controller.serviceName().toLatin1().constData());
126 |                      return 0;
127 |                  }
128 |              } else if (option == QLatin1String("-v") ||
129 |                      option == QLatin1String("-version")) {
130 |                  bool installed = controller.isInstalled();
131 |                  printf("The service\n"
132 |                          "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData());
133 |                  printf("is %s", (installed ? "installed" : "not installed"));
134 |                  printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running"));
135 |                  if (installed) {
136 |                      printf("path: %s\n", controller.serviceFilePath().toLatin1().data());
137 |                      printf("description: %s\n", controller.serviceDescription().toLatin1().data());
138 |                      printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual");
139 |                  }
140 |                  return 0;
141 |              }
142 |          }
143 |      }
144 |      printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n"
145 |              "\t-i(nstall) PATH\t: Install the service\n"
146 |              "\t-v(ersion)\t: Print status of the service\n"
147 |              "\t-u(ninstall)\t: Uninstall the service\n"
148 |              "\t-s(tart)\t: Start the service\n"
149 |              "\t-t(erminate)\t: Stop the service\n"
150 |              "\t-p(ause)\t: Pause the service\n"
151 |              "\t-r(esume)\t: Resume the service\n"
152 |              "\t-c(ommand) CODE\t: Send a command to the service\n"
153 |              "\t-h(elp)\t\t: Print this help info\n"
154 |              "\t-w(ait)\t\t: Wait for keypress when done\n");
155 |      return 0;
156 |  }
157 | 
158 |  int main(int argc, char **argv)
159 |  {
160 |  #if !defined(Q_OS_WIN)
161 |      // QtService stores service settings in SystemScope, which normally require root privileges.
162 |      // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
163 |      QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
164 |      qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
165 |  #endif
166 | 
167 |      int result = processArgs(argc, argv);
168 | 
169 |      if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") ||
170 |          QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) {
171 |          printf("\nPress Enter to continue...");
172 |          QFile input;
173 |          input.open(stdin, QIODevice::ReadOnly);
174 |          input.readLine();
175 |          printf("\n");
176 |      }
177 | 
178 |      return result;
179 |  }
180 |


181 | 182 | 183 | 184 | 185 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
186 | 187 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice-example-interactive.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | An Interactive Service 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

An Interactive Service
16 |

17 |

This example implements a service with a simple user interface.

18 |

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes.

19 |

However, although not recommended in the general case, in certain circumstances a service may provide a GUI itself. This is typically only possible if the service process is run as the same user as the one that is logged in, so that it will have access to the screen. Note however that on Windows Vista, service GUIs are not allowed at all, since services run in a diferent session than all user sessions, for security reasons.

20 |

This example demonstrates how to subclass the QtService class, the use of start(), stop(), pause(), resume(), and how to use processCommand() to receive control commands while running.

21 |

Here is the complete source code:

22 |
 /****************************************************************************
 23 |  **
 24 |  ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 25 |  ** Contact: http://www.qt-project.org/legal
 26 |  **
 27 |  ** This file is part of the Qt Solutions component.
 28 |  **
 29 |  ** You may use this file under the terms of the BSD license as follows:
 30 |  **
 31 |  ** "Redistribution and use in source and binary forms, with or without
 32 |  ** modification, are permitted provided that the following conditions are
 33 |  ** met:
 34 |  **   * Redistributions of source code must retain the above copyright
 35 |  **     notice, this list of conditions and the following disclaimer.
 36 |  **   * Redistributions in binary form must reproduce the above copyright
 37 |  **     notice, this list of conditions and the following disclaimer in
 38 |  **     the documentation and/or other materials provided with the
 39 |  **     distribution.
 40 |  **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 41 |  **     the names of its contributors may be used to endorse or promote
 42 |  **     products derived from this software without specific prior written
 43 |  **     permission.
 44 |  **
 45 |  ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 46 |  ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 47 |  ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 48 |  ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 49 |  ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 50 |  ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 51 |  ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 52 |  ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 53 |  ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 54 |  ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 55 |  ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 56 |  **
 57 |  ****************************************************************************/
 58 | 
 59 |  #include <QtGui/QApplication>
 60 |  #include <QtGui/QDesktopWidget>
 61 |  #include <QtGui/QLabel>
 62 |  #include <QtCore/QDir>
 63 |  #include <QtCore/QSettings>
 64 |  #include "qtservice.h"
 65 | 
 66 |  class InteractiveService : public QtService<QApplication>
 67 |  {
 68 |  public:
 69 |      InteractiveService(int argc, char **argv);
 70 |      ~InteractiveService();
 71 | 
 72 |  protected:
 73 | 
 74 |      void start();
 75 |      void stop();
 76 |      void pause();
 77 |      void resume();
 78 |      void processCommand(int code);
 79 | 
 80 |  private:
 81 |      QLabel *gui;
 82 |  };
 83 | 
 84 |  InteractiveService::InteractiveService(int argc, char **argv)
 85 |      : QtService<QApplication>(argc, argv, "Qt Interactive Service"), gui(0)
 86 |  {
 87 |      setServiceDescription("A Qt service with user interface.");
 88 |      setServiceFlags(QtServiceBase::CanBeSuspended);
 89 |  }
 90 | 
 91 |  InteractiveService::~InteractiveService()
 92 |  {
 93 |  }
 94 | 
 95 |  void InteractiveService::start()
 96 |  {
 97 |  #if defined(Q_OS_WIN)
 98 |      if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) &&
 99 |          (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) {
100 |          logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error );
101 |          return;
102 |      }
103 |  #endif
104 | 
105 |      qApp->setQuitOnLastWindowClosed(false);
106 | 
107 |      gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
108 |      gui->move(QApplication::desktop()->availableGeometry().topLeft());
109 |      gui->show();
110 |  }
111 | 
112 |  void InteractiveService::stop()
113 |  {
114 |      delete gui;
115 |  }
116 | 
117 |  void InteractiveService::pause()
118 |  {
119 |      if (gui)
120 |          gui->hide();
121 |  }
122 | 
123 |  void InteractiveService::resume()
124 |  {
125 |      if (gui)
126 |          gui->show();
127 |  }
128 | 
129 |  void InteractiveService::processCommand(int code)
130 |  {
131 |      gui->setText("Command code " + QString::number(code));
132 |      gui->adjustSize();
133 |  }
134 | 
135 |  int main(int argc, char **argv)
136 |  {
137 |  #if !defined(Q_OS_WIN)
138 |      // QtService stores service settings in SystemScope, which normally require root privileges.
139 |      // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
140 |      QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
141 |      qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
142 |  #endif
143 |      InteractiveService service(argc, argv);
144 |      return service.exec();
145 |  }
146 |


147 | 148 | 149 | 150 | 151 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
152 | 153 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice-example-server.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | A simple HTTP Server 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

A simple HTTP Server
16 |

17 |

It is a very simple implementation of a HTTP daemon that listens on chosen port (defaultly 8080) and sends back a simple HTML page back for every GET request it gets. After sending the page, it closes the connection.

18 |
 // HttpDaemon is the the class that implements the simple HTTP server.
 19 |  class HttpDaemon : public QTcpServer
 20 |  {
 21 |      Q_OBJECT
 22 |  public:
 23 |      HttpDaemon(quint16 port, QObject* parent = 0)
 24 |          : QTcpServer(parent), disabled(false)
 25 |      {
 26 |          listen(QHostAddress::Any, port);
 27 |      }
 28 | 
 29 |      void incomingConnection(int socket)
 30 |      {
 31 |          if (disabled)
 32 |              return;
 33 | 
 34 |          // When a new client connects, the server constructs a QTcpSocket and all
 35 |          // communication with the client is done over this QTcpSocket. QTcpSocket
 36 |          // works asynchronously, this means that all the communication is done
 37 |          // in the two slots readClient() and discardClient().
 38 |          QTcpSocket* s = new QTcpSocket(this);
 39 |          connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
 40 |          connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
 41 |          s->setSocketDescriptor(socket);
 42 | 
 43 |          QtServiceBase::instance()->logMessage("New Connection");
 44 |      }
 45 | 
 46 |      void pause()
 47 |      {
 48 |          disabled = true;
 49 |      }
 50 | 
 51 |      void resume()
 52 |      {
 53 |          disabled = false;
 54 |      }
 55 | 
 56 |  private slots:
 57 |      void readClient()
 58 |      {
 59 |          if (disabled)
 60 |              return;
 61 | 
 62 |          // This slot is called when the client sent data to the server. The
 63 |          // server looks if it was a get request and sends a very simple HTML
 64 |          // document back.
 65 |          QTcpSocket* socket = (QTcpSocket*)sender();
 66 |          if (socket->canReadLine()) {
 67 |              QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
 68 |              if (tokens[0] == "GET") {
 69 |                  QTextStream os(socket);
 70 |                  os.setAutoDetectUnicode(true);
 71 |                  os << "HTTP/1.0 200 Ok\r\n"
 72 |                      "Content-Type: text/html; charset=\"utf-8\"\r\n"
 73 |                      "\r\n"
 74 |                      "<h1>Nothing to see here</h1>\n"
 75 |                      << QDateTime::currentDateTime().toString() << "\n";
 76 |                  socket->close();
 77 | 
 78 |                  QtServiceBase::instance()->logMessage("Wrote to client");
 79 | 
 80 |                  if (socket->state() == QTcpSocket::UnconnectedState) {
 81 |                      delete socket;
 82 |                      QtServiceBase::instance()->logMessage("Connection closed");
 83 |                  }
 84 |              }
 85 |          }
 86 |      }
 87 |      void discardClient()
 88 |      {
 89 |          QTcpSocket* socket = (QTcpSocket*)sender();
 90 |          socket->deleteLater();
 91 | 
 92 |          QtServiceBase::instance()->logMessage("Connection closed");
 93 |      }
 94 | 
 95 |  private:
 96 |      bool disabled;
 97 |  };
98 |

The server implementation uses the QtService::logMessage() function to send messages and status reports to the system event log. The server also supports a paused state in which case incoming requests are ignored.

99 |

The HttpService class subclasses QtService to implement the service functionality.

100 |
 class HttpService : public QtService<QCoreApplication>
101 |  {
102 |  public:
103 |      HttpService(int argc, char **argv)
104 |          : QtService<QCoreApplication>(argc, argv, "Qt HTTP Daemon")
105 |      {
106 |          setServiceDescription("A dummy HTTP service implemented with Qt");
107 |          setServiceFlags(QtServiceBase::CanBeSuspended);
108 |      }
109 |

The constructor calls the QtService constructor instantiated with QCoreApplication since our service will not use GUI. The first two parameters of our constructor are passed to QtService. The last parameter, "Qt HTTP Daemon", is the name of the service.

110 |
 protected:
111 |      void start()
112 |      {
113 |          QCoreApplication *app = application();
114 | 
115 |          quint16 port = (app->argc() > 1) ?
116 |                  QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080;
117 |          daemon = new HttpDaemon(port, app);
118 | 
119 |          if (!daemon->isListening()) {
120 |              logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error);
121 |              app->quit();
122 |          }
123 |      }
124 |

The implementation of start() first checks if the user passed a port number. If yes that port is used by server to listen on. Otherwise default 8080 port is used. Then creates an instance of the HTTP server using operator new, passing the application object as the parent to ensure that the object gets destroyed.

125 |
     void pause()
126 |      {
127 |          daemon->pause();
128 |      }
129 | 
130 |      void resume()
131 |      {
132 |          daemon->resume();
133 |      }
134 | 
135 |  private:
136 |      HttpDaemon *daemon;
137 |  };
138 |

The implementations of pause() and resume() forward the request to the server object.

139 |
 #include "main.moc"
140 | 
141 |  int main(int argc, char **argv)
142 |  {
143 |  #if !defined(Q_OS_WIN)
144 |      // QtService stores service settings in SystemScope, which normally require root privileges.
145 |      // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
146 |      QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
147 |      qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
148 |  #endif
149 |      HttpService service(argc, argv);
150 |      return service.exec();
151 |  }
152 |

The main entry point function creates the service object and uses the exec() function to execute the service.

153 |


154 | 155 | 156 | 157 | 158 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
159 | 160 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice-members.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | List of All Members for QtService 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

List of All Members for QtService

16 |

This is the complete list of members for QtService, including inherited members.

17 |

18 | 45 |
44 |

46 |


47 | 48 | 49 | 50 | 51 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
52 | 53 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice.dcf: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | QtService 6 | application 7 | createApplication 8 | executeApplication 9 |
10 |
11 |
12 | QtServiceBase 13 | MessageType 14 | QtServiceBase::Warning 15 | QtServiceBase::Error 16 | QtServiceBase::Success 17 | QtServiceBase::Information 18 | ServiceFlag 19 | ServiceFlags 20 | QtServiceBase::Default 21 | QtServiceBase::NeedsStopOnShutdown 22 | QtServiceBase::CannotBeStopped 23 | QtServiceBase::CanBeSuspended 24 | createApplication 25 | exec 26 | executeApplication 27 | instance 28 | logMessage 29 | pause 30 | processCommand 31 | resume 32 | serviceDescription 33 | serviceFlags 34 | serviceName 35 | setServiceDescription 36 | setServiceFlags 37 | setStartupType 38 | start 39 | startupType 40 | stop 41 |
42 |
43 |
44 | QtServiceController 45 | StartupType 46 | QtServiceController::AutoStartup 47 | QtServiceController::ManualStartup 48 | install 49 | isInstalled 50 | isRunning 51 | pause 52 | resume 53 | sendCommand 54 | serviceDescription 55 | serviceFilePath 56 | serviceName 57 | start 58 | startupType 59 | stop 60 | uninstall 61 |
62 |
63 |
64 |
65 |
66 | A simple HTTP Server 67 |
68 |
69 | A simple Service Controller 70 |
71 |
72 | An Interactive Service 73 |
74 |
75 | Service 76 |
77 |
78 |
79 | 80 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | QtService Class Reference 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

QtService Class Reference

16 |

The QtService is a convenient template class that allows you to create a service for a particular application type. More...

17 |
 #include <QtService>

Inherits QtServiceBase.

18 | 21 |
22 | 23 |

Public Functions

24 | 25 | 26 | 27 |
QtService ( int argc, char ** argv, const QString & name )
~QtService ()
28 | 31 |
32 | 33 |

Protected Functions

34 | 35 | 36 |
Application * application () const
37 |
38 | 39 |

Reimplemented Protected Functions

40 | 41 | 42 | 43 |
virtual void createApplication ( int & argc, char ** argv )
virtual int executeApplication ()
44 | 47 |

Additional Inherited Members

48 | 51 | 52 |
53 |

Detailed Description

54 |

The QtService is a convenient template class that allows you to create a service for a particular application type.

55 |

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

56 |

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

57 |

Note: On Unix systems, this class relies on facilities provided by the QtNetwork module, provided as part of the Qt Open Source Edition and certain Qt Commercial Editions.

58 |

The QtService class functionality is inherited from QtServiceBase, but in addition the QtService class binds an instance of QtServiceBase with an application type.

59 |

Typically, you will create a service by subclassing the QtService template class. For example:

60 |
 class MyService : public QtService<QApplication>
 61 |  {
 62 |  public:
 63 |      MyService(int argc, char **argv);
 64 |      ~MyService();
 65 | 
 66 |  protected:
 67 |      void start();
 68 |      void stop();
 69 |      void pause();
 70 |      void resume();
 71 |      void processCommand(int code);
 72 |  };
73 |

The application type can be QCoreApplication for services without GUI, QApplication for services with GUI or you can use your own custom application type.

74 |

You must reimplement the QtServiceBase::start() function to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

75 |

In addition, you might want to reimplement the QtServiceBase::pause(), QtServiceBase::processCommand(), QtServiceBase::resume() and QtServiceBase::stop() to intervene the service's process on controller requests. You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented.

76 |

Your custom service is typically instantiated in the application's main function. Then the main function will call your service's exec() function, and return the result of that call. For example:

77 |
     int main(int argc, char **argv)
 78 |      {
 79 |          MyService service(argc, argv);
 80 |          return service.exec();
 81 |      }
82 |

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

83 |

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

84 |

See also QtServiceBase and QtServiceController.

85 |
86 |

Member Function Documentation

87 |

QtService::QtService ( int argc, char ** argv, const QString & name )

88 |

Constructs a QtService object called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor.

89 |

There can only be one QtService object in a process.

90 |

See also QtServiceBase().

91 |

QtService::~QtService ()

92 |

Destroys the service object.

93 |

Application * QtService::application () const   [protected]

94 |

Returns a pointer to the application object.

95 |

void QtService::createApplication ( int & argc, char ** argv )   [virtual protected]

96 |

Reimplemented from QtServiceBase::createApplication().

97 |

Creates application object of type Application passing argc and argv to its constructor.

98 |

int QtService::executeApplication ()   [virtual protected]

99 |

Reimplemented from QtServiceBase::executeApplication().

100 |


101 | 102 | 103 | 104 | 105 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
106 | 107 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservice.qhp: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.nokia.qtsolutions.qtservice_head 4 | qdoc 5 | 6 | qt 7 | qtservice 8 | solutions 9 | 10 | 11 | qt 12 | qtservice 13 | solutions 14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | qtservice-example-controller.html 83 | index.html 84 | qtservice-example-server.html 85 | qtservice-example-interactive.html 86 | qtservicebase.html 87 | qtservice.html 88 | qtservicecontroller.html 89 | classic.css 90 | images/qt-logo.png 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservicebase-members.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | List of All Members for QtServiceBase 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

List of All Members for QtServiceBase

16 |

This is the complete list of members for QtServiceBase, including inherited members.

17 |

18 | 44 |
43 |

45 |


46 | 47 | 48 | 49 | 50 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
51 | 52 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/html/qtservicecontroller-members.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | List of All Members for QtServiceController 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

List of All Members for QtServiceController

16 |

This is the complete list of members for QtServiceController, including inherited members.

17 |

18 | 39 |
38 |

40 |


41 | 42 | 43 | 44 | 45 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
46 | 47 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestSignalTrigger/TestQtService/qtservice/doc/images/qt-logo.png -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/doc/index.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | /*! 42 | \page index.html 43 | \title Service 44 | 45 | \section1 Description 46 | 47 | The QtService component is useful for developing Windows 48 | services and Unix daemons. 49 | 50 | 51 | 52 | The project provides a QtService template class that can be used to 53 | implement service applications, and a QtServiceController class 54 | to control a service. 55 | 56 | On Windows systems the implementation uses the Service Control 57 | Manager. 58 | 59 | On Unix systems services are implemented as daemons. 60 | 61 | 62 | 63 | \section1 Classes 64 | \list 65 | \i QtServiceController \i QtServiceBase \i QtService\endlist 66 | 67 | \section1 Examples 68 | \list 69 | \i \link qtservice-example-interactive.html An Interactive Service \endlink \i \link qtservice-example-server.html A simple HTTP Server \endlink \i \link qtservice-example-controller.html A simple Service Controller \endlink \endlist 70 | 71 | 72 | 73 | 74 | 75 | 76 | \section1 Tested platforms 77 | \list 78 | \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 79 | \i Qt 4.4, 4.5 / Linux / gcc 80 | \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc 81 | \endlist 82 | 83 | 84 | 85 | 86 | */ 87 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/qtservice.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE=subdirs 2 | CONFIG += ordered 3 | include(common.pri) 4 | qtservice-uselib:SUBDIRS=buildlib 5 | SUBDIRS+=examples 6 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/QtService: -------------------------------------------------------------------------------- 1 | #include "qtservice.h" 2 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/QtServiceBase: -------------------------------------------------------------------------------- 1 | #include "qtservice.h" 2 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/QtServiceController: -------------------------------------------------------------------------------- 1 | #include "qtservice.h" 2 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtservice.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSERVICE_H 42 | #define QTSERVICE_H 43 | 44 | #include 45 | 46 | #if defined(Q_OS_WIN) 47 | # if !defined(QT_QTSERVICE_EXPORT) && !defined(QT_QTSERVICE_IMPORT) 48 | # define QT_QTSERVICE_EXPORT 49 | # elif defined(QT_QTSERVICE_IMPORT) 50 | # if defined(QT_QTSERVICE_EXPORT) 51 | # undef QT_QTSERVICE_EXPORT 52 | # endif 53 | # define QT_QTSERVICE_EXPORT __declspec(dllimport) 54 | # elif defined(QT_QTSERVICE_EXPORT) 55 | # undef QT_QTSERVICE_EXPORT 56 | # define QT_QTSERVICE_EXPORT __declspec(dllexport) 57 | # endif 58 | #else 59 | # define QT_QTSERVICE_EXPORT 60 | #endif 61 | 62 | class QStringList; 63 | class QtServiceControllerPrivate; 64 | 65 | class QT_QTSERVICE_EXPORT QtServiceController 66 | { 67 | Q_DECLARE_PRIVATE(QtServiceController) 68 | public: 69 | enum StartupType 70 | { 71 | AutoStartup = 0, ManualStartup 72 | }; 73 | 74 | QtServiceController(const QString &name); 75 | virtual ~QtServiceController(); 76 | 77 | bool isInstalled() const; 78 | bool isRunning() const; 79 | 80 | QString serviceName() const; 81 | QString serviceDescription() const; 82 | StartupType startupType() const; 83 | QString serviceFilePath() const; 84 | 85 | static bool install(const QString &serviceFilePath, const QString &account = QString(), 86 | const QString &password = QString()); 87 | bool uninstall(); 88 | 89 | bool start(const QStringList &arguments); 90 | bool start(); 91 | bool stop(); 92 | bool pause(); 93 | bool resume(); 94 | bool sendCommand(int code); 95 | 96 | private: 97 | QtServiceControllerPrivate *d_ptr; 98 | }; 99 | 100 | class QtServiceBasePrivate; 101 | 102 | class QT_QTSERVICE_EXPORT QtServiceBase 103 | { 104 | Q_DECLARE_PRIVATE(QtServiceBase) 105 | public: 106 | 107 | enum MessageType 108 | { 109 | Success = 0, Error, Warning, Information 110 | }; 111 | 112 | enum ServiceFlag 113 | { 114 | Default = 0x00, 115 | CanBeSuspended = 0x01, 116 | CannotBeStopped = 0x02, 117 | NeedsStopOnShutdown = 0x04 118 | }; 119 | 120 | Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag) 121 | 122 | QtServiceBase(int argc, char **argv, const QString &name); 123 | virtual ~QtServiceBase(); 124 | 125 | QString serviceName() const; 126 | 127 | QString serviceDescription() const; 128 | void setServiceDescription(const QString &description); 129 | 130 | QtServiceController::StartupType startupType() const; 131 | void setStartupType(QtServiceController::StartupType startupType); 132 | 133 | ServiceFlags serviceFlags() const; 134 | void setServiceFlags(ServiceFlags flags); 135 | 136 | int exec(); 137 | 138 | void logMessage(const QString &message, MessageType type = Success, 139 | int id = 0, uint category = 0, const QByteArray &data = QByteArray()); 140 | 141 | static QtServiceBase *instance(); 142 | 143 | protected: 144 | 145 | virtual void start() = 0; 146 | virtual void stop(); 147 | virtual void pause(); 148 | virtual void resume(); 149 | virtual void processCommand(int code); 150 | 151 | virtual void createApplication(int &argc, char **argv) = 0; 152 | 153 | virtual int executeApplication() = 0; 154 | 155 | private: 156 | 157 | friend class QtServiceSysPrivate; 158 | QtServiceBasePrivate *d_ptr; 159 | }; 160 | 161 | template 162 | class QtService : public QtServiceBase 163 | { 164 | public: 165 | QtService(int argc, char **argv, const QString &name) 166 | : QtServiceBase(argc, argv, name), app(0) 167 | { } 168 | ~QtService() 169 | { 170 | } 171 | 172 | protected: 173 | Application *application() const 174 | { return app; } 175 | 176 | virtual void createApplication(int &argc, char **argv) 177 | { 178 | app = new Application(argc, argv); 179 | QCoreApplication *a = app; 180 | Q_UNUSED(a); 181 | } 182 | 183 | virtual int executeApplication() 184 | { return Application::exec(); } 185 | 186 | private: 187 | Application *app; 188 | }; 189 | 190 | Q_DECLARE_OPERATORS_FOR_FLAGS(QtServiceBase::ServiceFlags) 191 | 192 | #endif // QTSERVICE_H 193 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtservice.pri: -------------------------------------------------------------------------------- 1 | include(../common.pri) 2 | INCLUDEPATH += $$PWD 3 | DEPENDPATH += $$PWD 4 | !win32:QT += network 5 | win32:LIBS += -luser32 6 | 7 | qtservice-uselib:!qtservice-buildlib { 8 | LIBS += -L$$QTSERVICE_LIBDIR -l$$QTSERVICE_LIBNAME 9 | } else { 10 | HEADERS += $$PWD/qtservice.h \ 11 | $$PWD/qtservice_p.h 12 | SOURCES += $$PWD/qtservice.cpp 13 | win32:SOURCES += $$PWD/qtservice_win.cpp 14 | unix:HEADERS += $$PWD/qtunixsocket.h $$PWD/qtunixserversocket.h 15 | unix:SOURCES += $$PWD/qtservice_unix.cpp $$PWD/qtunixsocket.cpp $$PWD/qtunixserversocket.cpp 16 | } 17 | 18 | win32 { 19 | qtservice-buildlib:shared:DEFINES += QT_QTSERVICE_EXPORT 20 | else:qtservice-uselib:DEFINES += QT_QTSERVICE_IMPORT 21 | } 22 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtservice_p.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSERVICE_P_H 42 | #define QTSERVICE_P_H 43 | 44 | #include 45 | #include "qtservice.h" 46 | 47 | class QtServiceControllerPrivate 48 | { 49 | Q_DECLARE_PUBLIC(QtServiceController) 50 | public: 51 | QString serviceName; 52 | QtServiceController *q_ptr; 53 | }; 54 | 55 | class QtServiceBasePrivate 56 | { 57 | Q_DECLARE_PUBLIC(QtServiceBase) 58 | public: 59 | 60 | QtServiceBasePrivate(const QString &name); 61 | ~QtServiceBasePrivate(); 62 | 63 | QtServiceBase *q_ptr; 64 | 65 | QString serviceDescription; 66 | QtServiceController::StartupType startupType; 67 | QtServiceBase::ServiceFlags serviceFlags; 68 | QStringList args; 69 | 70 | static class QtServiceBase *instance; 71 | 72 | QtServiceController controller; 73 | 74 | void startService(); 75 | int run(bool asService, const QStringList &argList); 76 | bool install(const QString &account, const QString &password); 77 | 78 | bool start(); 79 | 80 | QString filePath() const; 81 | bool sysInit(); 82 | void sysSetPath(); 83 | void sysCleanup(); 84 | class QtServiceSysPrivate *sysd; 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtunixserversocket.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include "qtunixserversocket.h" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #ifndef SUN_LEN 49 | #define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ 50 | +strlen ((ptr)->sun_path)) 51 | #endif 52 | 53 | QtUnixServerSocket::QtUnixServerSocket(const QString &path, QObject *parent) 54 | : QTcpServer(parent) 55 | { 56 | setPath(path); 57 | } 58 | 59 | QtUnixServerSocket::QtUnixServerSocket(QObject *parent) 60 | : QTcpServer(parent) 61 | { 62 | } 63 | 64 | void QtUnixServerSocket::setPath(const QString &path) 65 | { 66 | path_.clear(); 67 | 68 | int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); 69 | if (sock != -1) { 70 | struct sockaddr_un addr; 71 | ::memset(&addr, 0, sizeof(struct sockaddr_un)); 72 | addr.sun_family = AF_UNIX; 73 | ::unlink(path.toLatin1().constData()); // ### This might need to be changed 74 | unsigned int pathlen = strlen(path.toLatin1().constData()); 75 | if (pathlen > sizeof(addr.sun_path)) pathlen = sizeof(addr.sun_path); 76 | ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); 77 | if ((::bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)) != -1) && 78 | (::listen(sock, 5) != -1)) { 79 | setSocketDescriptor(sock); 80 | path_ = path; 81 | } 82 | } 83 | } 84 | 85 | void QtUnixServerSocket::close() 86 | { 87 | QTcpServer::close(); 88 | if (!path_.isEmpty()) { 89 | ::unlink(path_.toLatin1().constData()); 90 | path_.clear(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtunixserversocket.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTUNIXSERVERSOCKET_H 42 | #define QTUNIXSERVERSOCKET_H 43 | 44 | #include 45 | 46 | class QtUnixServerSocket : public QTcpServer 47 | { 48 | Q_OBJECT 49 | public: 50 | QtUnixServerSocket(const QString &path, QObject *parent = 0); 51 | QtUnixServerSocket(QObject *parent = 0); 52 | 53 | void setPath(const QString &path); 54 | void close(); 55 | 56 | private: 57 | QString path_; 58 | }; 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtunixsocket.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include "qtunixsocket.h" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #ifndef SUN_LEN 49 | #define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ 50 | +strlen ((ptr)->sun_path)) 51 | #endif 52 | 53 | QtUnixSocket::QtUnixSocket(QObject *parent) 54 | : QTcpSocket(parent) 55 | { 56 | } 57 | 58 | bool QtUnixSocket::connectTo(const QString &path) 59 | { 60 | bool ret = false; 61 | int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); 62 | if (sock != -1) { 63 | struct sockaddr_un addr; 64 | ::memset(&addr, 0, sizeof(struct sockaddr_un)); 65 | addr.sun_family = AF_UNIX; 66 | size_t pathlen = strlen(path.toLatin1().constData()); 67 | pathlen = qMin(pathlen, sizeof(addr.sun_path)); 68 | ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); 69 | int err = ::connect(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)); 70 | if (err != -1) { 71 | setSocketDescriptor(sock); 72 | ret = true; 73 | } else { 74 | ::close(sock); 75 | } 76 | } 77 | return ret; 78 | } 79 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestQtService/qtservice/src/qtunixsocket.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTUNIXSOCKET_H 42 | #define QTUNIXSOCKET_H 43 | 44 | #include 45 | 46 | class QtUnixSocket : public QTcpSocket 47 | { 48 | Q_OBJECT 49 | public: 50 | QtUnixSocket(QObject *parent = 0); 51 | 52 | bool connectTo(const QString &path); 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestSignalTrigger.pri: -------------------------------------------------------------------------------- 1 | DESTDIR = $$PWD/build 2 | -------------------------------------------------------------------------------- /TestSignalTrigger/TestSignalTrigger.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS += \ 4 | TestQtService \ 5 | PluginOne \ 6 | PluginTwo \ 7 | TestPluginOnePluginTwo 8 | 9 | TestPluginOnePluginTwo.depends = \ 10 | PluginOne \ 11 | PluginTwo 12 | 13 | TestQtService.depends = \ 14 | PluginOne \ 15 | PluginTwo 16 | -------------------------------------------------------------------------------- /TestWindowsService/.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | build 3 | -------------------------------------------------------------------------------- /TestWindowsService/README.txt: -------------------------------------------------------------------------------- 1 | # MyWindowsService 2 | This is a Windows Service or Unix Daemon. It monitors users' log on/log off, lock/unlock, sleep/awake Windows events, and writes to the log. 3 | The log locates at C:/ProgramData/MyWindowsService/mws.log. 4 | This project also gives several tries to get the specific user's (the active user's) user name and environment variable. 5 | It seems the user name of the active user can be got, but it's hard to get the environment variables. 6 | -------------------------------------------------------------------------------- /TestWindowsService/TestWindowsService.pri: -------------------------------------------------------------------------------- 1 | PROJ_ARCH = "Unknown"; 2 | 3 | equals(QT_ARCH, x86_64) { 4 | PROJ_ARCH = "x64" 5 | } else : equals(QT_ARCH, i386) { 6 | PROJ_ARCH = "x86" 7 | } 8 | 9 | CONFIG(debug, debug|release) { 10 | PROJ_SPEC = $$basename(QMAKESPEC)-$${PROJ_ARCH}-d 11 | } else { 12 | PROJ_SPEC = $$basename(QMAKESPEC)-$${PROJ_ARCH}-r 13 | } 14 | 15 | DependencyPath = "release" 16 | CONFIG(debug, debug|release) { 17 | DependencyPath = "debug" 18 | } else { 19 | DependencyPath = "release" 20 | } 21 | 22 | defineTest(copyDependency) { 23 | QMAKE_POST_LINK += $(COPY_FILE) \ 24 | $$system_quote($$shell_path($$PWD/qt-service-lib/$$DependencyPath/*.dll)) \ 25 | $$system_quote($$shell_path($$DESTDIR)) $$escape_expand(\\n\\t) 26 | 27 | export(QMAKE_POST_LINK) 28 | } 29 | -------------------------------------------------------------------------------- /TestWindowsService/TestWindowsService.pro: -------------------------------------------------------------------------------- 1 | include(TestWindowsService.pri) 2 | 3 | QT += core 4 | QT -= gui 5 | 6 | 7 | TARGET = TestWindowsService 8 | TEMPLATE = app 9 | 10 | DESTDIR = $$PWD/build/$$PROJ_SPEC 11 | 12 | DEFINES += _UNICODE 13 | 14 | CONFIG += c++11 \ 15 | console 16 | CONFIG -= app_bundle 17 | 18 | CONFIG(debug, debug|release) { 19 | LIBS += -L$$PWD/qt-service-lib/debug \ 20 | -lQtSolutions_Service-headd 21 | } else { 22 | LIBS += -L$$PWD/qt-service-lib/release \ 23 | -lQtSolutions_Service-head 24 | } 25 | 26 | LIBS += -ladvapi32 \ 27 | -lkernel32 \ 28 | -lWtsapi32 \ 29 | -lUser32 \ 30 | -lUserEnv 31 | 32 | INCLUDEPATH += $$PWD/qt-service-lib/include 33 | 34 | SOURCES += main.cpp \ 35 | my_windows_service.cpp \ 36 | message_handler.cpp \ 37 | windowassist.cpp 38 | 39 | HEADERS += \ 40 | my_windows_service.h \ 41 | qt-service-lib/include/qtservice.h \ 42 | message_handler.h \ 43 | windowassist.h 44 | 45 | DISTFILES += \ 46 | TestWindowsService.pri 47 | 48 | copyDependency() 49 | -------------------------------------------------------------------------------- /TestWindowsService/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "message_handler.h" 4 | #include "my_windows_service.h" 5 | 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | MyWindowsService service(argc, argv); 11 | 12 | qInfo() << "In the main function for MyWindowsService..."; 13 | 14 | return service.exec(); 15 | } 16 | -------------------------------------------------------------------------------- /TestWindowsService/message_handler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "message_handler.h" 9 | 10 | using namespace message_handler; 11 | 12 | 13 | QString MessageHandler::s_log = "mws.log"; 14 | 15 | 16 | void MessageHandler::setLogFile(QString file) 17 | { 18 | s_log = file; 19 | } 20 | 21 | 22 | void MessageHandler::FormatMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) 23 | { 24 | static QMutex mutex; 25 | mutex.lock(); 26 | 27 | QFile logFile(MessageHandler::s_log); 28 | logFile.open(QIODevice::WriteOnly | QIODevice::Append); 29 | 30 | QString log(""); 31 | log += QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz") + QString(" "); 32 | 33 | switch(type) 34 | { 35 | case QtDebugMsg: 36 | log += QString("[Debug]"); 37 | break; 38 | 39 | case QtInfoMsg: 40 | log += QString("[Info]"); 41 | break; 42 | 43 | case QtWarningMsg: 44 | log += QString("[Warn]"); 45 | break; 46 | 47 | case QtCriticalMsg: 48 | log += QString("[Critical]"); 49 | break; 50 | 51 | case QtFatalMsg: 52 | log += QString("[Fatal]"); 53 | abort(); 54 | break; 55 | 56 | default: 57 | log += QString("[UnknownLogType]"); 58 | break; 59 | }; 60 | 61 | log += QString(context.file) 62 | + QString(", Line ") 63 | + QString::number(context.line) 64 | + QString(": %1\n").arg(msg); 65 | 66 | QTextStream text_stream(&logFile); 67 | text_stream << log; 68 | logFile.flush(); 69 | logFile.close(); 70 | 71 | mutex.unlock(); 72 | } 73 | -------------------------------------------------------------------------------- /TestWindowsService/message_handler.h: -------------------------------------------------------------------------------- 1 | #ifndef MESSAGEHANDLER_H 2 | #define MESSAGEHANDLER_H 3 | 4 | #include 5 | 6 | namespace message_handler { 7 | class MessageHandler 8 | { 9 | private: 10 | MessageHandler(); 11 | ~MessageHandler(); 12 | 13 | public: 14 | static void setLogFile(QString file = "./mws.log"); 15 | static void FormatMessage(QtMsgType type , const QMessageLogContext& context , const QString& msg); 16 | 17 | private: 18 | static QString s_log; 19 | }; 20 | } 21 | 22 | 23 | #endif // MESSAGEHANDLER_H 24 | -------------------------------------------------------------------------------- /TestWindowsService/my_windows_service.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "message_handler.h" 6 | #include "my_windows_service.h" 7 | 8 | #include 9 | 10 | 11 | MyWindowsService::MyWindowsService(int argc, char** argv) 12 | : QtService(argc, argv, "My Windows Service") 13 | { 14 | setServiceDescription("This is my Windows Service"); 15 | setServiceFlags(QtServiceBase::CanBeSuspended); 16 | 17 | m_windowAssist = new WindowAssist(this); 18 | } 19 | 20 | 21 | void MyWindowsService::installMessageHandler() 22 | { 23 | // Install Message Handler 24 | QString logDirName = "C:/ProgramData/MyWindowsService"; 25 | QDir logDir(logDirName); 26 | 27 | if (!logDir.exists()) 28 | { 29 | qDebug() << "Creating folder: " << logDirName; 30 | QDir().mkdir(logDirName); 31 | } 32 | 33 | QString logFile = logDirName + "/mws.log"; 34 | 35 | // Remove the Macro defined in winbase.h 36 | #ifdef FormatMessage 37 | #undef FormatMessage 38 | message_handler::MessageHandler::setLogFile(logFile); 39 | qInstallMessageHandler(message_handler::MessageHandler::FormatMessage); 40 | #endif 41 | } 42 | 43 | 44 | void MyWindowsService::way1_GetUserNameByQT() 45 | { 46 | // In the system level process/service, 47 | // the UserName is "$", e.g. "FINIX-LAPTOP$". 48 | 49 | qInfo() << "Way 1 - Get User Name via QT..."; 50 | qInfo() << "User Name = " << qgetenv("UserName"); 51 | qInfo() << "---------------------------"; 52 | } 53 | 54 | 55 | void MyWindowsService::way2_GetUserNameByWindowsAPI() 56 | { 57 | #ifdef Q_OS_WIN 58 | // Output: Windows User Name = "SYSTEM" 59 | 60 | qInfo() << "Way 2 - Get User Name via Windows API GetUserName()..."; 61 | 62 | wchar_t acUserName[200]; 63 | DWORD nUserName = sizeof(acUserName); 64 | if (GetUserName(acUserName, &nUserName)) 65 | { 66 | // Translate wchar_t * to QString 67 | qInfo() << "Windows User Name = " << QString::fromWCharArray(acUserName); 68 | } 69 | #elif Q_OS_UNIX 70 | QCoreApplication coreApplication(argc, argv); 71 | QProcess process; 72 | QObject::connect(&process, &QProcess::finished, [&coreApplication, &process](int exitCode, QProcess::ExitStatus exitStatus) { 73 | qDebug() << process.readAllStandardOutput(); 74 | coreApplication.quit(); 75 | }); 76 | process.start("whoami"); 77 | #endif 78 | qInfo() << "---------------------------"; 79 | } 80 | 81 | 82 | 83 | void MyWindowsService::way3_GetActiveUserNameByWindowsAPIInSystemProcess() 84 | { 85 | // Output: Windows User Name = "Finix" 86 | 87 | qInfo() << "Way 3 - Get Active User Name from a system process..."; 88 | DWORD sessionId = WTSGetActiveConsoleSessionId(); 89 | qInfo() << "session id = " << sessionId; 90 | 91 | wchar_t* ppBuffer[100]; 92 | DWORD bufferSize; 93 | WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppBuffer, &bufferSize); 94 | qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppBuffer); 95 | 96 | qInfo() << "---------------------------"; 97 | } 98 | 99 | 100 | void MyWindowsService::way4_GetHomeLocationByQStandardPaths() 101 | { 102 | // Output: "C:/Windows/system32/config/systemprofile" 103 | 104 | qInfo() << "Way 4 - Get Home Location via QStandardPaths..."; 105 | QStringList homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); 106 | qInfo() << homePath.first().split(QDir::separator()).last(); 107 | qInfo() << "---------------------------"; 108 | } 109 | 110 | 111 | void MyWindowsService::way5_GetHomeLocationByWindowsAPI() 112 | { 113 | // Output: "C:\\Windows\\system32\\config\\systemprofile" 114 | 115 | qInfo() << "Way 5 - Get Home Location via Windows API..."; 116 | wchar_t envVar[] = L"UserProfile"; 117 | wchar_t result[100]; 118 | GetEnvironmentVariable(envVar, result, sizeof(result)/sizeof(wchar_t)); 119 | qInfo() << "USER PROFILE = " << QString::fromWCharArray(result); 120 | qInfo() << "---------------------------"; 121 | } 122 | 123 | 124 | void MyWindowsService::way6_GetHomeLoactioneByWTS() 125 | { 126 | qInfo() << "Way 6 - Get Home Location via WTS technique..."; 127 | DWORD sessionId = WTSGetActiveConsoleSessionId(); 128 | qInfo() << "Session ID = " << sessionId; 129 | wchar_t* ppBuffer[100]; 130 | DWORD bufferSize; 131 | 132 | WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSWorkingDirectory, ppBuffer, &bufferSize); 133 | qInfo() << "Working Directory = " << QString::fromWCharArray(*ppBuffer); // Empty "" 134 | 135 | WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSClientDirectory, ppBuffer, &bufferSize); 136 | qInfo() << "Client Directory = " << QString::fromWCharArray(*ppBuffer); // Empty "" 137 | 138 | qInfo() << "---------------------------"; 139 | } 140 | 141 | void MyWindowsService::way7_GetEnvironmentVariables() 142 | { 143 | qInfo() << "Way 7 - Get Environment Variables by Windows API CreateEnvironmentBlock()..."; 144 | 145 | DWORD sessionId = WTSGetActiveConsoleSessionId(); 146 | qInfo() << "Session ID = " << sessionId; 147 | 148 | HANDLE token; 149 | if (!WTSQueryUserToken(sessionId, &token)) 150 | { 151 | qCritical() << "Failed to get the user token of session " << sessionId; 152 | qInfo() << "---------------------------"; 153 | return; 154 | } 155 | 156 | wchar_t* pEnv = NULL; 157 | if (CreateEnvironmentBlock((void**)&pEnv, token, TRUE)) 158 | { 159 | while (*pEnv) { 160 | // printf("%ls\n", pEnv); 161 | qInfo() << QString::fromWCharArray(pEnv); 162 | pEnv += wcslen(pEnv) + 1; 163 | } 164 | } 165 | 166 | qInfo() << "---------------------------"; 167 | } 168 | 169 | static LONG GetStringRegKey(HKEY hKey, const std::wstring &strValueName, std::wstring &strValue, const std::wstring &strDefaultValue) 170 | { 171 | strValue = strDefaultValue; 172 | WCHAR szBuffer[512]; 173 | DWORD dwBufferSize = sizeof(szBuffer); 174 | ULONG nError; 175 | nError = RegQueryValueExW(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize); 176 | if (ERROR_SUCCESS == nError) 177 | { 178 | strValue = szBuffer; 179 | } 180 | return nError; 181 | } 182 | 183 | static void GetUserRegistryHive() 184 | { 185 | std::wstring strValueOfBinDir = L"Unknown Value"; 186 | LONG regOpenResult = ERROR_SUCCESS; 187 | 188 | HKEY hKey; 189 | 190 | regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey); 191 | if (regOpenResult != ERROR_SUCCESS) 192 | { 193 | qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult; 194 | } 195 | 196 | HKEY hSubKey; 197 | 198 | RegOpenKeyEx(hKey, 199 | TEXT("Software\\Baidu\\BaiduYunGuanjia"), 200 | 0, 201 | KEY_READ, 202 | &hSubKey); 203 | GetStringRegKey(hSubKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown")); 204 | 205 | qInfo() << "The value of Registry is " << QString::fromWCharArray( strValueOfBinDir.c_str() ); 206 | 207 | } 208 | 209 | void MyWindowsService::way8_GetUserRegistry() 210 | { 211 | #ifdef Q_OS_WIN 212 | 213 | DWORD sessionId = WTSGetActiveConsoleSessionId(); 214 | qInfo() << "Session ID = " << sessionId; 215 | 216 | wchar_t * ppUserName[100]; 217 | DWORD sizeOfUserName; 218 | WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppUserName, &sizeOfUserName); 219 | qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppUserName); 220 | 221 | std::wstring strValueOfBinDir = L"Unknown Value"; 222 | LONG regOpenResult = ERROR_SUCCESS; 223 | 224 | HANDLE hUserToken = NULL; 225 | HANDLE hFakeToken = NULL; 226 | 227 | if (WTSQueryUserToken(sessionId, &hUserToken)) 228 | { 229 | if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hFakeToken) == TRUE) 230 | { 231 | qInfo() << "Before ImpersonateLoggedOnUser()......"; 232 | if (ImpersonateLoggedOnUser(hFakeToken)) 233 | { 234 | HKEY hKey; 235 | 236 | regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey); 237 | if (regOpenResult != ERROR_SUCCESS) 238 | { 239 | qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult; 240 | } 241 | 242 | HKEY hSubKey; 243 | 244 | RegOpenKeyEx(hKey, 245 | TEXT("Software\\Baidu\\BaiduYunGuanjia"), 246 | 0, 247 | KEY_READ, 248 | &hSubKey); 249 | GetStringRegKey(hSubKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown")); 250 | 251 | RevertToSelf(); 252 | } 253 | else 254 | { 255 | qCritical() << "Failed to ImpersonateLoggedOnUser..."; 256 | } 257 | CloseHandle(hFakeToken); 258 | } 259 | else 260 | { 261 | qCritical() << "Failed to call DuplicateTokenEx..."; 262 | } 263 | CloseHandle(hUserToken); 264 | } 265 | else 266 | { 267 | qCritical() << "Failed to get the user token of session " << sessionId; 268 | } 269 | 270 | qInfo() << "The value of Registry is " << QString::fromWCharArray( strValueOfBinDir.c_str() ); 271 | 272 | // Check that after Impersonating, can get the User Registry hive or not. As expected, not. 273 | GetUserRegistryHive(); 274 | 275 | #endif 276 | } 277 | 278 | void MyWindowsService::testUserStuff() 279 | { 280 | way1_GetUserNameByQT(); 281 | way2_GetUserNameByWindowsAPI(); 282 | way3_GetActiveUserNameByWindowsAPIInSystemProcess(); 283 | way4_GetHomeLocationByQStandardPaths(); 284 | way5_GetHomeLocationByWindowsAPI(); 285 | way6_GetHomeLoactioneByWTS(); 286 | way7_GetEnvironmentVariables(); 287 | way8_GetUserRegistry(); 288 | } 289 | 290 | void MyWindowsService::testKeepProcess() 291 | { 292 | QProcess* p = new QProcess(); // leaking on pourpose 293 | p->setProcessChannelMode(QProcess::MergedChannels); 294 | 295 | QObject::connect(p, &QProcess::started, [] () { 296 | qDebug() << "Notepad.exe started!"; 297 | }); 298 | 299 | // Keep restarting if notepad.exe is finished 300 | QObject::connect(p, static_cast(&QProcess::finished), 301 | [p] (int exitCode, QProcess::ExitStatus exitStatus) { 302 | qWarning() << "Notepad.exe was terminated! " 303 | << "Exit code: " << exitCode 304 | << "Exit status: " << exitStatus; 305 | 306 | // restart 307 | qWarning() << "Notepad.exe will restart... "; 308 | p->start(); 309 | }); 310 | 311 | p->start("notepad.exe"); 312 | } 313 | 314 | 315 | void MyWindowsService::start() 316 | { 317 | // Only for "-e" option, as message handler has not been installed 318 | qDebug() << "Get into start()......."; 319 | 320 | installMessageHandler(); 321 | 322 | qInfo() << "Start MyWindowsService..."; 323 | 324 | // testUserStuff(); 325 | 326 | testKeepProcess(); // Keep restarting "notepad.exe" in case found that it is finished. 327 | } 328 | 329 | void MyWindowsService::stop() 330 | { 331 | qInfo() << "Stop MyWindowsService..."; 332 | } 333 | 334 | void MyWindowsService::resume() 335 | { 336 | qInfo() << "Resume MyWindowsService..."; 337 | } 338 | 339 | void MyWindowsService::pause() 340 | { 341 | qInfo() << "Pause MyWindowsService..."; 342 | } 343 | -------------------------------------------------------------------------------- /TestWindowsService/my_windows_service.h: -------------------------------------------------------------------------------- 1 | #ifndef MYWINDOWSSERVICE_H 2 | #define MYWINDOWSSERVICE_H 3 | 4 | #include "qtservice.h" 5 | #include "windowassist.h" 6 | 7 | #ifdef Q_OS_WIN 8 | #include 9 | #include 10 | #include 11 | #include 12 | #endif 13 | 14 | class MyWindowsService: public QtService, public QObject 15 | { 16 | public: 17 | MyWindowsService(int argc, char* argv[]); 18 | 19 | protected: 20 | void start(); 21 | void pause(); 22 | void resume(); 23 | void stop(); 24 | 25 | private: 26 | void installMessageHandler(); 27 | 28 | void way1_GetUserNameByQT(); 29 | void way2_GetUserNameByWindowsAPI(); 30 | void way3_GetActiveUserNameByWindowsAPIInSystemProcess(); 31 | void way4_GetHomeLocationByQStandardPaths(); 32 | void way5_GetHomeLocationByWindowsAPI(); 33 | void way6_GetHomeLoactioneByWTS(); 34 | void way7_GetEnvironmentVariables(); 35 | void way8_GetUserRegistry(); 36 | void testUserStuff(); 37 | 38 | void testKeepProcess(); 39 | 40 | private: 41 | WindowAssist* m_windowAssist; 42 | }; 43 | 44 | #endif // MYWINDOWSSERVICE_H 45 | -------------------------------------------------------------------------------- /TestWindowsService/qt-service-lib/debug/QtSolutions_Service-headd.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestWindowsService/qt-service-lib/debug/QtSolutions_Service-headd.dll -------------------------------------------------------------------------------- /TestWindowsService/qt-service-lib/debug/QtSolutions_Service-headd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestWindowsService/qt-service-lib/debug/QtSolutions_Service-headd.lib -------------------------------------------------------------------------------- /TestWindowsService/qt-service-lib/debug/qtsolutions_service-headd.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestWindowsService/qt-service-lib/debug/qtsolutions_service-headd.pdb -------------------------------------------------------------------------------- /TestWindowsService/qt-service-lib/include/qtservice.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSERVICE_H 42 | #define QTSERVICE_H 43 | 44 | #include 45 | 46 | #if defined(Q_OS_WIN) 47 | # if !defined(QT_QTSERVICE_EXPORT) && !defined(QT_QTSERVICE_IMPORT) 48 | # define QT_QTSERVICE_EXPORT 49 | # elif defined(QT_QTSERVICE_IMPORT) 50 | # if defined(QT_QTSERVICE_EXPORT) 51 | # undef QT_QTSERVICE_EXPORT 52 | # endif 53 | # define QT_QTSERVICE_EXPORT __declspec(dllimport) 54 | # elif defined(QT_QTSERVICE_EXPORT) 55 | # undef QT_QTSERVICE_EXPORT 56 | # define QT_QTSERVICE_EXPORT __declspec(dllexport) 57 | # endif 58 | #else 59 | # define QT_QTSERVICE_EXPORT 60 | #endif 61 | 62 | class QStringList; 63 | class QtServiceControllerPrivate; 64 | 65 | class QT_QTSERVICE_EXPORT QtServiceController 66 | { 67 | Q_DECLARE_PRIVATE(QtServiceController) 68 | public: 69 | enum StartupType 70 | { 71 | AutoStartup = 0, ManualStartup 72 | }; 73 | 74 | QtServiceController(const QString &name); 75 | virtual ~QtServiceController(); 76 | 77 | bool isInstalled() const; 78 | bool isRunning() const; 79 | 80 | QString serviceName() const; 81 | QString serviceDescription() const; 82 | StartupType startupType() const; 83 | QString serviceFilePath() const; 84 | 85 | static bool install(const QString &serviceFilePath, const QString &account = QString(), 86 | const QString &password = QString()); 87 | bool uninstall(); 88 | 89 | bool start(const QStringList &arguments); 90 | bool start(); 91 | bool stop(); 92 | bool pause(); 93 | bool resume(); 94 | bool sendCommand(int code); 95 | 96 | private: 97 | QtServiceControllerPrivate *d_ptr; 98 | }; 99 | 100 | class QtServiceBasePrivate; 101 | 102 | class QT_QTSERVICE_EXPORT QtServiceBase 103 | { 104 | Q_DECLARE_PRIVATE(QtServiceBase) 105 | public: 106 | 107 | enum MessageType 108 | { 109 | Success = 0, Error, Warning, Information 110 | }; 111 | 112 | enum ServiceFlag 113 | { 114 | Default = 0x00, 115 | CanBeSuspended = 0x01, 116 | CannotBeStopped = 0x02, 117 | NeedsStopOnShutdown = 0x04 118 | }; 119 | 120 | Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag) 121 | 122 | QtServiceBase(int argc, char **argv, const QString &name); 123 | virtual ~QtServiceBase(); 124 | 125 | QString serviceName() const; 126 | 127 | QString serviceDescription() const; 128 | void setServiceDescription(const QString &description); 129 | 130 | QtServiceController::StartupType startupType() const; 131 | void setStartupType(QtServiceController::StartupType startupType); 132 | 133 | ServiceFlags serviceFlags() const; 134 | void setServiceFlags(ServiceFlags flags); 135 | 136 | int exec(); 137 | 138 | void logMessage(const QString &message, MessageType type = Success, 139 | int id = 0, uint category = 0, const QByteArray &data = QByteArray()); 140 | 141 | static QtServiceBase *instance(); 142 | 143 | protected: 144 | 145 | virtual void start() = 0; 146 | virtual void stop(); 147 | virtual void pause(); 148 | virtual void resume(); 149 | virtual void processCommand(int code); 150 | 151 | virtual void createApplication(int &argc, char **argv) = 0; 152 | 153 | virtual int executeApplication() = 0; 154 | 155 | private: 156 | 157 | friend class QtServiceSysPrivate; 158 | QtServiceBasePrivate *d_ptr; 159 | }; 160 | 161 | template 162 | class QtService : public QtServiceBase 163 | { 164 | public: 165 | QtService(int argc, char **argv, const QString &name) 166 | : QtServiceBase(argc, argv, name), app(0) 167 | { } 168 | ~QtService() 169 | { 170 | } 171 | 172 | protected: 173 | Application *application() const 174 | { return app; } 175 | 176 | virtual void createApplication(int &argc, char **argv) 177 | { 178 | app = new Application(argc, argv); 179 | QCoreApplication *a = app; 180 | Q_UNUSED(a); 181 | } 182 | 183 | virtual int executeApplication() 184 | { return Application::exec(); } 185 | 186 | private: 187 | Application *app; 188 | }; 189 | 190 | Q_DECLARE_OPERATORS_FOR_FLAGS(QtServiceBase::ServiceFlags) 191 | 192 | #endif // QTSERVICE_H 193 | -------------------------------------------------------------------------------- /TestWindowsService/qt-service-lib/release/QtSolutions_Service-head.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestWindowsService/qt-service-lib/release/QtSolutions_Service-head.dll -------------------------------------------------------------------------------- /TestWindowsService/qt-service-lib/release/QtSolutions_Service-head.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FinixLei/QtProjects/8092222c35a70ca37d8f9a99f91cf925ffa8253c/TestWindowsService/qt-service-lib/release/QtSolutions_Service-head.lib -------------------------------------------------------------------------------- /TestWindowsService/windowassist.cpp: -------------------------------------------------------------------------------- 1 | #include "windowassist.h" 2 | 3 | #include 4 | #include 5 | 6 | #ifdef Q_OS_WIN 7 | 8 | #include "windows.h" 9 | #include "Wtsapi32.h" 10 | 11 | 12 | void GetActiveUserName() 13 | { 14 | DWORD sessionId = WTSGetActiveConsoleSessionId(); 15 | qInfo() << "session id = " << sessionId; 16 | 17 | wchar_t* ppBuffer[100]; 18 | DWORD bufferSize; 19 | WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppBuffer, &bufferSize); 20 | qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppBuffer); 21 | } 22 | 23 | 24 | class WindowAssistImpl 25 | { 26 | WindowAssistImpl() = delete; 27 | 28 | public: 29 | static LPCWSTR m_windowName; 30 | static HWND m_windowHandle; 31 | static WindowAssist* m_windowAssist; 32 | 33 | public: 34 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 35 | { 36 | switch (msg) 37 | { 38 | case WM_WTSSESSION_CHANGE: 39 | switch (wParam) 40 | { 41 | case WTS_SESSION_LOGON: 42 | if (m_windowAssist != nullptr) 43 | { 44 | qDebug() << "Capture user logon event."; 45 | emit m_windowAssist->logon(); 46 | 47 | GetActiveUserName(); 48 | } 49 | break; 50 | case WTS_SESSION_LOGOFF: 51 | if (m_windowAssist != nullptr) 52 | { 53 | qDebug() << "Capture user logoff event."; 54 | emit m_windowAssist->logoff(); 55 | } 56 | break; 57 | case WTS_SESSION_LOCK: 58 | if (m_windowAssist != nullptr) 59 | { 60 | qDebug() << "Capture user lock event."; 61 | emit m_windowAssist->locked(); 62 | } 63 | break; 64 | case WTS_SESSION_UNLOCK: 65 | if (m_windowAssist != nullptr) 66 | { 67 | qDebug() << "Capture user unlock event."; 68 | emit m_windowAssist->unlocked(); 69 | 70 | GetActiveUserName(); 71 | } 72 | break; 73 | } 74 | break; 75 | case WM_POWERBROADCAST: 76 | switch (wParam) 77 | { 78 | case PBT_APMSUSPEND: 79 | if (m_windowAssist != nullptr) 80 | { 81 | qDebug() << "Capture system sleep event."; 82 | emit m_windowAssist->sleep(); 83 | } 84 | break; 85 | case PBT_APMRESUMEAUTOMATIC: 86 | if (m_windowAssist != nullptr) 87 | { 88 | qDebug() << "Capture system awake event."; 89 | emit m_windowAssist->awake(); 90 | } 91 | break; 92 | } 93 | break; 94 | case WM_DESTROY: 95 | PostQuitMessage(0); 96 | return 0; 97 | } 98 | 99 | return DefWindowProc(hWnd, msg, wParam, lParam); 100 | } 101 | 102 | static void createWindow() 103 | { 104 | LPCWSTR name = m_windowName; 105 | 106 | HINSTANCE instance = GetModuleHandle(NULL); 107 | 108 | WNDCLASSEX wcex; 109 | wcex.cbSize = sizeof(WNDCLASSEX); 110 | wcex.style = CS_NOCLOSE; 111 | wcex.lpfnWndProc = &WindowAssistImpl::WndProc; 112 | wcex.cbClsExtra = 0; 113 | wcex.cbWndExtra = 0; 114 | wcex.hInstance = instance; 115 | wcex.hIcon = NULL; 116 | wcex.hCursor = NULL; 117 | wcex.hbrBackground = NULL; 118 | wcex.lpszMenuName = NULL; 119 | wcex.lpszClassName = m_windowName; 120 | wcex.hIconSm = NULL; 121 | 122 | if (FALSE == RegisterClassEx(&wcex)) 123 | { 124 | qCritical() << "RegisterClassEx failed"; 125 | return; 126 | } 127 | 128 | m_windowHandle = CreateWindowEx( 129 | WS_EX_NOACTIVATE, 130 | name, 131 | name, 132 | NULL, 133 | 0, 0, 0, 0, 134 | NULL, 135 | NULL, 136 | instance, 137 | NULL); 138 | 139 | if (m_windowHandle == NULL) 140 | { 141 | qCritical() << "CreateWindowEx failed"; 142 | return; 143 | } 144 | 145 | if (!WTSRegisterSessionNotification(m_windowHandle, NOTIFY_FOR_ALL_SESSIONS)) 146 | { 147 | qCritical() << "Register Session Notification failed"; 148 | return; 149 | } 150 | } 151 | 152 | static void destroyWindow() 153 | { 154 | HINSTANCE instance = GetModuleHandle(NULL); 155 | 156 | if (FALSE == CloseWindow(m_windowHandle)) 157 | { 158 | qDebug() << "CloseWindow failed"; 159 | } 160 | 161 | if (FALSE == DestroyWindow(m_windowHandle)) 162 | { 163 | qDebug() << "DestroyWindow failed"; 164 | } 165 | 166 | if (FALSE == UnregisterClass(m_windowName, instance)) 167 | { 168 | qDebug() << "UnregisterClass failed"; 169 | } 170 | 171 | m_windowHandle = NULL; 172 | } 173 | }; 174 | 175 | /**************************************************************************************************/ 176 | 177 | LPCWSTR WindowAssistImpl::m_windowName = L"Event handler"; 178 | HWND WindowAssistImpl::m_windowHandle = NULL; 179 | WindowAssist* WindowAssistImpl::m_windowAssist = nullptr; 180 | 181 | /**************************************************************************************************/ 182 | 183 | WindowAssist::WindowAssist(QObject* parent) 184 | : QObject(parent) 185 | { 186 | WindowAssistImpl::m_windowAssist = this; 187 | WindowAssistImpl::createWindow(); 188 | } 189 | 190 | /**************************************************************************************************/ 191 | 192 | WindowAssist::~WindowAssist() 193 | { 194 | WindowAssistImpl::destroyWindow(); 195 | WindowAssistImpl::m_windowAssist = nullptr; 196 | } 197 | 198 | /**************************************************************************************************/ 199 | 200 | #endif // Q_OS_WIN 201 | -------------------------------------------------------------------------------- /TestWindowsService/windowassist.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOWASSIST_H 2 | #define WINDOWASSIST_H 3 | 4 | #include 5 | 6 | class WindowAssist: public QObject 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | /*! \brief Creates the instance of WindowAssist. */ 12 | explicit WindowAssist(QObject* parent = nullptr); 13 | 14 | /*! \brief Destroys the instance of WindowAssist. */ 15 | virtual ~WindowAssist(); 16 | 17 | Q_SIGNALS: 18 | 19 | /*! \brief Signal emited whenever the user logon system. 20 | * \details Signal emited whenever the user logon system. 21 | */ 22 | void logon(); 23 | 24 | /*! \brief Signal emited whenever the user logoff system. 25 | * \details Signal emited whenever the user logoff system. 26 | */ 27 | void logoff(); 28 | 29 | /*! \brief Signal emited whenever the user lock system. 30 | * \details Signal emited whenever the user lock system. 31 | */ 32 | void locked(); 33 | 34 | /*! \brief Signal emited whenever the user unlock system. 35 | * \details Signal emited whenever the user unlock system. 36 | */ 37 | void unlocked(); 38 | 39 | /*! \brief Signal emited whenever the computer goes to sleep. 40 | * \details Signal emited whenever the computer goes to sleep. 41 | */ 42 | void sleep(); 43 | 44 | /*! \brief Signal emited whenever the computer wakes up after sleep. 45 | * \details Signal emited whenever the computer wakes up after sleep. 46 | */ 47 | void awake(); 48 | }; 49 | 50 | #endif // WINDOWASSIST_H 51 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/TestWindowsServiceWithLibrarySource.pri: -------------------------------------------------------------------------------- 1 | PROJ_ARCH = "Unknown"; 2 | 3 | equals(QT_ARCH, x86_64) { 4 | PROJ_ARCH = "x64" 5 | } else : equals(QT_ARCH, i386) { 6 | PROJ_ARCH = "x86" 7 | } 8 | 9 | CONFIG(debug, debug|release) { 10 | PROJ_SPEC = $$basename(QMAKESPEC)-$${PROJ_ARCH}-d 11 | } else { 12 | PROJ_SPEC = $$basename(QMAKESPEC)-$${PROJ_ARCH}-r 13 | } 14 | 15 | DependencyPath = "release" 16 | CONFIG(debug, debug|release) { 17 | DependencyPath = "debug" 18 | } else { 19 | DependencyPath = "release" 20 | } 21 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/TestWindowsServiceWithLibrarySource.pro: -------------------------------------------------------------------------------- 1 | include(TestWindowsServiceWithLibrarySource.pri) 2 | include(qtservice/qtservice.pri) 3 | 4 | QT += core 5 | QT -= gui 6 | 7 | CONFIG += c++11 8 | 9 | TARGET = my_windows_service 10 | CONFIG += console 11 | CONFIG -= app_bundle 12 | CONFIG += c++11 13 | 14 | TEMPLATE = app 15 | 16 | DESTDIR = $$PWD/build/$$PROJ_SPEC 17 | 18 | SOURCES += main.cpp \ 19 | my_windows_service.cpp 20 | 21 | HEADERS += my_windows_service.h 22 | 23 | DISTFILES += \ 24 | qtservice/qtservice.pri \ 25 | TestWindowsServiceWithLibrarySource.pri 26 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "my_windows_service.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | MyWindowsService service(argc, argv); 8 | 9 | return service.exec(); 10 | } 11 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/my_windows_service.cpp: -------------------------------------------------------------------------------- 1 | #include "my_windows_service.h" 2 | 3 | MyWindowsService::MyWindowsService(int argc, char* argv[]) 4 | : QtService(argc, argv, "My Windows Service with Source") 5 | { 6 | } 7 | 8 | void MyWindowsService::start() 9 | { 10 | } 11 | 12 | void MyWindowsService::stop() 13 | { 14 | } 15 | 16 | void MyWindowsService::pause() 17 | { 18 | } 19 | 20 | void MyWindowsService::resume() 21 | { 22 | } 23 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/my_windows_service.h: -------------------------------------------------------------------------------- 1 | #ifndef MYWINDOWSSERVICE_H 2 | #define MYWINDOWSSERVICE_H 3 | 4 | #include "qtservice.h" 5 | 6 | 7 | class MyWindowsService: public QtService 8 | { 9 | public: 10 | MyWindowsService(int argc, char* argv[]); 11 | ~MyWindowsService(){} 12 | 13 | public: 14 | void start(); 15 | void pause(); 16 | void resume(); 17 | void stop(); 18 | }; 19 | 20 | #endif // MYWINDOWSSERVICE_H 21 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtservice.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSERVICE_H 42 | #define QTSERVICE_H 43 | 44 | #include 45 | 46 | #if defined(Q_OS_WIN) 47 | # if !defined(QT_QTSERVICE_EXPORT) && !defined(QT_QTSERVICE_IMPORT) 48 | # define QT_QTSERVICE_EXPORT 49 | # elif defined(QT_QTSERVICE_IMPORT) 50 | # if defined(QT_QTSERVICE_EXPORT) 51 | # undef QT_QTSERVICE_EXPORT 52 | # endif 53 | # define QT_QTSERVICE_EXPORT __declspec(dllimport) 54 | # elif defined(QT_QTSERVICE_EXPORT) 55 | # undef QT_QTSERVICE_EXPORT 56 | # define QT_QTSERVICE_EXPORT __declspec(dllexport) 57 | # endif 58 | #else 59 | # define QT_QTSERVICE_EXPORT 60 | #endif 61 | 62 | class QStringList; 63 | class QtServiceControllerPrivate; 64 | 65 | class QT_QTSERVICE_EXPORT QtServiceController 66 | { 67 | Q_DECLARE_PRIVATE(QtServiceController) 68 | public: 69 | enum StartupType 70 | { 71 | AutoStartup = 0, ManualStartup 72 | }; 73 | 74 | QtServiceController(const QString &name); 75 | virtual ~QtServiceController(); 76 | 77 | bool isInstalled() const; 78 | bool isRunning() const; 79 | 80 | QString serviceName() const; 81 | QString serviceDescription() const; 82 | StartupType startupType() const; 83 | QString serviceFilePath() const; 84 | 85 | static bool install(const QString &serviceFilePath, const QString &account = QString(), 86 | const QString &password = QString()); 87 | bool uninstall(); 88 | 89 | bool start(const QStringList &arguments); 90 | bool start(); 91 | bool stop(); 92 | bool pause(); 93 | bool resume(); 94 | bool sendCommand(int code); 95 | 96 | private: 97 | QtServiceControllerPrivate *d_ptr; 98 | }; 99 | 100 | class QtServiceBasePrivate; 101 | 102 | class QT_QTSERVICE_EXPORT QtServiceBase 103 | { 104 | Q_DECLARE_PRIVATE(QtServiceBase) 105 | public: 106 | 107 | enum MessageType 108 | { 109 | Success = 0, Error, Warning, Information 110 | }; 111 | 112 | enum ServiceFlag 113 | { 114 | Default = 0x00, 115 | CanBeSuspended = 0x01, 116 | CannotBeStopped = 0x02, 117 | NeedsStopOnShutdown = 0x04 118 | }; 119 | 120 | Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag) 121 | 122 | QtServiceBase(int argc, char **argv, const QString &name); 123 | virtual ~QtServiceBase(); 124 | 125 | QString serviceName() const; 126 | 127 | QString serviceDescription() const; 128 | void setServiceDescription(const QString &description); 129 | 130 | QtServiceController::StartupType startupType() const; 131 | void setStartupType(QtServiceController::StartupType startupType); 132 | 133 | ServiceFlags serviceFlags() const; 134 | void setServiceFlags(ServiceFlags flags); 135 | 136 | int exec(); 137 | 138 | void logMessage(const QString &message, MessageType type = Success, 139 | int id = 0, uint category = 0, const QByteArray &data = QByteArray()); 140 | 141 | static QtServiceBase *instance(); 142 | 143 | protected: 144 | 145 | virtual void start() = 0; 146 | virtual void stop(); 147 | virtual void pause(); 148 | virtual void resume(); 149 | virtual void processCommand(int code); 150 | 151 | virtual void createApplication(int &argc, char **argv) = 0; 152 | 153 | virtual int executeApplication() = 0; 154 | 155 | private: 156 | 157 | friend class QtServiceSysPrivate; 158 | QtServiceBasePrivate *d_ptr; 159 | }; 160 | 161 | template 162 | class QtService : public QtServiceBase 163 | { 164 | public: 165 | QtService(int argc, char **argv, const QString &name) 166 | : QtServiceBase(argc, argv, name), app(0) 167 | { } 168 | ~QtService() 169 | { 170 | } 171 | 172 | protected: 173 | Application *application() const 174 | { return app; } 175 | 176 | virtual void createApplication(int &argc, char **argv) 177 | { 178 | app = new Application(argc, argv); 179 | QCoreApplication *a = app; 180 | Q_UNUSED(a); 181 | } 182 | 183 | virtual int executeApplication() 184 | { return Application::exec(); } 185 | 186 | private: 187 | Application *app; 188 | }; 189 | 190 | Q_DECLARE_OPERATORS_FOR_FLAGS(QtServiceBase::ServiceFlags) 191 | 192 | #endif // QTSERVICE_H 193 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtservice.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | !win32:QT += network 4 | win32:LIBS += -luser32 5 | 6 | qtservice-uselib:!qtservice-buildlib { 7 | LIBS += -L$$QTSERVICE_LIBDIR -l$$QTSERVICE_LIBNAME 8 | } else { 9 | HEADERS += $$PWD/qtservice.h \ 10 | $$PWD/qtservice_p.h 11 | SOURCES += $$PWD/qtservice.cpp 12 | win32:SOURCES += $$PWD/qtservice_win.cpp 13 | unix:HEADERS += $$PWD/qtunixsocket.h $$PWD/qtunixserversocket.h 14 | unix:SOURCES += $$PWD/qtservice_unix.cpp $$PWD/qtunixsocket.cpp $$PWD/qtunixserversocket.cpp 15 | } 16 | 17 | win32 { 18 | qtservice-buildlib:shared:DEFINES += QT_QTSERVICE_EXPORT 19 | else:qtservice-uselib:DEFINES += QT_QTSERVICE_IMPORT 20 | } 21 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtservice_p.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSERVICE_P_H 42 | #define QTSERVICE_P_H 43 | 44 | #include 45 | #include "qtservice.h" 46 | 47 | class QtServiceControllerPrivate 48 | { 49 | Q_DECLARE_PUBLIC(QtServiceController) 50 | public: 51 | QString serviceName; 52 | QtServiceController *q_ptr; 53 | }; 54 | 55 | class QtServiceBasePrivate 56 | { 57 | Q_DECLARE_PUBLIC(QtServiceBase) 58 | public: 59 | 60 | QtServiceBasePrivate(const QString &name); 61 | ~QtServiceBasePrivate(); 62 | 63 | QtServiceBase *q_ptr; 64 | 65 | QString serviceDescription; 66 | QtServiceController::StartupType startupType; 67 | QtServiceBase::ServiceFlags serviceFlags; 68 | QStringList args; 69 | 70 | static class QtServiceBase *instance; 71 | 72 | QtServiceController controller; 73 | 74 | void startService(); 75 | int run(bool asService, const QStringList &argList); 76 | bool install(const QString &account, const QString &password); 77 | 78 | bool start(); 79 | 80 | QString filePath() const; 81 | bool sysInit(); 82 | void sysSetPath(); 83 | void sysCleanup(); 84 | class QtServiceSysPrivate *sysd; 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtunixserversocket.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include "qtunixserversocket.h" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #ifndef SUN_LEN 49 | #define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ 50 | +strlen ((ptr)->sun_path)) 51 | #endif 52 | 53 | QtUnixServerSocket::QtUnixServerSocket(const QString &path, QObject *parent) 54 | : QTcpServer(parent) 55 | { 56 | setPath(path); 57 | } 58 | 59 | QtUnixServerSocket::QtUnixServerSocket(QObject *parent) 60 | : QTcpServer(parent) 61 | { 62 | } 63 | 64 | void QtUnixServerSocket::setPath(const QString &path) 65 | { 66 | path_.clear(); 67 | 68 | int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); 69 | if (sock != -1) { 70 | struct sockaddr_un addr; 71 | ::memset(&addr, 0, sizeof(struct sockaddr_un)); 72 | addr.sun_family = AF_UNIX; 73 | ::unlink(path.toLatin1().constData()); // ### This might need to be changed 74 | unsigned int pathlen = strlen(path.toLatin1().constData()); 75 | if (pathlen > sizeof(addr.sun_path)) pathlen = sizeof(addr.sun_path); 76 | ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); 77 | if ((::bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)) != -1) && 78 | (::listen(sock, 5) != -1)) { 79 | setSocketDescriptor(sock); 80 | path_ = path; 81 | } 82 | } 83 | } 84 | 85 | void QtUnixServerSocket::close() 86 | { 87 | QTcpServer::close(); 88 | if (!path_.isEmpty()) { 89 | ::unlink(path_.toLatin1().constData()); 90 | path_.clear(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtunixserversocket.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTUNIXSERVERSOCKET_H 42 | #define QTUNIXSERVERSOCKET_H 43 | 44 | #include 45 | 46 | class QtUnixServerSocket : public QTcpServer 47 | { 48 | Q_OBJECT 49 | public: 50 | QtUnixServerSocket(const QString &path, QObject *parent = 0); 51 | QtUnixServerSocket(QObject *parent = 0); 52 | 53 | void setPath(const QString &path); 54 | void close(); 55 | 56 | private: 57 | QString path_; 58 | }; 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtunixsocket.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include "qtunixsocket.h" 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #ifndef SUN_LEN 49 | #define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ 50 | +strlen ((ptr)->sun_path)) 51 | #endif 52 | 53 | QtUnixSocket::QtUnixSocket(QObject *parent) 54 | : QTcpSocket(parent) 55 | { 56 | } 57 | 58 | bool QtUnixSocket::connectTo(const QString &path) 59 | { 60 | bool ret = false; 61 | int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); 62 | if (sock != -1) { 63 | struct sockaddr_un addr; 64 | ::memset(&addr, 0, sizeof(struct sockaddr_un)); 65 | addr.sun_family = AF_UNIX; 66 | size_t pathlen = strlen(path.toLatin1().constData()); 67 | pathlen = qMin(pathlen, sizeof(addr.sun_path)); 68 | ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); 69 | int err = ::connect(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)); 70 | if (err != -1) { 71 | setSocketDescriptor(sock); 72 | ret = true; 73 | } else { 74 | ::close(sock); 75 | } 76 | } 77 | return ret; 78 | } 79 | -------------------------------------------------------------------------------- /TestWindowsServiceWithLibrarySource/qtservice/qtunixsocket.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTUNIXSOCKET_H 42 | #define QTUNIXSOCKET_H 43 | 44 | #include 45 | 46 | class QtUnixSocket : public QTcpSocket 47 | { 48 | Q_OBJECT 49 | public: 50 | QtUnixSocket(QObject *parent = 0); 51 | 52 | bool connectTo(const QString &path); 53 | }; 54 | 55 | #endif 56 | --------------------------------------------------------------------------------