麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > Java > 正文

Windows服務編寫原理及探討(3)

2019-09-06 23:33:38
字體:
來源:轉載
供稿:網(wǎng)友

                   

(三)對服務的深入討論之下

  現(xiàn)在我們還剩下一個函數(shù)可以在細節(jié)上討論,那就是服務的CtrlHandler函數(shù)。

   

  當調用RegisterServiceCtrlHandler函數(shù)時,SCM得到并保存這個回調函數(shù)的地址。一個SCP調一個告訴SCM如何去控制服務的Win32函數(shù),現(xiàn)在已經(jīng)有10個預定義的控制請求:

                                                                                                                                                                                                                                                                                                                           
       

         Control           code

       
       

         Meaning

       
               SERVICE_CONTROL_STOP        Requests the         service to stop. The hService handle must have SERVICE_STOP         access.
               SERVICE_CONTROL_PAUSE        Requests the         service to pause. The hService handle must have         SERVICE_PAUSE_CONTINUE access.
               SERVICE_CONTROL_CONTINUE        Requests the         paused service to resume. The hService handle must have         SERVICE_PAUSE_CONTINUE access.
               SERVICE_CONTROL_INTERROGATE        Requests the         service to update immediately its current status information to the         service control manager. The hService handle must have         SERVICE_INTERROGATE access.
               SERVICE_CONTROL_SHUTDOWN        Requests the         service to perform cleanup tasks, because the system is shutting down.                For more information, see Remarks.
               SERVICE_CONTROL_PARAMCHANGE        Windows         2000: Requests the service to reread its startup parameters. The        hService handle must have SERVICE_PAUSE_CONTINUE access.
               SERVICE_CONTROL_NETBINDCHANGE        Windows         2000: Requests the service to update its network binding. The        hService handle must have SERVICE_PAUSE_CONTINUE access.
               SERVICE_CONTROL_NETBINDREMOVE        Windows         2000: Notifies a network service that a component for binding has         been removed. The service should reread its binding information and         unbind from the removed component.
               SERVICE_CONTROL_NETBINDENABLE        Windows         2000: Notifies a network service that a disabled binding has been         enabled. The service should reread its binding information and add the         new binding.
               SERVICE_CONTROL_NETBINDDISABLE        Windows         2000: Notifies a network service that one of its bindings has been         disabled. The service should reread its binding information and remove         the binding.
   

  上表中標有Windows     2000字樣的就是2000中新添加的控制代碼。除了這些代碼之外,服務也可以接受用戶定義的,范圍在128-255之間的代碼。

   

  當CtrlHandler函數(shù)收到一個SERVICE_CONTROL_STOP、SERVICE_CONTROL_PAUSE、        SERVICE_CONTROL_CONTINUE控制代碼的時候,SetServiceStatus必須被調用去確認這個代碼,并指定你認為服務處理這個狀態(tài)變化所需要的時間。

   

  例如:你的服務收到了停止請求,首先要把SERVICE_STATUS結構的dwCurrentState成員設置成SERVICE_STOP_PENDING,這樣可以使SCM確定你已經(jīng)收到了控制代碼。當一個服務的暫停或停止操作正在執(zhí)行的時候,必須指定你認為這種操作所需要的時間:這是因為一個服務也許不能立即改變它的狀態(tài),它可能必須等待一個網(wǎng)絡請求被完成或者數(shù)據(jù)被刷新到一個驅動器上。指定時間的方法就像我上一章說的那樣,用成員dwCheckPoint和dwWaitHint來指明它完成狀態(tài)改變所需要的時間。如果需要,可以用增加dwCheckPoint成員的值和設置dwWaitHint成員的值去指明你期待的服務到達下一步的時間的方式周期性的報告進展情況。

   

  當整個啟動的過程完成之后,要再一次調用SetServiceStatus。這時就要把SERVICE_STATUS結構的dwCurrentState成員設置成SERVICE_STOPPED,當報告狀態(tài)代碼的同時,一定要把成員dwCheckPoint和dwWaitHint設置為0,因為服務已經(jīng)完成了它的狀態(tài)變化。暫停或繼續(xù)服務的時候方法也一樣。

   

  當CtrlHandler函數(shù)收到一個SERVICE_CONTROL_INTERROGATE控制代碼的時候,服務將簡單的將dwCurrentState成員設置成服務當前的狀態(tài),同時,把成員dwCheckPoint和dwWaitHint設置為0,然后再調用SetServiceStatus就可以了。

   

  在操作系統(tǒng)關閉的時候,CtrlHandler函數(shù)收到一個SERVICE_CONTROL_SHUTDOWN控制代碼。服務根本無須回應這個代碼,因為系統(tǒng)即將關閉。它將執(zhí)行保存數(shù)據(jù)所需要的最小行動集,這是為了確定機器能及時關閉。缺省時系統(tǒng)只給很少的時間去關閉所有的服務,MSDN里面說大概是20秒的時間,不過那可能是Windows     NT 4的設置,在我的Windows     2000 Server里這個時間是10秒,你可以手動的修改這個數(shù)值,它被記錄在HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControl子鍵里面的WaitToKillServiceTimeout,單位是毫秒。

   

   

   

  當CtrlHandler函數(shù)收到任何用戶定義的代碼時,它應該執(zhí)行期望的用戶自定義行動。除非用戶自定義的行動要強制服務去暫停、繼續(xù)或停止,否則不調SetServiceStatus函數(shù)。如果用戶定義的行動強迫服務的狀態(tài)發(fā)生變化,SetServiceStatus將被調用去設置dwCurrentState、dwCheckPoint和dwWaitHint,具體控制代碼和前面說的一樣。

   

  如果你的CtrlHandler函數(shù)需要很長的時間執(zhí)行操作的話,千萬要注意:假如CtrlHandler函數(shù)在30秒內沒有返回的話,SCM將返回一個錯誤,這不是我們所期望的。所以如果出現(xiàn)上述情況,最好的辦法是再建立一個線程,讓它去繼續(xù)執(zhí)行操作,以便使得CtrlHandler函數(shù)能夠迅速的返回。例如,當收到一個SERVICE_CONTROL_STOP請求的時候,就像上面說的一樣,服務可能正在等待一個網(wǎng)絡請求被完成或者數(shù)據(jù)被刷新到一個驅動器上,而這些操作所需要的時間是你不能估計的,那么就要建立一個新的線程等待操作完成后執(zhí)行停止命令,CtrlHandler函數(shù)在返回之前仍然要報告SERVICE_STOP_PENDING狀態(tài),當新的線程執(zhí)行完操作之后,再由它將服務的狀態(tài)設置成SERVICE_STOPPED。如果當前操作的時間可以估計的到就不要這樣做,仍然使用前面交待的方法處理。

   

  CtrlHandler函數(shù)我就先講這些,下面說說服務怎么安裝。一個服務程序可以使用CreateService函數(shù)將服務的信息添加到SCM的數(shù)據(jù)庫。

   

SC_HANDLE     CreateService(    SC_HANDLE hSCManager, // handle to SCM database     LPCTSTR lpServiceName, // name of service to start    LPCTSTR lpDisplayName, // display name    DWORD dwDesiredAccess, // type of access to service    DWORD dwServiceType, // type of service    DWORD dwStartType, // when to start service    DWORD dwErrorControl, // severity of service failure    LPCTSTR lpBinaryPathName, // name of binary file    LPCTSTR lpLoadOrderGroup, // name of load ordering group    LPDWORD lpdwTagId, // tag identifier    LPCTSTR lpDependencies, // array of dependency names    LPCTSTR lpServiceStartName, // account name     LPCTSTR lpPassword // account password    );

   

  hSCManager是一個標示SCM數(shù)據(jù)庫的句柄,可以簡單的通過調用OpenSCManager得到。

   

SC_HANDLE     OpenSCManager(    LPCTSTR lpMachineName, // computer name    LPCTSTR lpDatabaseName, // SCM database name    DWORD dwDesiredAccess // access type    );

   

  lpMachineName是目標機器的名字,還記得我在第一章里說過可以在其它的機器上面安裝服務嗎?這就是實現(xiàn)的方法。對方機器名字必須以“/”開始。如果傳遞NULL或者一個空的字符串的話就默認是本機。

   

  lpDatabaseName是目標機器上面SCM數(shù)據(jù)庫的名字,但MSDN里面說這個參數(shù)要默認的設置成SERVICES_ACTIVE_DATABASE,如果傳遞NULL,就默認的打開SERVICES_ACTIVE_DATABASE。所以我還沒有真的搞明白這個參數(shù)的存在意義,總之使用的時候傳遞NULL就行了。

   

  dwDesiredAccess是SCM數(shù)據(jù)庫的訪問權限,具體值見下表:

                                                                                                                                                                                                           
       

         Object           access

       
       

                   Description

       
               SC_MANAGER_ALL_ACCESS        Includes         STANDARD_RIGHTS_REQUIRED, in addition to all of the access types listed         in this table.
               SC_MANAGER_CONNECT        Enables         connecting to the service control manager.
               SC_MANAGER_CREATE_SERVICE        Enables         calling of the CreateService function to create a service object         and add it to the database.
               SC_MANAGER_ENUMERATE_SERVICE        Enables         calling of the EnumServicesStatus function to list the services         that are in the database.
               SC_MANAGER_LOCK        Enables         calling of the LockServiceDatabase function to acquire a lock on         the database.
               SC_MANAGER_QUERY_LOCK_STATUS        Enables         calling of the QueryServiceLockStatus function to retrieve the         lock status information for the database.
   

  想要獲得訪問權限的話,似乎沒那么復雜。MSDN里面說所有進程都被允許獲得對所有SCM數(shù)據(jù)庫的SC_MANAGER_CONNECT,     SC_MANAGER_ENUMERATE_SERVICE, and SC_MANAGER_QUERY_LOCK_STATUS權限,這些權限使得你可以連接SCM數(shù)據(jù)庫,枚舉目標機器上安裝的服務和查詢目標數(shù)據(jù)庫是否已被鎖住。但如果要創(chuàng)建服務,首先你需要擁有目標機器的管理員權限,一般的傳遞SC_MANAGER_ALL_ACCESS就可以了。這個函數(shù)返回的句柄可以被CloseServiceHandle函數(shù)關閉。

   

  lpServiceName是服務的名字,lpDisplayName是服務在“服務”管理工具里顯示的名字。

   

  dwDesiredAccess也是訪問的權限,有一個比上面的還長的多的一個表,各位自己查MSDN吧。我們要安裝服務,仍然簡單的傳遞SC_MANAGER_ALL_ACCESS。

   

  dwServiceType是指你的服務是否和其它的進程相關聯(lián),一般是SERVICE_WIN32_OWN_PROCESS,表示不和任何進程相關聯(lián)。如果你確認你的服務需要和某些進程相關聯(lián),就設置成SERVICE_WIN32_SHARE_PROCESS。當你的服務要和桌面相關聯(lián)的時候,需要設置成SERVICE_INTERACTIVE_PROCESS。

   

  dwStartType是服務的啟動方式。服務有三種啟動方式,分別是“自動(SERVICE_AUTO_START)”“手動(SERVICE_DEMAND_START)”和“禁用(SERVICE_DISABLED)”。在MSDN里還有另外的兩種方式,不過是專為驅動程序設置的。

   

  dwErrorControl決定服務如果在系統(tǒng)啟動的時候啟動失敗的話要怎么辦。

                                                                                                                                                   
       

         值

       
       

         意義

       
               SERVICE_ERROR_IGNORE啟動程序記錄錯誤發(fā)生,但繼續(xù)啟動。
               SERVICE_ERROR_NORMAL啟動程序記錄錯誤發(fā)生,并彈出一個消息框,但仍繼續(xù)啟動
               SERVICE_ERROR_SEVERE啟動程序記錄錯誤發(fā)生,如果是以last-known-good         configuration啟動的話,啟動會繼續(xù)。否則會以last-known-good         configuration重新啟動計算機。
               SERVICE_ERROR_CRITICAL啟動程序記錄錯誤發(fā)生,如果可能的話。如果是以last-known-good         configuration啟動的話,啟動會失敗。否則會以last-known-good         configuration重新啟動計算機。好嚴重的錯誤啊。
   

  lpBinaryPathName是服務程序的路徑。MSDN里面特別提到如果服務路徑里面有空格的話一定要將路徑用引號引起來。例如"d:/my     share/myservice.exe"就一定要指定為""d:/my     share/myservice.exe""。

   

  lpLoadOrderGroup的意義在于,如果有一組服務要按照一定的順序啟動的話,這個參數(shù)用于指定一個組名用于標志這個啟動順序組,不過我還沒有用過這個參數(shù)。你的服務如果不屬于任何啟動順序組,只要傳遞NULL或者一個空的字符串就行了。

   

  lpdwTagId是應用了上面的參數(shù)之后要指定的值,專用于驅動程序,與本文內容無關。傳遞NULL。

   

  lpDependencies標示一個字符串數(shù)組,用于指明一串服務的名字或者一個啟動順序組。當與一個啟動順序組建立關聯(lián)的時候,這個參數(shù)的含義就是只有你指定的啟動順序組里有至少一個經(jīng)過對整個組里所有的成員已經(jīng)全部嘗試過啟動后,有至少一個成員成功啟動,你的服務才能啟動。不需要建立依存關系的話,仍是傳遞NULL或者一個空的字符串。但如果你要指定啟動順序組的話,必須為組名加上SC_GROUP_IDENTIFIER前綴,因為組名和服務名是共享一個命名空間的。

   

  lpServiceStartName是服務的啟動賬號,如果你設置你的服務的關聯(lián)類型是SERVICE_WIN32_OWN_PROCESS的話,你需要以DomainNameUserName的格式指定用戶名,如果這個賬戶在你本機的話,用.UserName就可以指定。如果傳遞NULL的話,會以本地的系統(tǒng)賬戶登陸。如果是Win     NT 4.0或更早的版本的話,如果你指定了SERVICE_WIN32_SHARE_PROCESS,就必須傳遞.System指定服務使用本地的系統(tǒng)賬戶。最后,如果你指定了SERVICE_INTERACTIVE_PROCESS,你必須使服務運行在本機系統(tǒng)賬戶。

   

  看名字就知道了,lpPassword是賬戶的密碼。如果指定系統(tǒng)賬戶的話,傳遞NULL。如果賬戶沒有密碼的話,傳遞空字符串。

   

  總之服務的基本原理就是這樣子了,到了這里這篇文章似乎可以告一段落了,但實際上還有很多內容必須要討論,所以我還不能草草收筆,敬請關注下一章。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 国产乱淫a∨片免费观看 | 欧美精品色精品一区二区三区 | 国产一级做a爱片在线看免 2019天天干夜夜操 | 神秘电影91| 草莓福利视频在线观看 | 一级做人爱c黑人影片 | 亚洲第一视频 | 成人午夜激情视频 | 黄色网址在线视频 | 国产一级毛片高清视频完整版 | 手机视频在线播放 | 国产成年人视频 | 中文字幕一区在线观看视频 | 国产亚洲精品久久久久久网站 | 日韩欧美电影一区二区三区 | 国产91一区| 亚洲一级毛片 | 中文字幕在线观看精品 | 亚洲成人免费电影 | 看国产一级毛片 | 国产日韩在线观看一区 | 亚洲一区二区成人 | 亚洲乱码精品久久久久 | 国产精品久久久免费观看 | 亚洲极色| 欧美成人视 | 久久中文一区 | 草草久久久| 毛片在线播放视频 | 国产亚洲在 | 国内自拍网址 | 黄色免费小网站 | 国产日本在线播放 | 韩国一级免费视频 | 56av国产精品久久久久久久 | 中文字幕一二区 | 亚洲一区久久 | 亚洲第一成网站 | 欧美日韩国产成人在线观看 | 日韩一级免费毛片 | 日本精品视频一区二区三区四区 |