Windows 如何在powershell中不断尝试,直到成功?
使用基本构造:Windows 如何在powershell中不断尝试,直到成功?,windows,powershell,scripting,powershell-3.0,powershell-4.0,Windows,Powershell,Scripting,Powershell 3.0,Powershell 4.0,使用基本构造: try { Do-Something } catch { Write-Output "Something threw an exception" } 是否有可能继续尝试,直到成功?也许使用这样的while loopp: $Timeout = 60 $timer = [Diagnostics.Stopwatch]::StartNew() $t = 0 while (($timer.Elapsed.TotalSeconds -lt $Timeout) -and ($
try
{
Do-Something
}
catch
{
Write-Output "Something threw an exception"
}
是否有可能继续尝试,直到成功?也许使用这样的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秒钟内就失败了。请帮忙
更具体地说,“做某事”是:
(Get-Process -Name FineReader).MainWindowHandle
我希望代码继续尝试,直到
FineReader
存在,并且它可以获得MainWindowHandle
您的执行某些操作
应使用开关-ErrorAction Stop
调用,以便发出可被try
捕获的终止异常
为此,还需要将函数绑定为CmdLet。例如:
function DoSomething {
[CmdLetBinding()]
Param(
)
# Your code
}
然后使用
-ErrorAction Stop
开关调用函数:
try {
Do-Something -ErrorAction Stop
}
如果您的
DoSomething
不是函数,而是现有的powershell CmdLet,则。。。你猜对了,只要用-ErrorAction Stop
您可以在powershell中了解有关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
}
如果要限制时间窗口,可以使用以下命令:
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
调用。调用$t
的目的是什么?它会立即退出,因为您的条件失败,您需要计时器小于60并且$t
不等于1
,但在第一次迭代时,您将$t
设置为1
,因此循环退出。@arco444我认为当执行某件事失败时,循环将失败,并且在执行某件事成功之前,循环将无法执行$t=1
。-ErrorAction Stop
可用于cmdlet,如果执行某件事是一个函数,错误处理功能必须明确完成。谢谢!您的建议与我的补充澄清(见问题)也起到了作用!我所做的唯一一件事就是将第一行更改为:$ErrorActionPreferenceBak=1