Windows服務進程的建立

來源:互聯網
上載者:User

                                       Windows服務進程的建立

       windows服務程式一般是在後台跑的不需要使用者互動的程式。

 

       建立windows服務程式的步驟:

       1. 在main中啟動 服務控制指派機

            調用StartServiceCtrlDispatcher,它的參數是一個SERVICE_TABLE_ENTRY 數組,數組元素包含了要啟動的服務名稱,和服務主入口函數。

 

            int _tmain(int argc, _TCHAR* argv[])<br />{<br /> //建立指派表並啟動控制指派機<br /> SERVICE_TABLE_ENTRY ServiceTable[2];<br /> ServiceTable[0].lpServiceName = _T("MyService");<br /> ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;<br /> ServiceTable[1].lpServiceName = NULL;<br /> ServiceTable[1].lpServiceProc = NULL;<br />//啟動服務的控制指派器線程<br /> StartServiceCtrlDispatcher(ServiceTable);</p><p>return 0;<br />}<br />

 

            這個數組的最後一個元素的值必須設定為NULL,這樣才能夠識別數組的結尾。所以上面的代碼雖然只指定了一個服務,但是有兩個元素。

           

            服務控制管理員(SCM:Services Control Manager)是一個管理系統所有服務的進程。當 SCM 啟動某個服務時,它等待某個進程的主線程來調用 StartServiceCtrlDispatcher 函數。將指派表傳遞給 StartServiceCtrlDispatcher。這將把調用進程的主線程轉換為控制指派器。這裡就是mian函數這個主線程。該指派器啟動一個新線程,該線程運行指派表中每個服務的 ServiceMain 函數(本文例子中只有一個服務)指派器還監視程式中所有服務的執行情況。然後指派器將控制請求從 SCM 傳給服務。

 

 

         2.服務入口函數 ServiceMain的實現

         這是由控制指派器建立的一個線程。 在這個線程的開始,就需要去註冊服務控制處理器。   調用的函數是: RegisterServiceCtrlHandler。 它指示控制指派器調用 ControlHandler 函數處理 SCM 控制請求。註冊完控制處理器之後,獲得狀態控制代碼(hStatus)。通過調用 SetServiceStatus 函數,用 hStatus 向 SCM 報表服務的狀態。

 

           在報告了服務狀態之後,你可以調用 InitService 函數來完成初始化。

           這個函數隨便你做什麼都可以。

 

            在 ServiceMain 中,檢查 InitService 函數的傳回值。如果初始化有錯(因為有可能寫記錄檔失敗),則將服務狀態置為終止並退出 ServiceMain:

 error = InitService();
if (error)
{
    // 初始化失敗,終止服務
    ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    ServiceStatus.dwWin32ExitCode = -1;
    SetServiceStatus(hStatus, &ServiceStatus);
    // 退出 ServiceMain
    return;
}

 

       

          

        

 

          

           

         

如果初始化成功,則向 SCM 報告狀態:

// 向 SCM 報告運行狀態 ServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus (hStatus, &ServiceStatus);
void WINAPI ServiceMain(int argc, char** argv) {int error; ServiceStatus.dwServiceType = SERVICE_WIN32; ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ServiceStatus.dwControlsAccepted   =  SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;ServiceStatus.dwWin32ExitCode = 0; ServiceStatus.dwServiceSpecificExitCode = 0; ServiceStatus.dwCheckPoint = 0; ServiceStatus.dwWaitHint = 0; //為服務註冊控制處理器,獲得狀態控制代碼hStatus,處理函數為ControlHandlerhStatus = RegisterServiceCtrlHandler(_T("MyService"), //服務的名稱(LPHANDLER_FUNCTION)ControlHandler); if (hStatus == (SERVICE_STATUS_HANDLE)0) { // Registering Control Handler failed  註冊控制處理器失敗return; }  // Initialize Service   初始化服務error = InitService(); if (error) {// Initialization failed  初始化服務失敗ServiceStatus.dwCurrentState = SERVICE_STOPPED; ServiceStatus.dwWin32ExitCode = -1; //通過調用 SetServiceStatus 函數,用 hStatus 向 SCM 報表服務的狀態。SetServiceStatus(hStatus, &ServiceStatus); return; } // 向SCM報告 服務正在運行ServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus (hStatus, &ServiceStatus);// The worker loop of a service  服務的工作迴圈while (ServiceStatus.dwCurrentState == SERVICE_RUNNING){//做你的事情                  cout<<"Service Running"<<endl;Sleep(2*1000);}return; }
   3. ControlHandler函數的實現

這個函數是用來響應SCM的命令的,它檢查 SCM 發送了什麼請求並採取相應行動。

STOP 請求是 SCM 終止服務的時候發送的。例如,如果使用者在“服務”控制台中手動終止服務。SHUTDOWN 請求是關閉機器時,由 SCM 發送給所有運行中服務的請求。兩種情況的處理方式相同。控制處理器函數必須報表服務狀態,即便 SCM 每次發送控制請求的時候狀態保持相同。因此,不管響應什麼請求,都要調用 SetServiceStatus。

//ControlHandler 函數處理 SCM 控制請求<br />void ControlHandler(DWORD request)<br />{<br />switch(request)<br />{<br />case SERVICE_CONTROL_STOP:<br /> cout<<"Servece Stop"<<endl;<br />ServiceStatus.dwWin32ExitCode = 0;<br />ServiceStatus.dwCurrentState = SERVICE_STOPPED;<br />SetServiceStatus (hStatus, &ServiceStatus);<br />return; </p><p>case SERVICE_CONTROL_SHUTDOWN:<br />cout<<"Servece Shutdown"<<endl;</p><p>ServiceStatus.dwWin32ExitCode = 0;<br />ServiceStatus.dwCurrentState = SERVICE_STOPPED;<br />SetServiceStatus (hStatus, &ServiceStatus);<br />return; </p><p>default:<br />break;<br />} </p><p>// Report current status<br />SetServiceStatus (hStatus, &ServiceStatus);</p><p>return; </p><p>}

 

 

 

服務的初始化函數InitService

//返回0,表示初始化沒有錯誤<br />int InitService()<br />{<br />//::AllocConsole();<br />////重新導向標準輸出<br />//freopen("CONOUT$","w+t",stdout);<br />////重新導向標準輸入<br />//freopen("CONIN$","r+t",stdin);</p><p>freopen("D://CreateEvent.log","w+t",stdout);</p><p> return 0;<br />}<br />

本文的完成參照了以下地址的文章:
http://www.vckbase.com/document/viewdoc/?id=1474
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.