• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 14, 文章 - 0, 評(píng)論 - 3, 引用 - 0
            數(shù)據(jù)加載中……

            [轉(zhuǎn)貼]Windows服務(wù)程序編程入門(mén)

            Windows服務(wù)程序是在操作系統(tǒng)后臺(tái)運(yùn)行的一種程序,要開(kāi)發(fā)該類(lèi)程序,需要使用windows提供的service API,
            MSDN上有對(duì)該類(lèi)api的詳細(xì)描述,這里簡(jiǎn)單介紹下windows服務(wù)編程的具體步驟:

            1.window服務(wù)的安裝
            鼠標(biāo)右擊"我的電腦 -〉管理"可以打開(kāi)計(jì)算機(jī)管理器,進(jìn)入到服務(wù)控制管理界面,這里可以看到所有的服務(wù)
            列表(注意所有這些服務(wù)名都存儲(chǔ)在window系統(tǒng)數(shù)據(jù)庫(kù)中),可以選擇每一項(xiàng)服務(wù)進(jìn)行啟動(dòng)或停止等管理操作,我們第一部介紹的就是如何把一項(xiàng)新的服務(wù)寫(xiě)入這個(gè)服務(wù)控制管理頁(yè)面里,這里我們使用一個(gè)installSercices函數(shù)實(shí)現(xiàn)這一功能,該函數(shù)使用OpenSCManager(WIN API)打開(kāi)服務(wù)控制管理器獲取的句柄,然后使用CreateService(WIN API)來(lái)創(chuàng)建一個(gè)新的服務(wù)。
            ///安裝服務(wù)
            int installServices(const char* szName)
            {

            ///這里的path是利用服務(wù)啟動(dòng)的對(duì)應(yīng)的exe程序路徑
            ///一般情況下,啟動(dòng)一個(gè)服務(wù),任務(wù)管理器中你可以可到該服務(wù)對(duì)應(yīng)的進(jìn)程被打開(kāi)運(yùn)行起來(lái)。
            char szPath[1024]={0};
            if(!GetModuleFileName(NULL, szPath, 1024))
            return -1;

            ///打開(kāi)服務(wù)控制管理器
            SC_HANDLE hSCM = OpenSCManager(
            NULL, //主機(jī)名,NULL表示本地
            NULL, //服務(wù)數(shù)據(jù)庫(kù)名,NULL默認(rèn)為 SERVICES_ACTIVE_DATABASE
            SC_MANAGER_ALL_ACCESS //期待獲取到服務(wù)管理器權(quán)限,具體權(quán)限參考msdn
            );
            if(!hSCM)
            return -1;

            ///創(chuàng)建一個(gè)服務(wù)
            SC_HANDLE hSS = CreateService(
            hSCM,
            szName, ///服務(wù)名
            szName, ///服務(wù)控制管理器上的顯示名
            SC_MANAGER_ALL_ACCESS, ///服務(wù)控制權(quán)限
            SERVICE_WIN32_OWN_PROCESS, /// 服務(wù)類(lèi)型
            SERVICE_DEMAND_START, ///服務(wù)啟動(dòng)方式SERVICE_DEMAND_START
            SERVICE_ERROR_NORMAL, ///服務(wù)啟動(dòng)錯(cuò)誤處理方式
            szPath, ///服務(wù)程序路徑
            NULL,
            NULL,
            NULL, ///依賴(lài)服務(wù)
            NULL, ///服務(wù)所屬用戶(hù)
            NULL ///用戶(hù)密碼
            );
            if(!hSS)
            return -1;

            if(hSS)
            CloseServiceHandle(hSS);

            if(hSCM)
            CloseServiceHandle(hSCM);

            return 0;
            }

            2. 服務(wù)的啟動(dòng)
            我們編寫(xiě)一個(gè)ServiceStart用來(lái)啟動(dòng)服務(wù),啟動(dòng)服務(wù)的主要win api為OpenService 打開(kāi)已存在的服務(wù)獲取服務(wù)句柄,QueryServiceStatus 獲取服務(wù)當(dāng)前狀態(tài),StartService來(lái)啟動(dòng)服務(wù),一般情況下,啟動(dòng)一個(gè)服務(wù),任務(wù)管理器中你可以可到該服務(wù)對(duì)應(yīng)的進(jìn)程被打開(kāi)運(yùn)行起來(lái)。像啟動(dòng)apache服務(wù)對(duì)應(yīng)的進(jìn)程為httpd.exe等。該函數(shù)就像你在服務(wù)控制管理器中選中某一服務(wù)項(xiàng)后右鍵啟動(dòng)。
            ///啟動(dòng)服務(wù)
            int ServiceStart(const char* szName)
            {
            ///打開(kāi)服務(wù)控制管理器
            SC_HANDLE hSCM = OpenSCManager(
            NULL, //主機(jī)名,NULL表示本地
            NULL, //服務(wù)數(shù)據(jù)庫(kù)名,NULL默認(rèn)為 SERVICES_ACTIVE_DATABASE
            SC_MANAGER_ALL_ACCESS //期待獲取到服務(wù)管理器權(quán)限,具體權(quán)限參考msdn
            );
            if(!hSCM)
            return -1;

            ///打開(kāi)服務(wù)
            SC_HANDLE hSS = OpenService(
            hSCM,
            szName,
            SERVICE_ALL_ACCESS
            );
            if (!hSS)
            goto END;

            int iState = SERVICE_START_PENDING;
            SERVICE_STATUS status = {0};
            status.dwControlsAccepted=SERVICE_ACCEPT_STOP; ///指定該服務(wù)允許被停止
            status.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
            status.dwCurrentState=SERVICE_STOPPED;
            ///先檢測(cè)服務(wù)程序是否已經(jīng)運(yùn)行
            for(int i=0;i < 300; i++)
            {

            if(!QueryServiceStatus(hSS, &status))
            goto END;

            iState = status.dwCurrentState;
            if(status.dwCurrentState == SERVICE_RUNNING)
            goto END;

            if (status.dwCurrentState == SERVICE_STOPPED)
            {
            break;
            }
            if (status.dwCurrentState == SERVICE_START_PENDING
            || status.dwCurrentState == SERVICE_STOP_PENDING)
            {
            Sleep(10);
            continue;
            }
            }

            if(!StartService(
            hSS,
            0, ///參數(shù)個(gè)數(shù)
            NULL ///參數(shù)列表
            ))
            {

            //goto END;
            DWORD err = GetLastError();
            err = 0;
            }

            for(int i=0;i < 300; i++)
            {

            if(!QueryServiceStatus(hSS, &status))
            goto END;

            iState = status.dwCurrentState;
            if(status.dwCurrentState == SERVICE_RUNNING)
            break;

            if (status.dwCurrentState == SERVICE_START_PENDING)
            {
            Sleep(10);
            continue;
            }
            }
            if(status.dwCurrentState==SERVICE_RUNNING)
            ControlService(hSS, SERVICE_CONTROL_CONTINUE, &status);
            END:
            if(hSS)
            CloseServiceHandle(hSS);
            if (hSCM)
            CloseServiceHandle(hSCM);

            return iState;

            }

            3. 服務(wù)的停止
            開(kāi)啟服務(wù)后我們也會(huì)使用停止服務(wù)的功能,這里給出一個(gè)停止服務(wù)的的函數(shù)ServiceStop,可以看出該函數(shù)與ServiceSart的代碼差別不大,ServiceStop使用ControlService(WIN API )給運(yùn)行中的程序發(fā)送一個(gè)SERVICE_CONTROL_STOP消息,運(yùn)行中的程序收到該消息后便退出。就像你停止了apapche服務(wù)后,httpd.exe收到SERVICE_CONTROL_STOP消息并退出進(jìn)程。該函數(shù)就像你在服務(wù)控制管理器中選中某一服務(wù)項(xiàng)后右鍵停止效果。ServiceStop函數(shù)實(shí)現(xiàn)了停止服務(wù)和刪除服務(wù)的功能,所以我們?cè)谙乱徊浇榻B服務(wù)的刪除給出代碼。

            4. 服務(wù)的刪除
            當(dāng)我們不需要這項(xiàng)服務(wù)的時(shí)候我們可以在winows服務(wù)控制管理器中刪除該服務(wù)(當(dāng)然你已可以使用windwo控制臺(tái)使用命令 sc 命令來(lái)實(shí)現(xiàn)),使用DeleteService(win api)可以實(shí)現(xiàn)這一點(diǎn),下面是ServiceStop函數(shù),當(dāng)她的第二個(gè)參數(shù)被指定為真實(shí),我們?cè)谕V狗?wù)后會(huì)刪除該服務(wù)。
            ///停止或刪除服務(wù)
            int ServiceStop(const char* szName,bool bDelService=false)
            {
            int iState = -1;
            ///打開(kāi)服務(wù)控制管理器
            SC_HANDLE hSCM = OpenSCManager(
            NULL, //主機(jī)名,NULL表示本地
            NULL, //服務(wù)數(shù)據(jù)庫(kù)名,NULL默認(rèn)為 SERVICES_ACTIVE_DATABASE
            SC_MANAGER_ALL_ACCESS //期待獲取到服務(wù)管理器權(quán)限
            );
            if(!hSCM)
            return -1;

            ///打開(kāi)服務(wù)
            SC_HANDLE hSS = OpenService(
            hSCM,
            szName,
            SERVICE_ALL_ACCESS
            );
            if (!hSS)
            goto END;


            ///先檢測(cè)服務(wù)程序是否已經(jīng)運(yùn)行
            for(int i=0;i < 300; i++)
            {
            SERVICE_STATUS status = {0};
            if(!QueryServiceStatus(hSS, &status))
            goto END;

            iState = status.dwCurrentState;
            if(status.dwCurrentState == SERVICE_RUNNING)
            break;

            if (status.dwCurrentState == SERVICE_STOPPED)
            {
            goto END;
            }
            if (status.dwCurrentState == SERVICE_START_PENDING
            || status.dwCurrentState == SERVICE_STOP_PENDING)
            {
            Sleep(10);
            continue;
            }
            }

            SERVICE_STATUS status = {0};
            if(!ControlService(hSS,SERVICE_CONTROL_STOP,&status))
            goto END;


            for(int i=0;i < 300; i++)
            {

            if(!QueryServiceStatus(hSS, &status))
            goto END;

            iState = status.dwCurrentState;
            if(status.dwCurrentState == SERVICE_STOPPED)
            break;

            if (status.dwCurrentState == SERVICE_STOP_PENDING)
            {
            Sleep(10);
            continue;
            }
            }


            END:
            if(bDelService && hSS)
            {
            if(!DeleteService(hSS))
            {

            }
            }
            if(hSS)
            CloseServiceHandle(hSS);
            if (hSCM)
            CloseServiceHandle(hSCM);

            return iState;

            }

            5 編寫(xiě)windows服務(wù)程序的功能代碼
            事實(shí)上,前面4部介紹的函數(shù)不一定要出現(xiàn)在我們的服務(wù)應(yīng)用程序代碼當(dāng)中,我們可以使用控制臺(tái)命令sc來(lái)實(shí)現(xiàn)控制服務(wù)的基本操作,服務(wù)程序的功能代碼才是我們關(guān)注的核心,把一個(gè)普通的exe程序改成服務(wù)程序,我們只需要在main函數(shù)中調(diào)用windows指定的service api StartServiceCtrlDispatcher,該函數(shù)指定一個(gè)windows指定的函數(shù)指針,我們把它實(shí)現(xiàn)為ServiceMain,如代碼:

            SERVICE_TABLE_ENTRY sTable[2] = {0};
            sTable[0].lpServiceName = (LPSTR)szName; ///該參數(shù)被忽略,可以為空字符
            sTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
            sTable[1].lpServiceName = NULL;
            sTable[1].lpServiceProc = NULL;
            if(!StartServiceCtrlDispatcher((SERVICE_TABLE_ENTRY*)sTable))
            err = GetLastError();

            ServiceMain才是我們程序功能代碼真正實(shí)現(xiàn)的地方,這里簡(jiǎn)單起見(jiàn),我們把該服務(wù)程序的功能寫(xiě)成不斷循環(huán)寫(xiě)文件,
            ServiceMain的函數(shù)原形和我們實(shí)現(xiàn)的代碼如下:
            ///StartServiceCtrlDispatcher制定的回調(diào)函數(shù)
            void WINAPI ServiceMain(DWORD dwAgrc, LPSTR lpszAgrv)
            {
            g_statusHandle = RegisterServiceCtrlHandler(g_serviceNmae, (LPHANDLER_FUNCTION)Handler);
            if(!g_statusHandle)
            return;

            SERVICE_STATUS status = {0};
            status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
            status.dwCurrentState = SERVICE_RUNNING;
            status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
            if(!SetServiceStatus(g_statusHandle,&status))
            goto END;

            while (!g_bStop)
            {
            FILE* pFile = fopen("d://s.service","ab+");
            const char* str = "this is service test/r/n";
            fwrite(str,1,sizeof("this is service test/r/n"),pFile);
            fflush(pFile);
            fclose(pFile);
            Sleep(10000);
            }

            END:
            status.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus(g_statusHandle,&status);
            }

            在ServiceMain函數(shù)開(kāi)始,我們立即調(diào)用了RegisterServiceCtrlHandler并指定了一個(gè)Handler函數(shù)指針,這其實(shí)是給定了外部與我們服務(wù)程序通信的方式,Handler函數(shù)就是接收外部消息的的處理函數(shù),我們前面提過(guò)的ControlService函數(shù)發(fā)出的消息就會(huì)在這里被接收和處理,SetServiceStatus就是用來(lái)設(shè)置服務(wù)管理控制器界面的服務(wù)狀態(tài)的函數(shù)。
            void WINAPI Handler(DWORD fdwControl)
            {

            const char* szName = g_serviceNmae;

            SERVICE_STATUS status = {0};
            switch(fdwControl)
            {
            case SERVICE_CONTROL_STOP:
            {
            g_bStop = true;
            status.dwCurrentState = SERVICE_STOPPED;
            break;
            }
            case SERVICE_CONTROL_PAUSE:
            status.dwCurrentState = SERVICE_PAUSED;
            break;
            case SERVICE_CONTROL_CONTINUE:
            {
            g_bStop= false;
            status.dwCurrentState = SERVICE_RUNNING;
            break;
            }
            case SERVICE_CONTROL_INTERROGATE:
            break;
            default:
            break;
            }

            if(!SetServiceStatus(g_statusHandle,&status))
            return;
            }

            好了,編寫(xiě)windows服務(wù)程序的基本步驟入門(mén)就是這樣子了,下面給出main函數(shù)的代碼
            #include 
            #include

            static char g_serviceNmae[1024] = "mySampleService";
            static SERVICE_STATUS_HANDLE g_statusHandle = NULL;
            static bool g_bStop = false;
            int main(char argc, char** argv)
            {
            if(argc >= 3)
            {
            memset(g_serviceNmae,0,sizeof(char)*1024);
            strcpy(g_serviceNmae, argv[2]);
            }
            const char* szName = g_serviceNmae;
            DWORD err = 0;
            if(argc > 1){
            if(strcmp(argv[1],"-install")==0)
            {
            if(installServices(szName)==-1)
            {
            err = GetLastError();
            }
            else
            {
            if(ServiceStart(szName)==-1)
            err = GetLastError();
            }
            }
            else if(strcmp(argv[1],"-delete")==0)
            {
            if(ServiceStop(szName,true)==-1)
            err = GetLastError();

            }
            else if(strcmp(argv[1],"-start")==0)
            {
            if(ServiceStart(szName)==-1)
            err = GetLastError();
            }
            else if(strcmp(argv[1],"-stop")==0)
            {
            if(ServiceStop(szName)==-1)
            err = GetLastError();
            }
            }

            else
            {
            for (int i=0;i<100;i++)
            {
            Sleep(50);
            }

            SERVICE_TABLE_ENTRY sTable[2] = {0};
            sTable[0].lpServiceName = (LPSTR)szName; ///該參數(shù)被忽略,可以為空字符
            sTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
            sTable[1].lpServiceName = NULL;
            sTable[1].lpServiceProc = NULL;
            if(!StartServiceCtrlDispatcher((SERVICE_TABLE_ENTRY*)sTable))
            err = GetLastError();
            }

            return 0;
            }

            原文地址:http://blog.csdn.net/xxq123321/article/details/6212252

            posted on 2013-12-17 17:10 天道酬勤 閱讀(440) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): windows編程

            国内精品人妻无码久久久影院导航| 久久婷婷五月综合色奶水99啪| Xx性欧美肥妇精品久久久久久| 丁香五月综合久久激情| 久久夜色精品国产www| 狠狠色狠狠色综合久久| 国产亚洲精品美女久久久| 精品熟女少妇aⅴ免费久久| 久久精品人妻中文系列| 国产精品久久久久9999高清| 久久亚洲AV无码西西人体| 久久夜色精品国产噜噜麻豆| 99久久国产免费福利| 久久婷婷五月综合色高清 | 亚洲精品tv久久久久久久久 | 国产亚州精品女人久久久久久| 性做久久久久久免费观看| 成人午夜精品久久久久久久小说| 久久久久久免费视频| 99久久精品免费看国产一区二区三区| 亚洲国产精品综合久久网络 | 一级做a爰片久久毛片人呢| 精品多毛少妇人妻AV免费久久| 国产午夜精品久久久久九九电影 | 久久国内免费视频| 久久国产成人| 久久久不卡国产精品一区二区 | 一本色道久久88综合日韩精品 | 欧洲精品久久久av无码电影| 亚洲国产精品无码久久青草| 久久久久久久久久久免费精品| 久久综合欧美成人| 日本福利片国产午夜久久| 大伊人青草狠狠久久| aaa级精品久久久国产片| 精品午夜久久福利大片| 丁香狠狠色婷婷久久综合| 亚洲国产精品久久久久久| 91久久精品国产免费直播| 国产精品日韩深夜福利久久| 精品久久久无码中文字幕天天|