PowerShell: break nested loops

20,062

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

Share:
20,062
ygoe
Author by

ygoe

Software developer and consultant, specialising in .NET data, web and cross-platform solutions. Into clean code, usability, design and typography. Curious. Not a coffee drinker. The passion for creating useful applications for people and continuous improvement in coding has kept me in the software development business for over 20 years and counting. I started with Basic, Pascal and C++, however for the past 15 years my focus has been on C# and .NET technologies on several platforms, together with databases, JavaScript and PHP. This includes customer projects for data processing and analysis in sectors like power supply, finance, medical and manufacturing, as well as my own product ideas that I draw from everyday work. I also enjoy contributing to open source projects. In my leisure time I also like travelling and photographing the beauty of our world. Read more about me on my website.

Updated on July 09, 2022

Comments

  • ygoe
    ygoe almost 2 years

    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.

  • ygoe
    ygoe almost 10 years
    No, I have a function there, WaitError. This code was from a much greater script.