如何用 C 註冊 windows 服務程式 (分析 Java Service Wrapper 代碼)
前提:
從http://wrapper.tanukisoftware.org 下載 Java Service Wrapper 的原始碼.
因為 Java Service Wrapper 同時提供windows 和 linux 上的實現,所以源檔案夾裡的代碼都是分兩份的.
在windows下的實現註冊 windows 服務的代碼在wrapper_win.c 檔案中.
看了其中的代碼後你會對作者的專業精神有深刻的體會,在wrapper_win.c檔案中的曆史變動說明就有300多行,詳細描述了每次改動的變化.具體實現的方法中也都有詳細的說明,所以看這樣的代碼基本上不費力氣的.
如果非要說看代碼是享受, Java Service Wrapper 的原始碼算一個.
下面我們看看它是如何?註冊一個exe檔案為windows服務的.
wrapper_win.c中的入口main 函數定義如下:
void _CRTAPI1 main(int argc, char **argv) //注意main定義的修飾_CRTAPI1
根據argv的輸入參數分別執行,註冊,取消,開始,停止windows服務的操作:
代碼如下:
if(!_stricmp(argv[1],"-i") || !_stricmp(argv[1],"/i")) {
result = wrapperInstall(argc, argv); //註冊服務
} else if(!_stricmp(argv[1],"-r") || !_stricmp(argv[1],"/r")) {
result = wrapperRemove(); //取消註冊
} else if(!_stricmp(argv[1],"-t") || !_stricmp(argv[1],"/t")) {
result = wrapperStartService(); //啟動服務
} else if(!_stricmp(argv[1],"-p") || !_stricmp(argv[1],"/p")) {
result = wrapperStopService(TRUE); //停止服務
}
我們重點看windows服務註冊的實現,即wrapperInstall(argc, argv) 方法.
第一步: 使用OpenSCManager winapi 獲得一個服務控制管理員的控制代碼.
第二步: 使用CreateService winapi 建立服務,參數很多,重要的有: 服務名 ,服務類型,可執行檔路徑等
第三步: 在註冊表中添加註冊資訊: 代碼如下:
sprintf(regPath, "SYSTEM//CurrentControlSet//Services//%s", wrapperData->ntServiceName);
//ntServiceName就是在服務管理員中看到的服務名
if ((wrapperData->ntServiceDescription != NULL && strlen(wrapperData->ntServiceDescription) > 0)
&& (RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_WRITE, (PHKEY) &hKey) == ERROR_SUCCESS)) {
RegSetValueEx(hKey, "Description", (DWORD) 0, (DWORD) REG_SZ,
(const unsigned char *)wrapperData->ntServiceDescription,
(strlen(wrapperData->ntServiceDescription) + 1));
RegCloseKey(hKey);
}
原以為很複雜的過程,實際上很簡單,對不對?
There are two excellent articles that explain how a simple service application can be created.
- Creating a Simple Win32 Service in C++ by Thompson Nigel.
- Five Steps to Writing Windows Services in C by Yevgeny Menaker.
下文介紹一下 使用 JNI 和 java 類 以及註冊服務互動的實現.
另: 周星星
void _CRTAPI1 main(int argc, char **argv) //注意main定義的修飾_CRTAPI1
上面的 關鍵字 _CRTAPI1 的用法能詳細說說嗎?
田春峰 20041221 修改