18

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.

2 Answers 2

36

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.

Sign up to request clarification or add additional context in comments.

7 Comments

Technet docs at technet.microsoft.com/en-us/library/hh847873.aspx show the colon in the break statement, but I tested this as well and found the same as iCodez: with the colon it ignored the label (just broke from the inner loop), without the colon it would break from the labeled loop.
@iCodez no, actually you are right... I thought it was working but it is not.
Thank you. I must have overlooked that. You should never rely on arbitrary websites to learn a programming language. But with PowerShell this seems necessary.
the Doc must have been fixed, there is no colon there now. Nor when I change Doc version to PS 3, or use Get-Help about_break in PS 5.1 console. But it still is on Hey, Scripting Guy! Blog
thanks for the demonstration. It worked fine for me
|
1

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 ':'

1 Comment

No, I have a function there, WaitError. This code was from a much greater script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.