Windows服務可在系統啟動時自動開啟的程式,非常適合做幕後處理程式。
1)、建立Windows服務項目
在建立項目中,選擇Windows服務。
實現裡面的OnStart與OnStop,同時添加對應的事務操作流程即可。如果有其他需求,可以在屬性中設定(如暫停等)然後重載對應介面即可。
OnStart中不能做太費時間的操作(如果30s內不能完成,Windows就認為啟動失敗),所以如果有複雜的操作,需要通過線程完成,同時儘快從OnStart中返回。
OnStart可就收一個字串數組參數,在啟動時,可通過ServiceController.Start(。。。)傳入。
2)、添加安裝程式
在服務的設計介面上右擊,從快顯功能表中選擇‘添加安裝程式’即可添加安裝相關功能。在安裝的設計介面上,設定ServiceInstaller相關屬性(主要是服務名稱ServiceName和啟動類型StartType)以及ServiceProcessInstaller相關屬性(主要是安裝賬戶Account)。
安裝賬戶如果設為User,則需要設定登入名稱(為./+賬戶的格式)與登入口令,否則安裝是會彈出口令輸入驗證對話方塊。如果是其他類型的安裝賬戶,在需要注意許可權的問題(可能會出現用戶端訪問被拒絕的情況)。
3)、安裝與寫作
最簡單的方式是通過InstallUtil命令(通過啟動SDK命令介面,即可直接使用此命令),但是不適合自動安裝實現。
下面介紹一下編碼實現。通過反射實現的,所以實現的服務中必須通過上面的第二版添加安裝程式。安裝與卸載時,需要先判斷服務是否已安裝。_strLogSrvName為服務名稱。
private bool IsSrvExisted(string strSrvName_)
{
try
{
ServiceController srvCtrl = new ServiceController(strSrvName_);
ServiceControllerStatus euStatu = srvCtrl.Status;
return true;
}
catch (SystemException){}
return false;
// ServiceController[] srvCtrls = ServiceController.GetServices();
// foreach (ServiceController srv in srvCtrls)
// {
// if (srv.ServiceName == strSrvName_)
// return true;
// }
//
// return false;
}
public static void Install(string strSrvFile_)
{
if (IsSrvExisted(_strLogSrvName))
{
return;
}
System.Collections.Hashtable hashState = new System.Collections.Hashtable();
AssemblyInstaller asInst = new AssemblyInstaller();
asInst.UseNewContext = true;
asInst.Path = strSrvFile_;
asInst.Install(hashState);
asInst.Commit(hashState);
}
public static void Uninstall(string strSrvFile_)
{
if (IsSrvExisted(_strLogSrvName))
{
AssemblyInstaller asInst = new AssemblyInstaller();
asInst.UseNewContext = true;
asInst.Path = strSrvFile_;
asInst.Uninstall(null);
}
}
4)、服務啟動與停止
看通過Windows服務管理員來方便的啟動(如果啟動時需要參數,此方式不行)與停止
public static void Start(int nOsId_, string strDBConfigFile_)
{
ServiceController srvCtrl = new ServiceController(_strLogSrvName);
if ((srvCtrl.Status == ServiceControllerStatus.Stopped)
|| (srvCtrl.Status == ServiceControllerStatus.StopPending))
{
srvCtrl.Start(new string[] { nOsId_.ToString(), strDBConfigFile_ });
// Wait for 30 seconds
srvCtrl.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 30));
}
}
public static void Stop()
{
ServiceController srvCtrl = new ServiceController(_strLogSrvName);
if ( (srvCtrl.Status != ServiceControllerStatus.Stopped)
&& (srvCtrl.Status != ServiceControllerStatus.StopPending))
{
srvCtrl.Stop();
}
}
5)、服務調試
以上就完成了一個基本服務的編寫,但是服務不能互動,如何調試呢?
為了方便調試,需要在Onstart中添加一條睡眠20秒(Sleep)語句:
- 程式編譯好,沒問題;安裝
- 在服務程式中設定斷點(要在Sleep後面)
- 啟動服務。
- 在IDE的‘調試’-‘附加到進程’中選擇我們的服務進程(需要保證20秒內完成)。
- 載入完成後,等待一下(等待睡眠完成),程式跳到斷點上,然後就可調試了。
當然除了上面的方法外,還可以寫日誌、寫檔案來調試。