亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

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

2019-09-06 23:33:38
字體:
來源:轉載
供稿:網友

                   

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

  現在我們還剩下一個函數可以在細節上討論,那就是服務的CtrlHandler函數。

   

  當調用RegisterServiceCtrlHandler函數時,SCM得到并保存這個回調函數的地址。一個SCP調一個告訴SCM如何去控制服務的Win32函數,現在已經有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函數收到一個SERVICE_CONTROL_STOP、SERVICE_CONTROL_PAUSE、        SERVICE_CONTROL_CONTINUE控制代碼的時候,SetServiceStatus必須被調用去確認這個代碼,并指定你認為服務處理這個狀態變化所需要的時間。

   

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

   

  當整個啟動的過程完成之后,要再一次調用SetServiceStatus。這時就要把SERVICE_STATUS結構的dwCurrentState成員設置成SERVICE_STOPPED,當報告狀態代碼的同時,一定要把成員dwCheckPoint和dwWaitHint設置為0,因為服務已經完成了它的狀態變化。暫?;蚶^續服務的時候方法也一樣。

   

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

   

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

   

   

   

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

   

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

   

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

   

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數據庫的句柄,可以簡單的通過調用OpenSCManager得到。

   

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

   

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

   

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

   

  dwDesiredAccess是SCM數據庫的訪問權限,具體值見下表:

                                                                                                                                                                                                           
       

         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數據庫的SC_MANAGER_CONNECT,     SC_MANAGER_ENUMERATE_SERVICE, and SC_MANAGER_QUERY_LOCK_STATUS權限,這些權限使得你可以連接SCM數據庫,枚舉目標機器上安裝的服務和查詢目標數據庫是否已被鎖住。但如果要創建服務,首先你需要擁有目標機器的管理員權限,一般的傳遞SC_MANAGER_ALL_ACCESS就可以了。這個函數返回的句柄可以被CloseServiceHandle函數關閉。

   

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

   

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

   

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

   

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

   

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

                                                                                                                                                   
       

         值

       
       

         意義

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

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

   

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

   

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

   

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

   

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

   

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

   

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

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

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产自在精品国产浪潮| 久久亚洲精品视频| 欧美又大粗又爽又黄大片视频| 亚洲国产精品成人精品| www.欧美三级电影.com| 亚洲欧美日韩国产中文专区| 亚洲国产中文字幕在线观看| 欧美黑人一区二区三区| 中文字幕在线观看日韩| 91久久久亚洲精品| 欧美日韩中文在线观看| 精品国内亚洲在观看18黄| 久久久久99精品久久久久| 国产精品日韩欧美综合| 亚洲成人国产精品| 日韩成人在线视频网站| 亚洲大尺度美女在线| 欧美激情第6页| 日韩欧美在线网址| 97超碰色婷婷| 久久久国产一区二区三区| 日韩欧美在线国产| 成人在线播放av| 亚洲国产成人久久综合| 久久伊人91精品综合网站| 亚洲电影av在线| 国产色视频一区| 在线不卡国产精品| www.国产一区| 日本欧美一级片| 欧美激情视频网站| 欧美精品激情在线观看| 国产精品91免费在线| 日韩美女在线看| 国产一区二区视频在线观看| 欧美在线影院在线视频| 亚洲成人免费网站| 亚洲第一福利视频| 久久久久久网站| 亚洲国产精品高清久久久| 国产精品自拍偷拍| 日韩视频在线免费| 日韩精品一区二区三区第95| 久久免费视频网| 国产精品久久久久7777婷婷| 色综合久久久888| 国产亚洲a∨片在线观看| 国产精品久久久久秋霞鲁丝| 中文字幕日韩av综合精品| 国产精品99久久久久久人| 日韩中文字幕网站| 78色国产精品| 亚洲四色影视在线观看| 最新亚洲国产精品| 亚洲一区中文字幕在线观看| 中日韩美女免费视频网址在线观看| 日韩av三级在线观看| 欧美丰满片xxx777| 欧美激情伊人电影| 亚洲自拍欧美色图| 亚洲少妇中文在线| 中文字幕成人精品久久不卡| 国产婷婷成人久久av免费高清| 国产精选久久久久久| 欧美亚洲激情视频| 色综合久久精品亚洲国产| 久久久国产91| 国产日韩精品在线| 热草久综合在线| 91久久嫩草影院一区二区| 亚洲成人黄色网| 久久69精品久久久久久国产越南| 国产高清视频一区三区| 欧美一区亚洲一区| 欧美日韩美女视频| 亚洲精品视频在线播放| 国产视频精品免费播放| 欧美成人激情视频| 国产亚洲欧美日韩精品| 性色av一区二区三区在线观看| 51精品国产黑色丝袜高跟鞋| 亚洲欧美一区二区三区情侣bbw| 97香蕉超级碰碰久久免费的优势| 国产欧美亚洲视频| 日韩成人av网| 久久久精品在线观看| 91精品视频观看| 国产在线精品播放| 欧美裸体xxxx极品少妇软件| 91精品国产99久久久久久| 亚洲国产高清高潮精品美女| 最新国产精品亚洲| 国产91精品久久久| 538国产精品一区二区在线| 日韩av在线最新| 久久久久久久国产精品| 2020国产精品视频| 日韩精品中文字幕在线播放| 91精品国产乱码久久久久久蜜臀| 亚洲爱爱爱爱爱| 97视频在线观看网址| 国产精品网红福利| 久久久精品久久久久| 91亚洲精品久久久久久久久久久久| 91在线看www| 久久在线免费视频| 日韩免费精品视频| 国产小视频91| 欧美黑人巨大xxx极品| 亚洲美女av电影| 精品国产精品三级精品av网址| 亚洲黄色在线观看| 97不卡在线视频| 欧美极品欧美精品欧美视频| 欧美电影电视剧在线观看| 欧美伦理91i| 亚洲欧美在线看| 国产精品日韩一区| 亚洲欧美激情另类校园| 欧美性视频在线| 欧美激情在线观看视频| 国产精品第三页| 81精品国产乱码久久久久久| 亚洲综合色激情五月| 91九色国产在线| 91成人在线观看国产| 成人综合网网址| 亚洲天堂网在线观看| 国内精品400部情侣激情| 亚洲国产日韩精品在线| 亚洲欧美一区二区激情| 日韩中文在线观看| 国产在线观看精品| 国产精品亚洲欧美导航| 午夜精品一区二区三区在线视频| 日韩欧美aaa| 国产精品wwwwww| 久久在线精品视频| 欧美成年人视频网站欧美| 亚洲欧美激情四射在线日| 国产精品美女免费| 欧美日韩一二三四五区| 欧美国产日韩二区| 茄子视频成人在线| 欧美激情性做爰免费视频| 日韩中文视频免费在线观看| 日本视频久久久| 国产精品久久久久久久久久99| 久久精品99无色码中文字幕| 亚洲精品按摩视频| 亚洲综合色激情五月| 国产精品自拍偷拍视频| 欧美极品少妇xxxxⅹ裸体艺术| 国产91ⅴ在线精品免费观看| 有码中文亚洲精品| 亚洲国产天堂久久综合| 91久久久国产精品| 日韩av在线导航| 亚洲欧美日韩一区在线| 麻豆成人在线看| 欧美最顶级丰满的aⅴ艳星| 日韩av免费在线观看| 成人两性免费视频| 日韩在线观看你懂的|