C#管理windows服務


.NET Framework中提供了現成的類庫可以很方便的實現對windows服務的安裝、卸載、啟動、停止、獲取運行狀態等功能。這些類都在System.ServiceProcess命名空間下。

安裝window服務

using (AssemblyInstaller installer = new AssemblyInstaller())
{
     installer.UseNewContext = true;
     installer.Path = serviceFilePath;    //serviceFilePath是windows服務可執行文件的完整路徑
     IDictionary savedState = new Hashtable();
     installer.Install(savedState);
     installer.Commit(savedState);
 }

 

卸載windows服務

using (AssemblyInstaller installer = new AssemblyInstaller())
{
    installer.UseNewContext = true;
    installer.Path = serviceFilePath;
     installer.Uninstall(null);
 }

 

啟動windows服務

//使用ServiceController.GetServices()可獲取windows服務列表,進而可判斷服務是否存在

//serviceName是注冊的windows服務名稱

using (ServiceController control = new ServiceController(serviceName))
 {
     if (control.Status == ServiceControllerStatus.Stopped)
     {
         control.Start();
     }
 }

 

一切都似乎很簡單,略坑的是,ServiceController.Start方法(注意並不是StartAsync),看起來是一個同步方法,如果服務啟動失敗,按理會異常拋出。而實際情況卻時,Start方法是立即返回的,不會等待服務的啟動結果。方法注釋里發生異常只有兩種情形:

System.ComponentModel.Win32Exception: 訪問系統 API 時出錯。

System.InvalidOperationException: 未找到服務。

至於其它情形導致的啟動失敗(如文件缺失、服務應用程序內部出錯),Start方法一無所知。

ServiceController類有一個Wait方法,作用是阻塞當前線程等待服務到達指定的狀態,還可以設置等待的超時時間,這有一定的用處,但並不理想。當啟動失敗的時候,如何能夠獲取到啟動失敗的信息呢?

 

一個猥瑣的辦法

windows服務啟動無論成功還是失敗,都會記錄一條windows日志,可以借助對windows日志的監控來實現:

在調用ServiceController.Start方法之前,啟動對windows日志的監聽:

_eventLog = new EventLog("Application");
 _eventLog.EnableRaisingEvents = true;
 _eventLog.EntryWritten += Log_EntryWritten;

在EntryWritten事件處理器里,判斷windows日志類型,進而得知windows服務啟動情況:

private void Log_EntryWritten(object sender, EntryWrittenEventArgs e)
 {
     EventLogEntry log = e.Entry;
     if(log.Source == _currentSection.ServiceName)
    {
        if(log.EntryType == EventLogEntryType.Information)
         {
            //啟動成功
        }
        else
        {
           //啟動失敗
            MessageBox.Show(log.Message);
        }
         _eventLog.Dispose();
         _eventLog = null;
     }
 }


這里還一個略坑的點,按一般的事件開發約定,sender參數應該就是發生事件的主體,在這里想來應該就是EventLog類的實例,然而事實上sender是EventLogInternal類的實例,很遺憾的是,這個類並不公開訪問,而且,也並未發現有跟EventLog類的直接關聯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM