2012-09-21 42 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 
}