ホーム

OFF-SOFT.net

OFF-SOFT.net

ウェブやソフトウェアに関するサポート&情報サイトです。サイト構築からソフトウェアの作成、利用まであなたの助けになるかも・・・・しれません。たぶん・・。

Qt (7) QtでWindows Serviceを作る

公開日| 2009年05月30日 | 3 のコメントがあります。
簡単なサンプルの解説
An Interactive Service, A simple Service Controller のいずれのサンプルソースもmain.cppのみです。
[An Interactive Service]
1
2
3
4
5
6
7
8
9
10
11
12
13
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
class InteractiveService : public QtService<QApplication>
{
public:
    InteractiveService(int argc, char **argv);
    ~InteractiveService();
 
protected:
 
    void start();
    void stop();
    void pause();
    void resume();
    void processCommand(int code);
 
private:
    QLabel *gui;
};
 
InteractiveService::InteractiveService(int argc, char **argv)
    : QtService<QApplication>(argc, argv, "Qt Interactive Service"), gui(0)
{
    setServiceDescription("A Qt service with user interface.");
    setServiceFlags(QtServiceBase::CanBeSuspended);
}
 
InteractiveService::~InteractiveService()
{
}
 
void InteractiveService::start()
{
#if defined(Q_OS_WIN)
    if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) &&
        (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) {
        logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error );
        return;
    }
#endif
 
    qApp->setQuitOnLastWindowClosed(false);
 
    gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
    gui->move(QApplication::desktop()->availableGeometry().topLeft());
    gui->show();
}
 
void InteractiveService::stop()
{
    delete gui;
}
 
void InteractiveService::pause()
{
    if (gui)
	gui->hide();
}
 
void InteractiveService::resume()
{
    if (gui)
	gui->show();
}
 
void InteractiveService::processCommand(int code)
{
    gui->setText("Command code " + QString::number(code));
    gui->adjustSize();
}

ここでは、InteractiveServiceのクラスのみを抜粋しています。
mainルーチンでは、このクラスをnewして、exec()を起動しているだけです。

このクラスの特徴は、QtService<QApplication>の継承と以下のメソッドです。

  • void start();
    -- サービスが開始した時のこのメソッドが動きます。
  • void stop();
    -- サービスが停止した時のこのメソッドが動きます。
  • void pause();
    -- サービスが一時停止した時のこのメソッドが動きます。
  • void resume();
    -- サービスが再開した時のこのメソッドが動きます。
  • void processCommand(int code);
    -- サービスがユーザからのコマンドを受信した時のこのメソッドが動きます。

22行目あたりのコンストラクタで、
サービスの概要を登録(setServiceDescription),
サービスの機能の設定(setServiceFlags)-一時停止を可と設定している,
ぐらいでしょうか。

あとは、解説するほどのソースコードではないように思います。

[A simple Service Controller]
1
2
3
4
5
6
7
8
9
10
11
12
13
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
83
84
85
86
87
88
89
90
91
92
93
94
int processArgs(int argc, char **argv)
{
    if (argc > 2) {
        QString arg1(argv[1]);
	if (arg1 == QLatin1String("-i") ||
            arg1 == QLatin1String("-install")) {
	    if (argc > 2) {
                QString account;
                QString password;
		QString path(argv[2]);
                if (argc > 3)
                    account = argv[3];
                if (argc > 4)
                    password = argv[4];
                printf("The service %s installed.\n",
                       (QtServiceController::install(path, account, password) ? "was" : "was not"));
                return 0;
            }
        } else {
            QString serviceName(argv[1]);
            QtServiceController controller(serviceName);
            QString option(argv[2]);
            if (option == QLatin1String("-u") ||
                option == QLatin1String("-uninstall")) {
                printf("The service \"%s\" %s uninstalled.\n",
                            controller.serviceName().toLatin1().constData(),
                            (controller.uninstall() ? "was" : "was not"));
                return 0;
            } else if (option == QLatin1String("-s") ||
                       option == QLatin1String("-start")) {
                QStringList args;
                for (int i = 3; i < argc; ++i)
                    args.append(QString::fromLocal8Bit(argv[i]));
                printf("The service \"%s\" %s started.\n",
                       controller.serviceName().toLatin1().constData(),
                            (controller.start(args) ? "was" : "was not"));
                return 0;
            } else if (option == QLatin1String("-t") ||
                       option == QLatin1String("-terminate")) {
                printf("The service \"%s\" %s stopped.\n",
                       controller.serviceName().toLatin1().constData(),
                       (controller.stop() ? "was" : "was not"));
                return 0;
            } else if (option == QLatin1String("-p") ||
                    option == QLatin1String("-pause")) {
                printf("The service \"%s\" %s paused.\n",
                       controller.serviceName().toLatin1().constData(),
                       (controller.pause() ? "was" : "was not"));
                return 0;
            } else if (option == QLatin1String("-r") ||
                       option == QLatin1String("-resume")) {
                printf("The service \"%s\" %s resumed.\n",
                       controller.serviceName().toLatin1().constData(),
                       (controller.resume() ? "was" : "was not"));
                return 0;
            } else if (option == QLatin1String("-c") ||
                       option == QLatin1String("-command")) {
                if (argc > 3) {
                    QString codestr(argv[3]);
                    int code = codestr.toInt();
                    printf("The command %s sent to the service \"%s\".\n",
                           (controller.sendCommand(code) ? "was" : "was not"),
                           controller.serviceName().toLatin1().constData());
                    return 0;
                }
            } else if (option == QLatin1String("-v") ||
                    option == QLatin1String("-version")) {
                bool installed = controller.isInstalled();
                printf("The service\n"
                        "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData());
                printf("is %s", (installed ? "installed" : "not installed"));
                printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running"));
                if (installed) {
                    printf("path: %s\n", controller.serviceFilePath().toLatin1().data());
                    printf("description: %s\n", controller.serviceDescription().toLatin1().data());
                    printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual");
                }
                return 0;
            }
        }
    }
    printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n"
            "\t-i(nstall) PATH\t: Install the service\n"
            "\t-v(ersion)\t: Print status of the service\n"
            "\t-u(ninstall)\t: Uninstall the service\n"
            "\t-s(tart)\t: Start the service\n"
            "\t-t(erminate)\t: Stop the service\n"
            "\t-p(ause)\t: Pause the service\n"
            "\t-r(esume)\t: Resume the service\n"
            "\t-c(ommand) CODE\t: Send a command to the service\n"
            "\t-h(elp)\t\t: Print this help info\n"
            "\t-w(ait)\t\t: Wait for keypress when done\n");
    return 0;
}


ここでは、A simple Service Controllerの内部サブルーチンprocessArgsのみを抜粋しています。
mainルーチンでは、このサブルーチンを起動しているだけです。

このサブルーチンで、コマンドパラメータにより、分岐がありますが、ほとんど、解説は不要と思います。
ほとんどが、QtServiceController クラスオブジェクトに対して、メソッドをコールするだけです。

その結果に対して、コンソールへ結果表示を行っています。
簡単にQtServiceController クラスのメソッドを解説しておくと以下のとおりです。


  • bool start ( const QStringList & arguments )
    -- サービスを開始する時のこのメソッドを起動します。
  • bool start ()
    -- サービスを開始する時のこのメソッドを起動します。
  • bool stop ()
    -- サービスを停止する時のこのメソッドを起動します。
  • bool pause ()
    -- サービスを一時停止する時のこのメソッドを起動します。
  • bool resume ()
    -- サービスを再開する時のこのメソッドを起動します。
  • bool sendCommand ( int code )
    -- サービスへユーザからのコマンドを送信する時のこのメソッドを起動します。
  • bool uninstall ()
    -- サービスをサービス削除(uninstall)する時のこのメソッドを起動します。
  • bool install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )
    -- サービスをサービス登録(install)する時のこのメソッドを起動します。

細かいメソッドの動作については、ドキュメントを参照された方が間違いがないです。
http://doc.trolltech.com/solutions/4/qtservice/index.html

もっと、Qt関連について詳しく知りたい方は、以下の本なども良いと思います。
Qtに関する日本語の本が少ないですね。「入門書」は、さすがに、このページを読まれるくらいの方は不要だと思います。
やっぱり、本+ネット+試してみる!!の3本柱でやっていく以外にないように思います。


コメント

3 のコメントがあります。 “Qt (7) QtでWindows Serviceを作る”


  1. Lwin Htoo Ko
    2010年10月15日 @ 16:06:12

    I tried to compile the qtservice framework. But after nmake, I got the list of errors.

    I am using Qt4.7, Visual Studio 2008 and Window XP.

    C:\Qt\QtService2.6_1>qmake

    C:\Qt\QtService2.6_1>nmake

    Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
    Copyright (C) Microsoft Corporation. All rights reserved.

    cd buildlib\ && “C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nma
    ke.exe” -f Makefile

    Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
    Copyright (C) Microsoft Corporation. All rights reserved.

    c:\Qt\Qt4.7WinCE\bin\qmake.exe -o Makefile buildlib.pro
    “C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nmake.exe” -f Makef
    ile.Debug

    Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
    Copyright (C) Microsoft Corporation. All rights reserved.

    cl -c -nologo -Zm200 -Zc:wchar_t- -DDEBUG -D_DEBUG -Zi -MDd -EHs-c- -W3
    -w34100 -w34189 -DUNDER_CE -DWINCE -D_WINDOWS -D_UNICODE -DUNICODE -D_WIN32 -DQT
    _NO_PRINTER -DQT_NO_PRINTDIALOG -DARMV4I -D_ARMV4I_ -Darmv4i -D_ARM_ -DARM -D_M_
    ARM -DARM -D__arm__ -DQ_OS_WINCE_WM -DQT_NO_PRINTER -DQT_NO_PRINTDIALOG -D_WIN32
    _WCE=0x502 -DQT_QTSERVICE_EXPORT -DQT_DLL -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD
    _SUPPORT -DQT_NO_DYNAMIC_CAST -I”..\..\Qt4.7WinCE\include\QtCore” -I”..\..\Qt4.7
    WinCE\include\QtGui” -I”..\..\Qt4.7WinCE\include” -I”..\src” -I”..\..\Qt4.7WinCE
    \include\ActiveQt” -I”debug” -I”..\..\Qt4.7WinCE\mkspecs\default” -Fodebug\ @C:\
    DOCUME~1\user\LOCALS~1\Temp\nm6.tmp
    qtservice_win.cpp
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2260) : error C2
    733: second C linkage of overloaded function ‘InterlockedIncrement’ not allowed
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2258) :
    see declaration of ‘InterlockedIncrement’
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2267) : error C2
    733: second C linkage of overloaded function ‘InterlockedDecrement’ not allowed
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2265) :
    see declaration of ‘InterlockedDecrement’
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2275) : error C2
    733: second C linkage of overloaded function ‘InterlockedExchange’ not allowed
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2272) :
    see declaration of ‘InterlockedExchange’
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2286) : error C2
    733: second C linkage of overloaded function ‘InterlockedExchangeAdd’ not allowe
    d
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2283) :
    see declaration of ‘InterlockedExchangeAdd’
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2295) : error C2
    733: second C linkage of overloaded function ‘InterlockedCompareExchange’ not al
    lowed
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winbase.h(2291) :
    see declaration of ‘InterlockedCompareExchange’
    ..\src\qtservice_win.cpp(718) : error C2065: ‘WM_ENDSESSION’ : undeclared identi
    fier
    NMAKE : fatal error U1077: ‘”C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN
    \cl.EXE”‘ : return code ‘0x2’
    Stop.
    NMAKE : fatal error U1077: ‘”C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN
    \nmake.exe”‘ : return code ‘0x2’
    Stop.
    NMAKE : fatal error U1077: ‘cd’ : return code ‘0x2’
    Stop.

    Is there solution for that?

    Thanks

  2. 管理人
    2010年10月15日 @ 19:48:36

    Hi Ko,
    I could compile qt service 2.6.1 with Qt4.7, Visual Studio 2008 and Window XP.
    You might have problem with your environment , or forget ‘C:QtQtService2.6_1> configure -library’ before ‘qmake’.
    If you want static library, you should do it without parameter ( ex) ‘C:QtQtService2.6_1> configure’ ).

    OK?

  3. weihao.ma
    2010年12月28日 @ 02:03:48

    hi guy, the InteractiveService app works fine to me, but i can’t debug the code in InteractiveService::start() function, what’s the matter with this problem?

コメントをどうぞ







  • はてなブックマークへ追加する
  • Facebookでシェアする
  • twitter でつぶやく
  • Google Plusでシェアする
  • Pocketでシェアする
ページトップへ