2012-07-30 91 views
1

我有一個C#應用程序,它使用的Windows服務並非總是處於啓動狀態,我希望能夠在服務啓動和關閉時發送電子郵件通知。我寫了電子郵件腳本,但我似乎無法弄清楚如何檢測服務狀態更改。檢測/監聽服務啓動和停止狀態更改

我一直在閱讀 ServiceController類,我認爲 WaitForStatus()方法可能是我需要的,但是我一直未能找到一個示例,它在尚未啓動的服務上使用。 編輯:由於WaitForStatus()方法busy-waiting,我需要執行由服務運行的程序的其餘部分,同時收聽服務啓動/停止,我不認爲這是方法我,除非有人使用這種方法結合多線程的解決方案,並且乾淨而高效。

 

更多:

  • 該服務將不會被應用程序啓動 - 應用程序的用戶將在管理工具的服務窗口來啓動直接。
  • 使用的服務是不是默認的Windows服務 - 它被設計用於這種應用

 

感謝您的幫助的定製服務!

 

P.S.請注意,我對C#相當陌生,並且在我去這裏學習。

 

UPDATE:

我設法得到報警郵件給每個服務啓動時發送:當我繼續通過我的代碼閱讀(我,不幸的是,不能發佈這裏),我注意到用於創建服務的類正在擴展ServiceBase類,並且有人使用自定義OnStart()方法來覆蓋默認類。我添加了對新的OnStart()方法的必要方法調用,併成功發送了通知。

我試圖爲OnStop()方法做同樣的事情,但對我來說這並沒有那麼好 - 在繼續之前,我想補充一點,我已經用Java編程了好幾年了,而且我非常熟悉Java設計模式。

我試圖做的,這一點在Java工作過,是一個調用電子郵件通知重寫ServiceBase類的OnStop()方法,投MyServiceServiceBase類型,然後再調用ServiceBase類的Stop()方法(注意:OnStop()是一種受保護的方法,因此無法直接調用 - Stop()方法調用OnStop(),然後繼續使用必要的代碼停止服務)。我認爲鑄造ServiceBase會強制調用默認的OnStop()方法,而不是我自定義的方法。

正如你可以想像,我結束了剛剛1萬個電子郵件成功發送到我的收件箱之前,我設法在我的電腦強行進入硬關機。

我現在需要的是一種方法,既可以使用我重寫OnStop()方法,然後把它調用默認的方法,或其他辦法解決這個問題。任何和所有的幫助,非常感謝。非常感謝。

 

與多線程解決方案你所組成:

protected override void OnStart(string[] args) { 
    string subject = "Notice: Service Started"; 
    string body = "This message is to notify you that the service " + 
     "has been started. This message was generated automatically."; 
    EmailNotification em = new EmailNotification(subject, body); 
    em.SendNotification(); 

    ...INITIALIZE LISTENER FOR SERVICE STOPPING HERE... 

    ...custom stuff to be run on start... 
} 

而且,記住類調用此方法中,我們稱之爲Service,擴展了ServiceBase類。

 

更新兩個:

的問候,我使用NotifyServerStatusChange據我瞭解,這是不允許的解決方案中使用的系統功能,由於各種原因的建議。澄清一下,只有純粹在C#和.NET範圍內的解決方案纔是可行的。再次感謝你的幫助!

+0

看看wmi查詢。 – Chriseyre2000 2012-07-30 19:39:53

+0

沒錯,但應用程序沒有檢查事件的狀態 - 它需要持續監聽狀態變化 – 2012-07-30 19:41:56

+0

@ Chriseyre2000:這是一個有效的解決方案,迄今爲止,我只有這個解決方案。如果你想刪除評論並將其作爲答案,我會對它進行投票,因爲它是對此的唯一答案。然而,正如文章本身所說,代碼會變得混亂,我真的不能朝這個方向前進。 – 2012-07-31 12:36:09

回答

2

這裏是解決方案,爲什麼之前我無法找到它:正如我剛纔所說,我的課擴展ServiceBase類。在我的第一次更新中,我發佈了我試圖解決這個問題的方式,我將用Java解決它:通過投射。但是,在C#中,如果在派生類中覆蓋它,顯然不會讓您調用基本方法。當我第一次發佈這個問題和這個更新(並且很明顯是沒有人想到的事情之一)時,我不知道的一件事是C#包括base構造函數,它可以用來從基類的方法調用派生類。由於base構造函數可用於C#中的任何類,因此它不會出現在ServiceBase Class documentation中。

一次我學到了這一點,我能夠把我原來的解決方案並將其修改爲使用基類:

protected override void OnStop() { 
     string subject = "Notice: Service Stopped"; 
     string body = "This message is to notify you that the service has " + 
      "been stopped. This message was generated automatically."; 
     EmailNotification em = new EmailNotification(subject, body); 
     em.SendNotification(); 
     base.OnStop(); 
    } 

我想通了這一點,當我在Visual Studio中,發現的代碼打轉轉base在我的智能感知中。我點擊進入其定義,並將它發送給ServiceBase(顯然未定義)。在注意到我的代碼中沒有定義基礎並且它是ServiceBase類的實例之後,我意識到它一定是某種構造函數。經過Google的快速搜索,我找到了我正在尋找的東西。去智能感知的方法!

謝謝大家對您的幫助!

1

ServiceController類有一個WaitForStatus方法。雖然它在內部進行輪詢。

+0

是的,投票方面使它成爲一個禁行,除非有人可以告訴我如何創建一個新的線程這個工作,如果沒有它在性能方面花費我很多(注意:我一直在尋找多線程這個應用程序,但是,正如我之前所說,我對C#有點新,從我讀過的內容來看,它聽起來並不像它能夠正確或高效地工作 - 思想?) – 2012-07-31 12:34:09

+0

您認爲一個或幾個輪詢線程是性能問題?他們每250毫秒喚醒一次。你爲什麼認爲這是一個不行? – usr 2012-07-31 13:01:55

+0

對不起,我不認爲我的評論非常清楚 - 我不是說投票會是一個性能問題,只有第二個主題。在性能方面,投票本身對我來說完全沒問題,但是當程序監聽服務停止時,我需要做些事情。根據定義,輪詢是忙等待的,除非我有兩個線程,否則我不能這樣做,這樣我就可以在一箇中等待,然後在另一個程序中通過其餘的程序。 – 2012-07-31 13:09:48

1

如果你不能PInvoke的NotifyServiceStatusChange,那麼你就必須輪詢服務。例如:

ServiceController sc = new ServiceController("Some Service"); 
Console.WriteLine("Status = " + sc.Status); 
+0

這是一個很好的解決方案,如果我們要實現一個「心跳監視器」,它將很好的工作,但是我們的規範要求解決方案是服務本身的一部分,當服務被告知停止時,所以。 – 2012-07-31 14:41:39

0

使用NotifyServiceStatusChange()時要非常小心,因爲它僅在Windows Vista/Windows 2008(及更高版本)上受支持。如果您針對以下任何平臺,則無法使用該API。 (仍然有很多XP/Windows 2000-2003系統。)

更糟糕的是,如果服務重新啓動,輪詢將不會總是可靠的,因爲如果您以非常快的速度輪詢服務系統(SSD驅動器或虛擬機上的預緩衝I/O)時,服務可能會在兩次輪詢之間重新啓動。

+0

謝謝 - 我經常檢查堆棧,並且總是在我發佈的帖子/問題上查看新答案/評論。你的帖子非常有見地,但它不僅僅是一種解決方案而是一種評論 - 你是否還有另一種解決方案可以提出建議? (如果沒有,請將您的帖子更改爲評論而不是答案)謝謝:) – 2013-07-02 16:33:58