程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 寫一個Windows上的守護進程(6)Windows服務,windows守護進程

寫一個Windows上的守護進程(6)Windows服務,windows守護進程

編輯:C++入門知識

寫一個Windows上的守護進程(6)Windows服務,windows守護進程


寫一個Windows上的守護進程(6)Windows服務

守護進程因為要開機啟動,還要高權限,所以我就把它做成Windows服務了。

關於Windows服務的官方文檔,大家可以看https://msdn.microsoft.com/en-us/library/windows/desktop/ms686953(v=vs.85).aspx。

 

總的來說,服務的行為區別於普通應用程序的地方有以下幾點:

1. 一般來說,服務是運行於System用戶下的,當然也可以自己指定。也就是說服務可以在無用戶登錄的情況下運行

2. 一般來說,服務是沒有用戶交互的

3. 服務可以通過服務管理器管理(啟動、停止等等)

服務程序的編寫區別於普通應用程序的地方有以下幾點:

1. 服務程序執行的主體是ServiceMain函數,你需要在main函數中調用StartServiceCtrlDispatcher注冊你的ServiceMain函數。也就是說你的功能代碼應寫在你的ServiceMain函數中。StartServiceCtrlDispatcher直到服務停止才會返回

2. 在ServiceMain函數中,你要及時向服務管理器報告自己的狀態,好讓其向用戶展示自己。一般來說,ServiceMain函數的流程是這樣的:

class CWin32Service : public Singleton<CWin32Service> { friend class Singleton<CWin32Service>; private: CWin32Service(void); public: ~CWin32Service(void); public: bool init(const ServiceInfo& info); typedef std::vector<tstring> ArgList; typedef boost::function<bool(const ArgList&)> StartingFunction;//ArgList是應用程序的命令行參數 typedef boost::function<void(const ArgList&)> ServiceFunction; void register_starting_function(const StartingFunction& f); void register_running_function(const ServiceFunction& f); void register_control_code_function(const DWORD c, const ServiceFunction& f); bool go(); };

上面是其主要對外接口,接口基本上對應於上面ServiceMain的流程:

l Init:告知服務名稱等信息

l StartingFunction:通常都是做好初始化工作,加載配置什麼的,然後啟動工作線程

l running_function:通常都是等待退出信號,等待工作線程結束什麼的。此函數返回意味著服務結束了

l control_code_function:這是要處理的控制代碼。一般我們都會要處理stop control code的,不過你不設置也沒關系

l go:這個就是調用StartServiceCtrlDispatcher注冊ServiceMain函數。直到服務結束才會返回。ServiceMain中就是按流程調用上面注冊的函數和報告狀態

 

當然我們不能只完成服務程序的編寫,還要讓用戶能安裝服務、啟動服務、通知服務、卸載服務的方法,我把這些提供在了命令行裡:

l DaemonSvc.exe –intsall

l DaemonSvc.exe –start

l DaemonSvc.exe –stop

l DaemonSvc.exe –remove

這些動作的實現都被我拎出來放到了ServiceUtil裡面。

 

服務是沒辦法在VC裡直接按F5調試的,你那樣啟動起來的不是服務,是普通應用程序。為了方便調試,我把服務分了兩種模式:普通模式,服務模式:不帶參數啟動起來的是普通模式,帶-svc參數起來的是服務模式(所以你會看到我實現服務安裝的時候,給的命令行後面是有-svc的)。普通模式下,不走StartServiceCtrlDispatcher,直接ServiceMain,並且不和服務管理器打交道。

普通模式開發調試完畢後,可以安裝啟動服務,看下服務模式下是不是正常,此時也可以用VC附加到服務進程上調試。

 

服務類的使用示例:

int main(int argc, char * argv[])
{
    InitLog("", 0, LOG_DEBUG);
    //try to enable debug privilege for querying other processes' info
    WindowsUtil::set_privilege(SE_DEBUG_NAME, true);

    ServiceInfo si;
    si.name = TSTR("DaemonSvc");
    si.display_name = si.name;

    CWin32Service& svc = CWin32Service::get_instance_ref();

    if (!svc.init(si))
    {
        ErrorLog("init service fail");
    }
    else
    {
        InfoLog("init service success");

        svc.register_starting_function(starting);
        svc.register_running_function(running);
        svc.register_control_code_function(SERVICE_CONTROL_STOP, stopping);
        svc.register_control_code_function(200, restart);

        if (!svc.go())
        {
            ErrorLog("make service go fail");
        }
        else
        {
            InfoLog("everything is OK");
        }
    }

    return 0;
}

 

源碼:https://git.oschina.net/mkdym/DaemonSvc.git (主)&& https://github.com/mkdym/DaemonSvc.git (提升逼格用的)。

 

 

2015年11月7日星期六

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved