熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

Visual C#中調用Windows服務初探

2013-11-13 10:08:07  來源: .NET編程 

  Windows服務是獨立於登錄用戶而工作的Windows應用程序它通常在計算機啟動時開始執行且常常連續執行直到計算機關閉為止像Exchange ServerIIS和殺毒軟件等都使用這種方式這樣就可以獨立於某一用戶而且可以在任何用戶登錄前來運行同時也可以服務於所有的進程從而以一種服務的形式存在
  
  正因為Windows服務有著這麼多的特性因此當需要一些特殊功能的時候就可以考慮使用Windows服務來解決問題比如下面我們要做的這個例子對於我們這些程序設計人員計算機是在一起工作時間最長的伙伴每天都會對著它的屏幕八個小時以上還不包括下班後在家打游戲的時間因此保護眼睛是最重要的了問題的起因來源於本人周六去眼科對激光手術的復查大夫一再向我強調眼睛的自我調節能力就是說只要你能保證你每隔一個小時左右就閉眼休息或向遠處眺望離開電腦屏幕那麼已經治好的近視就不會反彈本人雖是自律性比較強的人但在計算機屏幕面前就不再如此了往往幾個小時也不抬頭一次為了眼睛的健康我決定把這個艱巨的任務交由計算機來完成讓它在一小時左右自動提醒我休息五分鐘如此一來豈不是再也不用顧慮這件事了
  
  功能雖然簡單但要寫個程序放在啟動組裡每天自動運行也不是一個好的辦法正巧以前也沒做過Windows服務不如索性來試一試同進也看看NET為我們提供了多麼先進的功能吧於是決定就用C#來做一個提醒我保護眼睛的Windows服務取名就叫CareEye吧
  
  運行Visual StudioNET 建立一個C#的Windows服務項目在CareEyecs的設計視圖提示可以把需要的控件和組件拖動到這上面假如想要做系統日志的話當然就可以把EventLog組件拖過來了不過這個程序好像不需要這些東西還是算了吧那麼計時要不要采用計時器控件呢?想了一下這個控件雖然好用但太常用了本著學習新知識的原則最恰當的恐怕就是線程了而且在以後做其他Windows服務的時候線程肯定是必需的所以還是用線程好這樣我只要在線程中完成對時間的監測把線程的啟動和停止交給服務的啟動和停止很方便啊
  
  再來看CareEyecs的源程序一大堆沒見過的東西不過仔細分析一下也就沒什麼了CareEye類派生於ServiceBase類因此繼承了基本服務類的特性顯然Main()方法會由SCM(服務控制管理程序)調用在這個方法中Run一個新的CareEye實例這樣就運行了一個Windows服務OnStart()和OnStop()明顯是用於啟動和停止服務的響應函數了
  
  注意在Main()方法中有一個ServiceBase[]的數組它是為那些一個服務進程包含多個服務准備的對於這個程序來說它只有一個CareEye服務因此完全可以把這個數組刪除而只是使用SystemServiceProcessServiceBaseRun(new CareEye());一句就夠了
  
  接下來為了使用線程需要引入SystemThreading命名空間為了使用對話框還需要引入SystemWindowsForms命名空間這是為了將來提示用戶時顯示對話框而准備的
  
  下面為類CareEye添加一個成員字段private Thread MainThread;同時在構造函數中對其進行初始化
  
  MainThread=new Thread(new ThreadStart(ThreadFunc));
  MainThreadPriority=ThreadPriorityLowest;
  
  這裡把線程的優先級設到最低這樣不會耗用過多的系統性能這個線程對象使用ThreadFunc作為線程函數因此將這個線程函數補充完整
  
  public static void ThreadFunc()
  {
  int LastHour=DateTimeNowHour;
  while (true)
  {
  SystemThreadingThreadSleep();
  if (DateTimeNowHour==LastHour)
  {
  MessageBoxShow(為了愛護您的眼睛請您暫時休息分鐘並向遠處眺望!警告MessageBoxButtonsOKMessageBoxIconWarningMessageBoxDefaultButtonButton
  MessageBoxOptionsDefaultDesktopOnly);
  LastHour=DateTimeNowHour;
  }
  }
  }
  
  余下的代碼就簡單了只要在OnStart中啟動線程在OnStop中停止線程就行了
  
  以上的服務程序雖然很簡單線程的處理上也不很恰當也違背了很多服務程序的原則比如界面顯示等但對於本人的需求而言是足夠了因此就如此制作了如果你有需要當然可以把對話框改為其他的提醒方式如響鈴等線程也可以使用內核對象同時使用更好的處理方法
  
  Windows服務就做完了余下的就是要測試了但發現這個EXE無法運行它會提示你該EXE需要使用安裝程序來安裝服務看來不可能寫一個程序就算是Windows服務了還要把它注冊到Windows才行
  
  接下來右擊CareEyecs的設計視圖添加安裝程序(VSNET想得就是挺周到的)這下又出來一批代碼不過好在不用改代碼了只要把Account的賬戶類型設成LocalSystem把StartType設成手動啟動就行了這裡用手動是為了方便調試以後可以改成自動類型
  
  編譯完後還是無法運行此處還需要一步就是運行installutil來安裝這個服務其安裝和卸載的用法為
  
  installutil CareEyeexe
  installutil /u CareEyeexe
  
  安裝完後能過系統的服務管理器你就可以看到你的服務了只要點擊啟動就可以把它啟動把時間向前改一個小時它就會提醒你需要休息了呵呵夠簡單了吧
  
  如果你想制作成安裝包分發給自己的朋友只需要再添加個部署項目就行了不過為了完成自注冊要在自定義操作編輯器中的安裝階段添加一個自定義的安裝操作把InstallerClass屬性設成TRUE即可
  
  以下是careeyecs的源程序:
  
  using System;
  using SystemCollections;
  using SystemComponentModel;
  using SystemData;
  using SystemDiagnostics;
  using SystemServiceProcess;
  using SystemThreading;
  using SystemWindowsForms;
  namespace CareEye
  {
  public class CareEye : SystemServiceProcessServiceBase
  {
  private Thread MainThread;
  /// <summary>
  /// 必需的設計器變量
  /// </summary>
  private SystemComponentModelContainer components = null;
  
  public CareEye()
  {
  // 該調用是 WindowsForms 組件設計器所必需的
  InitializeComponent();
  
  // TODO: 在 InitComponent 調用後添加任何初始化
  MainThread=new Thread(new ThreadStart(ThreadFunc));
  MainThreadPriority=ThreadPriorityLowest;
  }
  
  // 進程的主入口點
  static void Main()
  {
  //SystemServiceProcessServiceBase[] ServicesToRun;
  
  // 同一進程中可以運行多個用戶服務若要將
  //另一個服務添加到此進程請更改下行
  // 以創建另一個服務對象例如
  //
  // ServicesToRun = New SystemServiceProcessServiceBase[] {new CareEye() new MySecondUserService()};
  //
  //ServicesToRun = new SystemServiceProcessServiceBase[] { new CareEye() };
  
  SystemServiceProcessServiceBaseRun(new CareEye());
  }
  
  /// <summary>
  /// 設計器支持所需的方法 不要使用代碼編輯器
  /// 修改此方法的內容
  /// </summary>
  private void InitializeComponent()
  {
  //
  // CareEye
  //
  thisServiceName = CareEye;
  
  }
  
  /// <summary>
  /// 清理所有正在使用的資源
  /// </summary>
  
  protected override void Dispose( bool disposing )
  {
  if( disposing )
  {
  if (components != null)
  {
  componentsDispose();
  }
  }
  baseDispose( disposing );
  }
  
  /// <summary>
  /// 設置具體的操作以便服務可以執行它的工作
  /// </summary>
  protected override void OnStart(string[] args)
  {
  // TODO: 在此處添加代碼以啟動服務
  MainThreadStart();
  }
  
  /// <summary>
  /// 停止此服務
  /// </summary>
  protected override void OnStop()
  {
  // TODO: 在此處添加代碼以執行停止服務所需的關閉操作
  MainThreadAbort();
  }
  public static void ThreadFunc()
  {
  int LastHour=DateTimeNowHour;
  while (true)
  {
  SystemThreadingThreadSleep();
  if (DateTimeNowHour==LastHour)
  {
  MessageBoxShow(為了愛護您的眼睛請您暫時休息分鐘並向遠處眺望!警告MessageBoxButtonsOKMessageBoxIconWarningMessageBoxDefaultButtonButtonMessageBoxOptionsDefaultDesktopOnly);
  LastHour=DateTimeNowHour;
  }
  }
  }
  }
  }
From:http://tw.wingwit.com/Article/program/net/201311/12658.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.