在 Windows Powershell 中,如何在继续之前等待事件为真?
In Windows Powershell, how can I wait for an event to be true before proceeding?
我正在编写一个 Windows 停止服务的 Powershell 脚本,然后我想在它最终停止时打印该服务的状态。我尝试了以下方法,但它只是挂起[=13=]
$service = Get-Service | Where-Object {$_.name -like "*MyService*"}
Stop-Service -Name $service.name
$wait=true
while ($wait) {
if($service.Status -eq "Running") {
Start-Sleep -Seconds 1
}
else {
$wait=$false
}
}
我知道我可能可以写一个 for{}
循环来代替计数 0-9,并在满足我的条件时中断,但是有更好的方法吗?
您需要re-check循环内的服务。
$service = Get-Service | Where-Object {$_.name -like "*MyService*"}
Stop-Service -Name $service.name
$wait=true
while ($wait) {
if($service.Status -eq "Running") {
Start-Sleep -Seconds 1
# ADD THIS BELOW. Need to re-check service in loop.
$service = Get-Service | Where-Object {$_.name -like "*MyService*"}
}
else {
$wait=$false
}
}
解决您眼前的问题:
- 一个
[System.ServiceProcess.ServiceController]
instance (as returned by Get-Service
)的.Status
属性值是一个static值,只反映服务的状态在 Get-Service
调用时。[1]
- 要更新值以反映 then-current 状态,请调用
.Refresh()
方法。
但是,不需要显式地等待服务停止,因为Stop-Service
是同步的,即:
- 它等待 服务在返回之前完成停止,除非您明确传递
-NoWait
。
- 如果在固定的 2 秒超时内没有发生这种情况:[2]
- 如果服务上次报告停止待定,则会发出警告 - 可能会最终停止完成。
- 否则,会出现non-terminating错误 - 这表明服务被卡住了。
因此,您可以简化代码如下:
# Report a script-terminating error if stopping doesn't finish
# within the timeout period.
Stop-Service -Name *MyService* -ErrorAction Stop -WarningAction Stop
如果要实现重试机制,还需要做更多的工作。
[1] 有一个例外,虽然该行为没有记录并且应该被视为一个实现细节:如果你 pipe a 预先存在的 ServiceController
实例到 Stop-Service
/ Start-Service
,这些 cmdlet 会为您刷新实例;例如,执行 ($service = Get-Service Bits) | Stop-Service
后,$service.Status
是 当前(反映 Stopped
)。
[2] 从 PowerShell Core 7.3.0-preview.2 开始 - 请参阅 the source code.
我正在编写一个 Windows 停止服务的 Powershell 脚本,然后我想在它最终停止时打印该服务的状态。我尝试了以下方法,但它只是挂起[=13=]
$service = Get-Service | Where-Object {$_.name -like "*MyService*"}
Stop-Service -Name $service.name
$wait=true
while ($wait) {
if($service.Status -eq "Running") {
Start-Sleep -Seconds 1
}
else {
$wait=$false
}
}
我知道我可能可以写一个 for{}
循环来代替计数 0-9,并在满足我的条件时中断,但是有更好的方法吗?
您需要re-check循环内的服务。
$service = Get-Service | Where-Object {$_.name -like "*MyService*"}
Stop-Service -Name $service.name
$wait=true
while ($wait) {
if($service.Status -eq "Running") {
Start-Sleep -Seconds 1
# ADD THIS BELOW. Need to re-check service in loop.
$service = Get-Service | Where-Object {$_.name -like "*MyService*"}
}
else {
$wait=$false
}
}
- 一个
[System.ServiceProcess.ServiceController]
instance (as returned byGet-Service
)的.Status
属性值是一个static值,只反映服务的状态在Get-Service
调用时。[1] - 要更新值以反映 then-current 状态,请调用
.Refresh()
方法。
但是,不需要显式地等待服务停止,因为Stop-Service
是同步的,即:
- 它等待 服务在返回之前完成停止,除非您明确传递
-NoWait
。 - 如果在固定的 2 秒超时内没有发生这种情况:[2]
- 如果服务上次报告停止待定,则会发出警告 - 可能会最终停止完成。
- 否则,会出现non-terminating错误 - 这表明服务被卡住了。
因此,您可以简化代码如下:
# Report a script-terminating error if stopping doesn't finish
# within the timeout period.
Stop-Service -Name *MyService* -ErrorAction Stop -WarningAction Stop
如果要实现重试机制,还需要做更多的工作。
[1] 有一个例外,虽然该行为没有记录并且应该被视为一个实现细节:如果你 pipe a 预先存在的 ServiceController
实例到 Stop-Service
/ Start-Service
,这些 cmdlet 会为您刷新实例;例如,执行 ($service = Get-Service Bits) | Stop-Service
后,$service.Status
是 当前(反映 Stopped
)。
[2] 从 PowerShell Core 7.3.0-preview.2 开始 - 请参阅 the source code.