如何在 powershell 中不断尝试直到成功?
How to continuously try something in powershell until it succeeds?
使用基本构造:
try
{
Do-Something
}
catch
{
Write-Output "Something threw an exception"
}
是否可以一直尝试 Do-Something 直到成功?也许像这样使用 while loopp:
$Timeout = 60
$timer = [Diagnostics.Stopwatch]::StartNew()
$t = 0
while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and ($t -ne 1))) {
Start-Sleep -Seconds 1
try
{
Do-Something
$t = 1
}
catch
{
Write-Output "Something threw an exception"
}
}
$timer.Stop()
在这里,我使用计时器来确保 PowerShell 不会无限期地 运行。
它应该继续尝试,直到 try
成功并且 $t = 1
被执行。但是,它会在大约 2 秒内失败。请帮忙。
更具体地说,Do-Something 是:
(Get-Process -Name FineReader).MainWindowHandle
我希望代码继续尝试直到 FineReader
存在并且它可以获得 MainWindowHandle
.
您的 Do-Something
应该使用开关 -ErrorAction Stop
调用,以便发出可以被 try
捕获的终止异常
为此,您还需要将函数绑定为 CmdLet。例如:
function DoSomething {
[CmdLetBinding()]
Param(
)
# Your code
}
然后使用 -ErrorAction Stop
开关调用您的函数:
try {
Do-Something -ErrorAction Stop
}
如果您的 DoSomething
不是函数而是现有的 powershell CmdLet,那么...您猜对了,只需使用 -ErrorAction Stop
调用它
您可以在 powershell here
中了解有关 try/catch/finally 的更多信息
您可以使用 break
关键字。
# Set the erroracton preference to stop when an error occurs,
$ErrorActionPreferenceBak = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
While($True){
try{
Do-Something
break
}
catch{
Write-Output "Something failed"
Start-Sleep -Seconds 1 # wait for a seconds before next attempt.
}
finally{
#Reset the erroracton preference
$ErrorActionPreference = $ErrorActionPreferenceBak
}
}
假设您有一个函数在 10 次调用中有 9 次失败:
function Get-RandomFail{
$value = [Random]::new().Next(10);
if ($value -ne 5) { throw }
return $value
}
而你想限制时间window,你可以使用以下方法:
function Try-Invoke{
[CmdletBinding()]
param(
$Action,
$MaxSeconds,
$Delay=1
)
$timeout = [timespan]::FromSeconds($MaxSeconds)
$start = [DateTime]::Now
do {
try {
return &$Action
} catch {
Write-Verbose "Error"
}
Start-Sleep -Seconds $Delay
} until (([DateTime]::Now - $start) -gt $timeout)
throw
}
$result = Try-Invoke {Get-RandomFail} -MaxSeconds 5 -Verbose
Get-RandomFail
将被调用,直到没有错误发生或直到时间结束。您还可以使用 Delay
参数在每次不成功的 Get-RandomFail
调用后修改睡眠时间。
使用基本构造:
try
{
Do-Something
}
catch
{
Write-Output "Something threw an exception"
}
是否可以一直尝试 Do-Something 直到成功?也许像这样使用 while loopp:
$Timeout = 60
$timer = [Diagnostics.Stopwatch]::StartNew()
$t = 0
while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and ($t -ne 1))) {
Start-Sleep -Seconds 1
try
{
Do-Something
$t = 1
}
catch
{
Write-Output "Something threw an exception"
}
}
$timer.Stop()
在这里,我使用计时器来确保 PowerShell 不会无限期地 运行。
它应该继续尝试,直到 try
成功并且 $t = 1
被执行。但是,它会在大约 2 秒内失败。请帮忙。
更具体地说,Do-Something 是:
(Get-Process -Name FineReader).MainWindowHandle
我希望代码继续尝试直到 FineReader
存在并且它可以获得 MainWindowHandle
.
您的 Do-Something
应该使用开关 -ErrorAction Stop
调用,以便发出可以被 try
为此,您还需要将函数绑定为 CmdLet。例如:
function DoSomething {
[CmdLetBinding()]
Param(
)
# Your code
}
然后使用 -ErrorAction Stop
开关调用您的函数:
try {
Do-Something -ErrorAction Stop
}
如果您的 DoSomething
不是函数而是现有的 powershell CmdLet,那么...您猜对了,只需使用 -ErrorAction Stop
您可以在 powershell here
中了解有关 try/catch/finally 的更多信息您可以使用 break
关键字。
# Set the erroracton preference to stop when an error occurs,
$ErrorActionPreferenceBak = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
While($True){
try{
Do-Something
break
}
catch{
Write-Output "Something failed"
Start-Sleep -Seconds 1 # wait for a seconds before next attempt.
}
finally{
#Reset the erroracton preference
$ErrorActionPreference = $ErrorActionPreferenceBak
}
}
假设您有一个函数在 10 次调用中有 9 次失败:
function Get-RandomFail{
$value = [Random]::new().Next(10);
if ($value -ne 5) { throw }
return $value
}
而你想限制时间window,你可以使用以下方法:
function Try-Invoke{
[CmdletBinding()]
param(
$Action,
$MaxSeconds,
$Delay=1
)
$timeout = [timespan]::FromSeconds($MaxSeconds)
$start = [DateTime]::Now
do {
try {
return &$Action
} catch {
Write-Verbose "Error"
}
Start-Sleep -Seconds $Delay
} until (([DateTime]::Now - $start) -gt $timeout)
throw
}
$result = Try-Invoke {Get-RandomFail} -MaxSeconds 5 -Verbose
Get-RandomFail
将被调用,直到没有错误发生或直到时间结束。您还可以使用 Delay
参数在每次不成功的 Get-RandomFail
调用后修改睡眠时间。