• 3860阅读
  • 2回复

[提问]【已解决】如何在Windows服务中使用Qt [复制链接]

上一主题 下一主题
离线ninsun
 

只看楼主 倒序阅读 楼主  发表于: 2015-12-02
我之前的代码写错了…………才导致的我测试失败……其实按照正常逻辑也是可以使用的……
不过这个代码也能工作,所以就无所谓了……
离线ninsun

只看该作者 1楼 发表于: 2015-12-02
果真……
微软的StartServiceCtrlDispatcher这个API可以在另一个线程中调用……
于是……在服务中使用Qt变的超级简单……
写这么一个函数:
  1. void startServiceCtrlDispatcher()
  2. {
  3.     SERVICE_TABLE_ENTRY ServiceTable[2];
  4.     ServiceTable[0].lpServiceName = TEXT(SERVICE_NAME);
  5.     ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;
  6.     ServiceTable[1].lpServiceName = NULL;
  7.     ServiceTable[1].lpServiceProc = NULL;
  8.     StartServiceCtrlDispatcher(ServiceTable);
  9. }
然后在main函数中调用:
  1. QtConcurrent::run(startServiceCtrlDispatcher);
接着在写一个函数,也就是startServiceCtrlDispatcher定义的服务主函数service_main
  1. void WINAPI service_main(int argc, char** argv)
  2. {
  3.     ServiceStatus.dwServiceType = SERVICE_WIN32;
  4.     ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  5.     ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
  6.     ServiceStatus.dwWin32ExitCode = 0;
  7.     ServiceStatus.dwServiceSpecificExitCode = 0;
  8.     ServiceStatus.dwCheckPoint = 0;
  9.     ServiceStatus.dwWaitHint = 0;
  10.     hServiceStatusHandle = RegisterServiceCtrlHandler(TEXT(SERVICE_NAME), ServiceHandler);
  11.     if (hServiceStatusHandle == 0)
  12.     {
  13.         DWORD nError = GetLastError();
  14.     }
  15.     ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  16.     ServiceStatus.dwCheckPoint = 0;
  17.     ServiceStatus.dwWaitHint = 9000;
  18.     if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
  19.     {
  20.         DWORD nError = GetLastError();
  21.     }
  22. }
嗯,别忘了主函数里还说了一个叫做ServiceHandler的东东,这个牵扯到你的服务能否被关闭的:
  1. void WINAPI ServiceHandler(DWORD fdwControl)
  2. {
  3.     switch (fdwControl)
  4.     {
  5.     case SERVICE_CONTROL_STOP:
  6.     case SERVICE_CONTROL_SHUTDOWN:
  7.         ServiceStatus.dwWin32ExitCode = 0;
  8.         ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  9.         ServiceStatus.dwCheckPoint = 0;
  10.         ServiceStatus.dwWaitHint = 0;
  11.         uaquit = 1;
  12.         //add you quit code here
  13.         if (g_pApp != nullptr)
  14.         {
  15.             g_pApp->exit();
  16.         }
  17.         break;
  18.     default:
  19.         return;
  20.     };
  21.     if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
  22.     {
  23.         DWORD nError = GetLastError();
  24.     }
  25. }


离线ninsun

只看该作者 2楼 发表于: 2015-12-02
这里贴上完整的main.cpp代码吧……

/*******************************************************************************
Written by:   shiyang sun
First: you can used this code free,absolutely free!
Second:of course,you can remove this header unconstrained!
but this header might useful if you sometimes want to kick my ass or praise me.

Copyright:none
Get more message on:http://blog.sina.com.cn/lipfreedom
Address:sunshiyang shenzhen city guangdong province china
E-mail:zyy6569@163.com

Create date:2010/10/14

Modify by: Zheng Xu 2015-12-2
********************************************************************************/

#include "Windows.h"

#include <QtCore/QCoreApplication>
#include <QtConcurrent/QtConcurrent>
#include "Observer.h"

#define SERVICE_NAME "Algalon"

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hServiceStatusHandle;
void WINAPI service_main(int argc, char** argv);
void WINAPI ServiceHandler(DWORD fdwControl);

TCHAR szSvcName[80];
SC_HANDLE schSCManager;
SC_HANDLE schService;
int uaquit;

std::fstream g_log;

QCoreApplication *g_pApp = nullptr;

void WINAPI ServiceHandler(DWORD fdwControl)
{
    switch (fdwControl)
    {
    case SERVICE_CONTROL_STOP:
    case SERVICE_CONTROL_SHUTDOWN:
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ServiceStatus.dwCheckPoint = 0;
        ServiceStatus.dwWaitHint = 0;
        uaquit = 1;
        //add you quit code here
        if (g_pApp != nullptr)
        {
            g_pApp->exit();
        }
        break;
    default:
        return;
    };
    if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
    {
        DWORD nError = GetLastError();
    }
}

void WINAPI service_main(int argc, char** argv)
{
    ServiceStatus.dwServiceType = SERVICE_WIN32;
    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 0;
    hServiceStatusHandle = RegisterServiceCtrlHandler(TEXT(SERVICE_NAME), ServiceHandler);
    if (hServiceStatusHandle == 0)
    {
        DWORD nError = GetLastError();
    }

    ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 9000;
    if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
    {
        DWORD nError = GetLastError();
    }
}
//*********************************************************
//Functiopn:            IsInstalled
//Description:            判断服务是否已经被安装
//Calls:
//Called By:
//Table Accessed:
//Table Updated:
//Input:
//Output:
//Return:
//Others:
//History:
//            <author>niying <time>2006-8-10        <version>        <desc>
//*********************************************************
BOOL IsInstalled()
{
    BOOL bResult = FALSE;

    //打开服务控制管理器
    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hSCM != NULL)
    {
        //打开服务
        SC_HANDLE hService = ::OpenService(hSCM, TEXT(SERVICE_NAME), SERVICE_QUERY_CONFIG);
        if (hService != NULL)
        {
            bResult = TRUE;
            ::CloseServiceHandle(hService);
        }
        ::CloseServiceHandle(hSCM);
    }
    return bResult;
}

//*********************************************************
//Functiopn:            Install
//Description:            安装服务函数
//Calls:
//Called By:
//Table Accessed:
//Table Updated:
//Input:
//Output:
//Return:
//Others:
//History:
//            <author>niying <time>2006-8-10        <version>        <desc>
//*********************************************************
BOOL Install()
{
    if (IsInstalled())
        return TRUE;

    //打开服务控制管理器
    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM == NULL)
    {
        MessageBox(NULL, TEXT("Couldn't open service manager"), TEXT(SERVICE_NAME), MB_OK);
        return FALSE;
    }

    // Get the executable file path
    TCHAR szFilePath[MAX_PATH];
    ::GetModuleFileName(NULL, szFilePath, MAX_PATH);

    //创建服务
    SC_HANDLE hService = ::CreateService(
        hSCM, TEXT(SERVICE_NAME), TEXT(SERVICE_NAME),
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, TEXT(""), NULL, NULL);

    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        MessageBox(NULL, TEXT("Couldn't create service"), TEXT(SERVICE_NAME), MB_OK);
        return FALSE;
    }

    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
    return TRUE;
}

//*********************************************************
//Functiopn:            Uninstall
//Description:            删除服务函数
//Calls:
//Called By:
//Table Accessed:
//Table Updated:
//Input:
//Output:
//Return:
//Others:
//History:
//            <author>niying <time>2006-8-10        <version>        <desc>
//*********************************************************
BOOL Uninstall()
{
    if (!IsInstalled())
        return TRUE;

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (hSCM == NULL)
    {
        MessageBox(NULL, TEXT("Couldn't open service manager"), TEXT(SERVICE_NAME), MB_OK);
        return FALSE;
    }

    SC_HANDLE hService = ::OpenService(hSCM, TEXT(SERVICE_NAME), SERVICE_STOP | DELETE);

    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        MessageBox(NULL, TEXT("Couldn't open service"), TEXT(SERVICE_NAME), MB_OK);
        return FALSE;
    }
    SERVICE_STATUS status;
    ::ControlService(hService, SERVICE_CONTROL_STOP, &status);

    //删除服务
    BOOL bDelete = ::DeleteService(hService);
    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);

    if (bDelete)
        return TRUE;

    return FALSE;
}

void startServiceCtrlDispatcher()
{
    SERVICE_TABLE_ENTRY ServiceTable[2];

    ServiceTable[0].lpServiceName = TEXT(SERVICE_NAME);
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;

    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;

    StartServiceCtrlDispatcher(ServiceTable);
}

//do not change main function
int main(int argc, char *argv[])
{
    g_log.open("c:\\algalon.log", std::ios_base::app);
    if (argc == 2)
    {
        if (strcmp(argv[1], "-i") == 0 ||
            strcmp(argv[1], "--install") == 0)
        {
            Install();
            return 0;
        }
        else if (strcmp(argv[1], "-u") == 0 ||
            strcmp(argv[1], "--uninstall") == 0)
        {
            Uninstall();
            return 0;
        }
    }

    g_pApp = new QCoreApplication(argc, argv);
    g_log << "QCoreApplication create\n";
    g_log.flush();
    // 在这里,你可以创建任意你需要的Qt类——不包括窗口类……

    // 在另一个线程中启动服务的控制分派机线程
    QtConcurrent::run(startServiceCtrlDispatcher);
    g_log << "ServiceCtrlDispatcher start\n";
    g_log.flush();

    int _rt = g_pApp->exec();
    g_log << "QCoreApplication exit\n";
    g_log.flush();

    delete g_pApp;

    return _rt;
}
快速回复
限100 字节
 
上一个 下一个