2012-02-10 57 views
1

這個問題是基於其他問題: How can a windows service programmatically restart itself?問題與Windows服務程序重新啓動本身

我實現的解決方案之一在前面的問題,像這樣:

Dim proc As New Process() 
Dim psi As New ProcessStartInfo() 

psi.CreateNoWindow = True 
psi.FileName = "cmd.exe" 
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE" 
psi.LoadUserProfile = False 
psi.UseShellExecute = False 
psi.WindowStyle = ProcessWindowStyle.Hidden 
proc.StartInfo = psi 
proc.Start() 

我看到2個問題與此:

  1. 事件日誌每次服務重新啓動時引發此警告: Windows detected your registry file is still in use by other applications or services... 5 user registry handles leaked from ...
  2. 服務有時可能無法重新啓動。在仔細研究之後,我最好的猜測就是該服務在該進程嘗試重新啓動之前結束。這是一個問題的原因是因爲淨停止命令將失敗,因爲服務已經停止,導致它不執行net start命令。

下面是完整的代碼:

Private Sub Timer_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles _timer.Elapsed 
    ' we do not want the timer stepping on itself (ie. the time interval elapses before the first call is done processing 
    _timer.Stop() 

    ' do some processing here 
    Dim shouldRestart As Boolean = ProcessStuff() 

    If shouldRestart Then 
     Dim proc As New Process() 
     Dim psi As New ProcessStartInfo() 

     psi.CreateNoWindow = True 
     psi.FileName = "cmd.exe" 
     psi.Arguments = "/C net stop ""My Cool Service"" && net start ""My Cool Service""" 
     psi.LoadUserProfile = False 
     psi.UseShellExecute = False 
     psi.WindowStyle = ProcessWindowStyle.Hidden 
     proc.StartInfo = psi 
     proc.Start() 
     Return 
    End If 

    _timer.Start() 
End Sub 

假設我是正確的(重要的假設)有問題2,你認爲用了Thread.Sleep(10000)命令更換工作Return語句?

回答

1

我認爲這樣做的最好方法是運行批處理文件而不是內聯命令集。這樣,批處理文件就可以運行「net stop」並獲取錯誤,而不會影響正在運行的其他語句。

您是否使用services.msc中的服務註冊將服務「失敗」(異常終止)記錄到事件日誌中?如果沒有,並且只要告訴它「重新啓動服務」,如果可執行文件因任何原因退出,那麼這很簡單;調用Application.Exit(),而服務可執行文件將正常終止,然後Windows將重新啓動它。就註冊表句柄而言,如果你的服務使用註冊表數據,你的OnStop方法應該延遲程序退出,直到所有的句柄都被清除;這意味着所有後臺線程必須被告知取消並允許這樣做(這意味着線程進程必須能夠被取消而不會簡單地「殺死」它們),所有打開的文件和註冊表流必須被關閉並妥善處置,一般服務不能留下任何「磨損的目的」。當這些事情發生時,OnStop()可以將程序執行延遲約10秒鐘;如果您的服務需要比完全退出時間更長的時間,Windows將會出錯,並且您的服務最終會停止,但不會重新啓動。

+0

+1對於Onstop的信息。有Windows重新啓動它是一個好的選擇(見其他評論)。我將不得不使用批處理文件進行測試。該服務可以在任何用戶帳戶(不僅是本地系統)下運行,在這種情況下,該用戶可能沒有權限執行批處理文件。不確定,但我會測試。 – 2012-02-10 21:20:05

+0

我剛發現不使用批處理文件的另一個原因。安全!如果服務作爲具有高權限的用戶運行,我想不出一個更簡單的方法來破解它。 – 2012-02-16 16:27:30

+0

如果安全性問題,該服務可以發出自己的批處理文件。這在很大程度上排除了攻擊者劫持進程以運行惡意批處理文件的能力,並且不會比任何基於運行cmd.exe和Process.Start()的東西更加依賴「魔術字符串」如果命令需要更改,則必須重新構建應用程序的代價。 – KeithS 2012-02-16 16:34:17

0

這一個會幫你嗎? (公然自我推銷類似的回答我做的) link to answer to similar problem

+0

該選項是「OK」。我不喜歡如何重新啓動需要1分鐘,並且沒有簡單的方法來以編程方式設置恢復選項。 – 2012-02-10 21:13:51

相關問題