如何?可插拔的windows服務
關於windows服務的建立相關資源很多,園子裡面也有很多這樣的文章。
整理了一下相關blog如下,
http://www.cnblogs.com/wuxilin/archive/2006/06/04/416838.html
http://www.cnblogs.com/wujm/archive/2005/05/12/154369.html
http://www.cnblogs.com/caca/archive/2005/02/25/109028.html
http://www.cnblogs.com/laiwen/archive/2005/08/21/219590.html
歸納一下步驟大概如下:
1.建立服務:
1.1我們應該建立windows服務類型的project,IDE會自動從serviceBase類繼承一個類出來,在這個類裡面有on_star和on_stop兩個方法,可以在裡面寫入啟動邏輯和停止邏輯
在設計檢視下我們可以修改service的屬性
Autolog 是否自動寫入系統的記錄檔
CanHandlePowerEvent 服務時候接受電源事件
CanPauseAndContinue 服務是否接受暫停或繼續啟動並執行請求
CanShutdown 服務是否在運行它的電腦關閉時收到通知,以便能夠調用 OnShutDown 過程
CanStop 服務是否接受停止啟動並執行請求
ServiceName 服務名
1.2選擇服務元件,並切換到設計模式,右鍵->Add Installer,產生安裝檔案。安裝檔案中的屬性修改可以參考下面的內容:
projectInstall參數修改Account(指定使用者還是使用本地系統使用者)
ServiceInstall參數修改:
描述名:Description,
顯示名:DisplayName,
ServiName:服務名,要和剛才建立的服務名一一對應才行
StartType:(Manual:服務安裝後,必須手動啟動.Automatic:每次電腦重新啟動時,服務都會自動啟動;Disabled:服務無法啟動)
2安裝
安裝服務要使用微軟提供的工具InstallUtil,這個工具在c:/windows/wicrosoft.net/framework/[version]中
使用InstallUtil 安裝,使用InstallUtil /u 反安裝服務
如果還有什麼可以參考剛才說的那幾個blog,ok一切都很簡單。但是如果要做為一個企業級的應用,往往會有別的情境需求,下面說一下我曾碰到的情境要求
1.我們的windows服務可能不止滿足一種商務邏輯,比如:如果你的機器安裝了oracle的話,就會有OracleService服務,我們啟動資料庫的時候可以只是啟動tns服務和OracleService服務就可以了,但是實際上啟動OracleService服務的同時會啟動好幾個服務,例如:DBWR(資料檔案寫入),LGWR(記錄檔寫入),SMON(系統監護),PMON(使用者進程監),CKPT(檢查點,同步資料檔案,記錄檔,控制檔案等)。有時為了效能的考慮,一個服務也可能要多線程的運行商務邏輯。比如一個匯入檔案的資料介面服務,如果資料量非常大就要這樣考慮。一般如果執行多個任務,可以有兩種方法:1.開多個線程;2.在一個線程中順序進行(可以加上時間控制)。我覺得這裡最靈活的方法是用.net本省的多線程支援來解決。
2.要能在不改變系統結構的情況下,可以非常快速的支援新的服務需求。這說明我們在onstar方法中不能寫入相關類的處理邏輯,必須要用某種方法解耦才行。
實現方法:
參考下面的類圖
servcive類和具體的業務實作類別解耦,我們可以使用原廠模式產生商務邏輯類,每個商務邏輯類啟動在一個新的線程中,在.net中原廠模式可以用反射非常方便的實現,這塊代碼如下:
typeInfo = node.Attributes["type"].Value;
Type type = Type.GetType(typeInfo);
IService instance = (IService)Activator.CreateInstance(type);
//初始化服務
instance.Initialize(node);
instanceArray.Add(instance);
//在新線程中運行服務,每個服務使用相同的安全上下文
ThreadStart ts = new ThreadStart(instance.Start);
Thread t = new Thread(ts);
t.Start();
從設定檔中讀出需要載入的商務邏輯類,執行個體化後用ThreadStart調用其中的Start方法,啟動新線程。這裡對設定檔的讀取如果要求比較高可以採用Enterprise Libary的Login block來做。
在OnStop方法中調用每個類的Stop方法,如果想對每個Stop方法非同步呼叫,可以用delegate封裝介面的Stop方法用
BeginInvoke方法實現非同步呼叫
foreach (object o in instanceArray)
{
try
{
IService service = (IService)o;
if (service !=null)
{
//非同步呼叫每個服務的stop方法來停止業務組件
OnStopDelegate osd = new OnStopDelegate(service.Stop);
osd.BeginInvoke(null,null);
}
}
catch (Exception ex)
{
//
}
}
這樣,整個windows服務就實現了,這裡還有個額外的好處是可以熱部署,即不需要刪除已經部署的windows服務,將新的DLL覆蓋將以前的DLL覆蓋,修改*.exe.config檔案並重新啟動就可以了。其實我覺得停止服務,重新編譯部署後在啟動服務花費的時間可能比這樣還少些。
關於調試:
windows服務常用的調試方法是用調試->附加到進程的方法。
選擇顯示所有使用者進程,我們已經部署並啟動的windows服務進程就會出現,並跳到我們設定好的斷點處。但是這樣對service中的onstart部分調試比較麻煩。我還是推薦建立一個porjec做為調試用,這裡面可以寫onstart部分的代碼,代碼不多,非常方便。大家就可以象調試普通windows程式一樣調試這windows服務代碼了