2012-09-21 40 views
8

我們使用停止服務cmdlet來殺死我們的服務箱上的一些服務。大多數情況下,它的效果很好,但是我們有一兩種服務(誰不?),偶爾不會很好。停止服務cmdlet超時可能嗎?

在這種情況下所討論的服務之一將保持在停止狀態,並且cmdlet一遍又一遍地把這個到控制檯:

[08:49:21]WARNING: Waiting for service 'MisbehavingService (MisbehavingService)' to finish 
[08:49:21]stopping... 
[08:49:23]WARNING: Waiting for service 'MisbehavingService (MisbehavingService)' to finish 
[08:49:23]stopping... 
[08:49:25]WARNING: Waiting for service 'MisbehavingService (MisbehavingService)' to finish 
[08:49:25]stopping... 

最後,我們必須殺死任務服務經理,然後我們的劇本繼續。

有沒有辦法讓停止服務cmdlet放棄或在某個點後超時?我想我們可以在以後檢查,如果服務仍在運行,請使用kill-process cmdlet提供最後一個印章。

回答

3

停止服務沒有超時選項,但是如果存在依賴服務,則可能需要使用-force。

服務可以在啓動時定義一個等待提示(它指定了一個超時),但超時由服務控制。任何服務控制請求(開始,停止,暫停,恢復)都要經過服務控制管理器(SCM),並且將遵守每項服務的等待提示。如果超過等待提示,操作將失敗並返回錯誤。

您可以使用invoke-command作爲作業運行Stop-Service並定期檢查它。如果尚未完成,則可以使用Stop-Process終止進程並繼續。

+0

謝謝史蒂文。我認爲下面的這個討論對於這個主題也有一些很好的建議。特別是,該頁面上的最後發佈:http://www.powershellcommunity.org/Forums/tabid/54/aft/5243/Default.aspx – larryq

+0

這也是一些好東西。 –

7

雖然Stop-Service沒有超時參數,對System.ServiceControllerWaitForStatus方法確實有過載,需要一個超時參數(記錄here)。幸運的是,這正是Get-Service命令返回的對象的類型。

這是一個簡單的函數,它以秒爲單位獲取服務名稱和超時值。如果服務在達到超時之前停止,則返回$true;如果呼叫超時(或服務不存在),則返回$false

function Stop-ServiceWithTimeout ([string] $name, [int] $timeoutSeconds) { 
    $timespan = New-Object -TypeName System.Timespan -ArgumentList 0,0,$timeoutSeconds 
    $svc = Get-Service -Name $name 
    if ($svc -eq $null) { return $false } 
    if ($svc.Status -eq [ServiceProcess.ServiceControllerStatus]::Stopped) { return $true } 
    $svc.Stop() 
    try { 
     $svc.WaitForStatus([ServiceProcess.ServiceControllerStatus]::Stopped, $timespan) 
    } 
    catch [ServiceProcess.TimeoutException] { 
     Write-Verbose "Timeout stopping service $($svc.Name)" 
     return $false 
    } 
    return $true 
}