PowerShell: break nested loops

寵の児 提交于 2019-12-06 23:49:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!