PowerShell Code Breaks: Break Line, Not Code


Summary: Ed Wilson, Microsoft Scripting Guy, talks about line continuation without breaking Windows PowerShell code.

Hey, Scripting Guy! Question Hey, Scripting Guy!

I have a problem sometimes when I copy code from the Hey, Scripting Guy! Blog. It does not seem to work. I try to take out spaces, but it still doesn’t work. I am at my wits end because the code should do exactly what I want it to do, but I cannot get it to work. Can you help me?

—BG

Hey, Scripting Guy! Answer Hello BG,

Microsoft Scripting Guy, Ed Wilson, is here. It is definitely summer here in Charlotte, North Carolina. When the sun comes up, it is already hot, and when the sun goes down, it is hot. At night, well…it is still hot. Anyway, one thing that goes well with hot weather, is hot tea—it is very refreshing. So I have a nice cup of Gunpowder green tea and a biscotti. I decided to use my Windows Surface Pro 3 to check my email sent to scripter@microsoft.com, and I ran across your email.

Why break code in the first place?

When writing code that will be printed in a book, I need to keep my code lines to around 80 characters in length. When writing code that will be placed on a blog, I need to keep within constraints of my current blogging platform, which is around 85 characters, but not much more than that.

As an IT pro, I like to keep my code to a little less than the width of my monitor. So this means that if I do not need to scroll to see the rest of my code, I am cool. As a best practice, I recommend that when you write Windows PowerShell code (or any code for that matter), you avoid scrolling to see the remainder of the code. This is because it makes reading and troubleshooting code a problem.

With high resolution video cards and monitors, this line constraint is not a huge deal, but for books, it becomes a major problem—especially because so many Windows PowerShell cmdlet names are very long, as are many .NET Framework namespaces, classes, and member names. Typing is not a major issue because we have IntelliSense and Tab completion, but restricting code to 80 characters becomes a major pain.

Please keep this in mind: There is no virtue in writing "narrow code” (that is, code that is 80 lines or less in length) simply for the sake of having narrow code. To do so often requires the use of intermediate variable assignments, use of enumeration numeric values, and other techniques that can make code more difficult to read.

If you are not writing code for a book or for a blog post, as far as I am concerned, if the code fits on the screen, you are cool. If you have great eye sight and can read 4 pixel characters at 1920 x 1080 (or greater) resolution, you can get an lot of code on a single line without the need to break your code. On the other hand, if you bump your font size to real large and you have a screen resolution of 600 x 800, your code lines will be short to avoid scrolling.

In Windows PowerShell, there is the line continuation character. It is the backtick ( ` ), but it needs to be placed properly or it does not work. So how do I break my code lines without breaking the code?

What's the best way to break code?

When a line of code is too long, it needs to continue on the next line. This is often referred to as line continuation, or sometimes breaking your code (because you break the line into pieces, not because you actually broke the code and it no longer works). However, at times, this is exactly what happens—a piece of perfectly working code becomes nonfunctioning because it was inproperly broken into pieces.

If I have a command such as the one here, I do not need to continue the command on another line:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME

But when I decide that I want to select specific properties from the object, I am going to continue to the next line. In this particular case, the best way to do this is to place the pipeline character on the end of the line, and then place the Select-Object cmdlet on the following line. If I do not choose too many properties, I can avoid continuing the second line to a third line. This is shown here:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64

But, what if I want more than the four properties I have selected on the second line? How do I continue to the third line? In this case, the comma will serve as my line continuation because Windows PowerShell knows that if I have a comma at the end of a line, and I continue property selection on the next line, everything will be fine. This code is shown here:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64,

VirtualMemorySize

As shown here, I could have used the line continuation character, but it was not necessary:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64, `

VirtualMemorySize

I also could have placed the line continuation character at the end of the line, and added a comma on the next line, as shown here:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64 `

, VirtualMemorySize

This code looks strange to me, but as shown here, it does work:

Image of command output

In the following code, it might seem that the backtick is required because it generates an error message if it is left out:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64,

VirtualMemorySize |

Format-Table -Property `

    ProcessName, ID

Image of command output

However, remember that I can leave out line continuation from properties that are separated by commas. So all I need to do is to revise the way the code appears a bit:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64,

VirtualMemorySize |

Format-Table -Property ProcessName,

    ID

I can also break code when I open or close braces. This is shown here:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64,

VirtualMemorySize |

Format-Table -Property ProcessName,

    ID, @{

     Label = 'CPU'; Expression = { [int]$_.cpu }

     }

In addition, I can break when I open or close a parenthesis:

Get-Process -Name powershell_ise -ComputerName $env:COMPUTERNAME |

Select-Object -Property ProcessName, Id, CPU, VirtualMemorySize64,

VirtualMemorySize |

Format-Table -Property ProcessName,

    ID, @{

     Label = 'CPU'; Expression = { [int]$_.cpu }},

     @{ Label = 'VM64';

        Expression = {(

         $_.VirtualMemorySize64

         ).Tostring()

         }}

I can even break at the period (or dot). In the following example, I move the method call to the next line. It looks really strange, but Windows PowerShell knows how to interpret it:

Image of command

The best thing is to leave out the line continuation character and simply break at the pipe, the comma, the brace, or the parenthesis because Windows PowerShell is expecting it anyway, and you avoid a potential source of failure.

BG, that is all there is to using Windows PowerShell line continuation. Join me tomorrow when I have a guest post about single versus double quotation marks.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (3)

  1. Hello Ed! How do you think about what Bartek wrote here:
    https://becomelotr.wordpress.com/2013/01/06/quick-tip-break-a-code-differently/

    I tend to ‘break the line’ with either the pipeline character, or I use splatting or read-strings. Look at this example:

    $groupName = ‘foo’

    $query = @"
    ‘select SMS_R_USER.ResourceID,
    SMS_R_USER.ResourceType,
    SMS_R_USER.Name,SMS_R_USER.UniqueUserName,
    SMS_R_USER.WindowsNTDomain
    from SMS_R_User where SMS_R_User.SecurityGroupName = "$groupName"’
    "@

    $params = @{
    ‘Collection name’ = ‘Name’
    ‘QueryExpression’ = $query
    ‘RuleName’ = ‘rulename’
    }

    Add-CMUserCollectionQueryMembershipRule @params -Verbose

    Keep the code clean imho. What do you think?

  2. Martin says:

    Pedantically (thanks to Don Jones), the backtick is the escape character and not a distinct line continuation char.

    Also, if you have to use it make certain that there are no characters after the backtick. It absolutely must be last character on the line.

  3. Brad_Voris says:

    I like Richard’s suggestion for line breaks makes sense and its a bit cleaner than what I have been doing in the past. Will have to use this to clean up my code. Thanks for the suggestion Richard. Oh I do use a lot of notation in my code for breaking down
    areas (mainly to explain what a particular function is in the script)

Skip to main content