如何編寫windows服務程式
原
by:張鵬/hikvision
這兩天想學習關於如何編寫windows服務程式的知識,就上網查了些資料。看了一篇文章《用c 語言編寫windows 服務程式的五個步驟》。但可能由於譯者的疏忽,忘記了將關鍵**放入該文件,導致初學者可能會看不懂。所以又查閱了相關資料。自己完成了《用c 語言編寫windows 服務程式的五個步驟》中的樣例程式。
在本文中我希望能給初學者一些幫助,大致講一下編寫windows服務程式需要的知識。
首先microsoft windows 服務(即,以前的 nt 服務)使您能夠建立在它們自己的 windows 會話中可長時間執行的可執行應用程式。這些服務可以在計算機啟動時自動啟動,可以暫停和重新啟動而且不顯示任何使用者介面。這使服務非常適合在伺服器上使用,或任何時候,為了不影響在同一臺計算機上工作的其他使用者,需要長時間執行功能時使用。還可以在不同於登入使用者的特定使用者帳戶或缺省計算機帳戶的安全上下文中執行服務。
服務是有狀態的,當我們使用windows自帶的服務管理程式sc.exe檢視服務狀態時可以顯示服務的當前狀態,這個狀態是由我們在程式**中進行控制的。你最好在服務初始化的時候將服務設定為service_start_pending,當初始化完畢時設為service_running,這些狀態是系統自定義的狀態,可通過msdn檢視其他狀態。這個狀態資訊你會在sc.exe中看到。
在編寫windows服務程式過程中你需要關注的函式有:
1.首先是main函式,由於windows服務不需要介面,所以大部分程式為win32控制台應用程式,所以程式主函式為main 而不是winmain()。在主函式要做的主要工作就是初始化乙個service_table_entry 分派表結構體,然後呼叫startservicectrldispatcher();這將把呼叫程序的主線程轉換為控制分派器。該分派器啟動乙個新執行緒,該執行緒執行分派表中對應於你的服務的servicemain()函式。servicemain()函式將在下面提到。
此過程示例**如下:
service_table_entry entrytable[2];
entrytable[0].lpservicename="testservice";
entrytable[0].lpserviceproc=(lpservice_main_function)servicemain;
entrytable[1].lpservicename=null;
entrytable[1].lpserviceproc=null;
startservicectrldispatcher(entrytable);
在這之後系統將自動建立乙個執行緒去執行servicemain函式的內容,你應該將你要執行的任務在servicemain中迴圈,這樣服務就開始執行了。
2.servicemain函式為void winapi servicemain(int argc, char** argv)格式的函式,函式名字可以任意定義。它的作用就是:將你需要執行的任務放到該函式中迴圈執行即可。這就是服務程式的工作函式。在servicemain執行你的任務前,需要給service_table_entry 分派表結構體進行賦值,注意由於此時服務還沒有開始執行你的任務所以我們將服務的狀態設定為service_start_pending,即正在初始化。我們進行如下賦值:
servicestatus.dwservicetype = service_win32;
servicestatus.dwcurrentstate = service_start_pending;
servicestatus.dwcontrolsaccepted=service_accept_shutdown|service_accept_stop;
//在本例中只接受系統關機和停止服務兩種控制命令
servicestatus.dwwin32exitcode = 0;
servicestatus.dwservicespecificexitcode = 0;
servicestatus.dwcheckpoint = 0;
servicestatus.dwwaithint = 0;
hstatus = ::registerservicectrlhandler("testservice", ctrlhandler);
ctrlhandler為void winapi ctrlhandler(dword request)型的函式,函式名字可以任意設定。將在下一點講到。
hstatus為service_status_handle型別的全域性變數。當需要改變服務狀態時setservicestatus()函式需要它做為引數來標識乙個服務。
3. void winapi ctrlhandler(dword request),函式的主要功能是,接收系統傳遞的控制命令,比如當你通過sc.exe關閉服務時,該函式會收到service_control_stop訊息,你就可以對服務進行必要的管理。在本例子程式中就只接收service_accept_shutdown和service_accept_stop訊息,這是通過前面給servicestatus賦值設定的。
這樣乙個基本的服務程式就完成了。
下面貼出我的示例**僅供參考。該**在vs2008中除錯通過。本文結束的時候會附上如何安裝服務。
#include
#include
#define sleep_time 5000 //間隔時間
#define file_path "c:\\log.txt" //資訊輸出檔案
bool brun=false;
service_status servicestatus;
service_status_handle hstatus;
int writetolog(char* str);
void winapi servicemain(int argc, char** argv);
void winapi ctrlhandler(dword request);
int initservice();
int writetolog(char* str)
fprintf_s(pfile,"%s\n",str);
fclose(pfile);
return 0;
}void winapi servicemain(int argc, char** argv)
writetolog("registerservicectrlhandler success");
//向scm 報告執行狀態
servicestatus.dwcurrentstate = service_running;
setservicestatus (hstatus, &servicestatus);
//下面就開始任務迴圈了,你可以新增你自己希望服務做的工作
brun=true;
memorystatus memstatus;
char str[100];
memset(str,'\0',100);
while (brun)
writetolog("service stopped");
}void winapi ctrlhandler(dword request)
setservicestatus (hstatus, &servicestatus);
}void main()
如何安裝服務:
執行命令提示符 cmd.exe
輸入 sc create testservicename binpath= d:\test.exe
輸入 sc start testservicename 啟動服務
輸入sc query 會在最底部顯示你的服務當前的狀態
輸入 sc stop testservicename 停止服務
輸入 sc delete testservicename刪除服務,該服務將在下次重啟後刪除,在重啟之前將不能註冊同乙個名字的服務。
Windows服務程式編寫
windows服務程式編寫 2014年8月17日16 08 55 1 用vs2008新建乙個空的控制台工程。如下 include include ifdef unicode define t s l s else define t s s endif define sleep time 5000 間...
如何編寫Windows服務
按微軟的定義,服務是乙個長時間執行的可執行檔案,它不支援使用者介面,並執行在特殊的使用者賬戶之下,也可以在沒有任何使用者登入計算機的情況下執行。預設情況下,服務執行在system賬戶之下。與一般的應用程式相比,服務自動執行的,並且無需與使用者互動。在.net framework中,與windows服...
如何編寫Windows服務
按微軟的定義,服務是乙個長時間執行的可執行檔案,它不支援使用者介面,並執行在特殊的使用者賬戶之下,也可以在沒有任何使用者登入計算機的情況下執行。預設情況下,服務執行在system賬戶之下。與一般的應用程式相比,服務自動執行的,並且無需與使用者互動。在.net framework中,與windows服...