问题
There should be a break
command in PowerShell that can exit nested loops by assigning a label. Just it doesn't work. Here's my code:
$timestampServers = @(
"http://timestamp.verisign.com/scripts/timstamp.dll",
"http://timestamp.comodoca.com/authenticode",
"http://timestamp.globalsign.com/scripts/timstamp.dll",
"http://www.startssl.com/timestamp"
)
:outer for ($retry = 2; $retry -gt 0; $retry--)
{
Write-Host retry $retry
foreach ($timestampServer in $timestampServers)
{
Write-Host timestampServer $timestampServer
& $signtoolBin sign /f $keyFile /p "$password" /t $timestampServer $file
if ($?)
{
Write-Host OK
break :outer
}
}
}
if ($retry -eq 0)
{
WaitError "Digitally signing failed"
exit 1
}
It prints the following:
retry 2
timestampServer http://timestamp.verisign.com/scripts/timstamp.dll
Done Adding Additional Store
Successfully signed and timestamped: C:\myfile.dll
OK
retry 1
timestampServer http://timestamp.verisign.com/scripts/timstamp.dll
Done Adding Additional Store
Successfully signed and timestamped: C:\myfile.dll
OK
ERROR: Digitally signing failed
What have I done wrong?
Can I have goto and labels, please?
Using Windows 7 and I guess PS 2.0. This script is supposed to run on PS 2 at least.
回答1:
You do not add the colon when using break
with a loop label. This line:
break :outer
should be written like this:
break outer
For a further demonstration, consider this simple script:
:loop while ($true)
{
while ($true)
{
break :loop
}
}
When executed, it will run forever without breaking. This script however:
:loop while ($true)
{
while ($true)
{
break loop
}
}
exits as it should because I changed break :loop
to break loop
.
回答2:
So, I changed the code a bit to make it clear
$timestampServers = @(
"http://timestamp.verisign.com/scripts/timstamp.dll",
"http://timestamp.comodoca.com/authenticode",
"http://timestamp.globalsign.com/scripts/timstamp.dll",
"http://www.startssl.com/timestamp"
)
:outer for ($retry = 2; $retry -gt 0; $retry--)
{
Write-Host retry $retry
foreach ($timestampServer in $timestampServers)
{
Write-Host timestampServer $timestampServer
#& $signtoolBin sign /f $keyFile /p "$password" /t $timestampServer $file
if ($true)
{
break :outer
Write-Host OK
}
}
}
if ($retry -eq 0)
{
Write-Error "Digitally signing failed" ## you have a typo there
exit 1
}
This produces the following:
retry 2
timestampServer http://timestamp.verisign.com/scripts/timstamp.dll
retry 1
timestampServer http://timestamp.verisign.com/scripts/timstamp.dll
C:\temp\t.ps1 : Digitally signing failed
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,t.ps1
So, skips Write-Host OK, but also seems to continue to loop. In other words, it acts like 'Continue' statement.
Changed it like the folks mentioned to remove ':', although PowerShell documentation does not exclude it:
if ($true)
{
break outer
Write-Host OK
}
I get the correct behavior.
retry 2
timestampServer http://timestamp.verisign.com/scripts/timstamp.dll
Long story short... do not use ':'
来源:https://stackoverflow.com/questions/24043990/powershell-break-nested-loops