Windows-創(chuàng)建服務(wù)

服務(wù)創(chuàng)建步驟

  1. 設(shè)置服務(wù)入口函數(shù)ServiceMain,
    StartServiceCtrlDispatcher
  2. 注冊服務(wù)控制處理器念秧,接收SCM的命令强霎。
    RegisterServiceCtrlHandler
  3. 服務(wù)執(zhí)行,等待停止膏燃,反饋狀態(tài)刷允。

代碼

#define SERVICE_NAME _T("MyXzmService")
#define LOGFILE _T("E:\\memstatus.txt")

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

void WINAPI ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int WriteToLog(TCHAR *str);
int InitService();

// 文章: https://blog.csdn.net/nodeathphoenix/article/details/24181509
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    OutputDebugString(_T("-------_tWinMain--------"));

    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = SERVICE_NAME;   // 指向表示服務(wù)名稱字符串的指針;當(dāng)定義了多個(gè)服務(wù)時(shí)奶躯,那么這個(gè)域必須指定; 
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;               // 指向服務(wù)主函數(shù)的指針(服務(wù)入口點(diǎn))亿驾; 

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

    StartServiceCtrlDispatcher(ServiceTable);
    return 0;
}

// 該函數(shù)是服務(wù)的入口點(diǎn)嘹黔。它運(yùn)行在一個(gè)單獨(dú)的線程當(dāng)中,這個(gè)線程是由控制分派器創(chuàng)建的
void WINAPI ServiceMain(int argc, char** argv){
    OutputDebugString(_T("ServiceMain start"));
    ServiceStatus.dwServiceType = SERVICE_WIN32;            // 指示服務(wù)類型颊乘,創(chuàng)建 Win32 服務(wù)参淹。賦值 SERVICE_WIN32 ; 
    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;   // 指定服務(wù)的當(dāng)前狀態(tài)
    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;   // 這個(gè)域通知 SCM 服務(wù)接受哪個(gè)域
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 0;

    // 為服務(wù)注冊控制處理器,兩個(gè)參數(shù)傳遞給此函數(shù):服務(wù)名和指向 ControlHandlerfunction 的指針乏悄。 
    // 注冊完控制處理器之后浙值,獲得狀態(tài)句柄(hStatus)。通過調(diào)用 SetServiceStatus 函數(shù)檩小,用 hStatus 向 SCM 報(bào)告服務(wù)的狀態(tài)开呐。 
    hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)ControlHandler);
    if (hStatus == (SERVICE_STATUS_HANDLE)0)
    {
        // Registering Controll Handler failed;
        return;
    }
    OutputDebugString(_T("ServiceMain InitService"));
    int error = InitService();
    if (error)
    {
        OutputDebugString(_T("ServiceMain InitService fail."));
        // 初始化失敗,終止服務(wù)
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ServiceStatus.dwWin32ExitCode = -1;
        SetServiceStatus(hStatus, &ServiceStatus);
        // 退出ServiceMan
        return;
    }
    ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hStatus, &ServiceStatus);

    //  
    // 不斷獲取內(nèi)存大小寫入文件
    while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
    {
        TCHAR buffer[100];
        MEMORYSTATUS memory;
        GlobalMemoryStatus(&memory);
        _stprintf_s(buffer, _T("memory.dwAvailPhys=%d"), memory.dwAvailPhys);
        int result = WriteToLog(buffer);
        if (result)
        {
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            ServiceStatus.dwWin32ExitCode = -1;
            SetServiceStatus(hStatus, &ServiceStatus);
            return;
        }

        // 等待10s
        Sleep(10000);
    }
}

void ControlHandler(DWORD request){
    switch (request)
    {
    case SERVICE_CONTROL_STOP:
        WriteToLog(_T("Monitoring stoppend."));
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ServiceStatus.dwWin32ExitCode = 0;
        SetServiceStatus(hStatus, &ServiceStatus);
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        WriteToLog(_T("Monitoring shutdown."));
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ServiceStatus.dwWin32ExitCode = 0;
        SetServiceStatus(hStatus, &ServiceStatus);
        break;
    default:
        break;
    }
}

int InitService(){
    int result;
    result = WriteToLog(_T("Monitoring started."));
    return result;
}

int WriteToLog(TCHAR *str){
    FILE * log;
    _tfopen_s(&log, LOGFILE, _T("a+"));
    if (log == NULL)
    {
        return -1;
    }
    _ftprintf(log,_T("%s\n"), str);
    fclose(log);

    return 0;
}

SC.exe管理Service

sc命令的語法格式:

sc create MyService binpath= e:/xxx/MyService.exe ;創(chuàng)建服務(wù)MyService
sc start MyService ;啟動(dòng)服務(wù)
sc stop MyService ;停止服務(wù)
sc delete MyService ; 刪除服務(wù)
sc config 服務(wù)名 start= auto|demand|disabled ;修改服務(wù)啟動(dòng)類型规求。start參數(shù)的值可以是demand(手動(dòng))筐付、disabled(禁用),auto(自動(dòng))阻肿。

參考

C++編寫Windows服務(wù)
https://blog.csdn.net/nodeathphoenix/article/details/24181509

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓦戚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子丛塌,更是在濱河造成了極大的恐慌较解,老刑警劉巖畜疾,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異印衔,居然都是意外死亡啡捶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門奸焙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞎暑,“玉大人,你說我怎么就攤上這事与帆×硕模” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵鲤桥,是天一觀的道長揍拆。 經(jīng)常有香客問我渠概,道長茶凳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任播揪,我火速辦了婚禮贮喧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猪狈。我一直安慰自己箱沦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布雇庙。 她就那樣靜靜地躺著谓形,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疆前。 梳的紋絲不亂的頭發(fā)上寒跳,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音竹椒,去河邊找鬼童太。 笑死,一個(gè)胖子當(dāng)著我的面吹牛胸完,可吹牛的內(nèi)容都是我干的书释。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼赊窥,長吁一口氣:“原來是場噩夢啊……” “哼爆惧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锨能,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對情侶失蹤扯再,失蹤者是張志新(化名)和其女友劉穎肴捉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叔收,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡齿穗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饺律。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窃页。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖复濒,靈堂內(nèi)的尸體忽然破棺而出脖卖,到底是詐尸還是另有隱情,我是刑警寧澤巧颈,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布畦木,位于F島的核電站,受9級(jí)特大地震影響砸泛,放射性物質(zhì)發(fā)生泄漏十籍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一唇礁、第九天 我趴在偏房一處隱蔽的房頂上張望勾栗。 院中可真熱鬧,春花似錦盏筐、人聲如沸围俘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽界牡。三九已至,卻和暖如春漾抬,著一層夾襖步出監(jiān)牢的瞬間宿亡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工奋蔚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留她混,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓泊碑,卻偏偏與公主長得像坤按,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子馒过,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評(píng)論 25 707
  • 在此特此聲明:一下所有鏈接均來自互聯(lián)網(wǎng)臭脓,在此記錄下我的查閱學(xué)習(xí)歷程,感謝各位原創(chuàng)作者的無私奉獻(xiàn) 腹忽! 技術(shù)一點(diǎn)一點(diǎn)積...
    遠(yuǎn)航的移動(dòng)開發(fā)歷程閱讀 11,081評(píng)論 12 197
  • 本系列出于AWeiLoveAndroid的分享来累,在此感謝砚作,再結(jié)合自身經(jīng)驗(yàn)查漏補(bǔ)缺,完善答案嘹锁。以成系統(tǒng)葫录。 Andro...
    濟(jì)公大將閱讀 1,816評(píng)論 2 10
  • 夜深人靜的時(shí)候摔竿,往往最容易觸動(dòng)那根敏感的神經(jīng)面粮。往事,如潮水一般涌動(dòng)過來继低。 我有3個(gè)qq號(hào)熬苍,一個(gè)大號(hào),一個(gè)小號(hào)袁翁,還有...
    b1ff1c7ee1aa閱讀 323評(píng)論 0 1
  • 曉雪去海邊旅游柴底,遇到一位正在打漁的漁夫,曉雪姐了解到他幾十年日復(fù)一日梦裂,每天的工作就是四點(diǎn)鐘出海撒網(wǎng)打漁似枕,五...
    從源王有鵬閱讀 227評(píng)論 0 2