September 7th, 2014

Weekend Scripter: Don’t Break PowerShell Script with Line Breaks

Doctor Scripto
Scripter

Summary: Microsoft Scripting Guy, Ed Wilson, talks about line breaks in Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. This morning, the weather is cool for a change. It was a great morning to get up and take a walk through a peach grove. There is actually a sidewalk through the peach grove here. Peach season is nearly over, so the peach trees still have leaves, but no peaches on them now.

One of the problems with writing books, blogs, and papers about Windows PowerShell is that the line length is pretty much limited to 80 characters. With modern monitors and the Windows PowerShell ISE, I can have lines that are nearly triple that length. The line still fits on screen, and I do not have to scroll.

There is, in fact, a double-edged sword with Windows PowerShell. The commands are easy to read and understand, but quite often, cmdlet names are incredibly long. The argument is, "Well, with Tab completion, I do not actually have to type the complete cmdlet name."

But the argument contrary to that is, "With thousands of cmdlets, Tab completion is not as effective as it once was." In fact, on my laptop, there 13 cmdlets that have names that are 41 characters long or longer. Here is the script I wrote to figure this out:

PS C:\> Get-Command | select name, @{LABEL='length';EXPRESSION={($_.name.tostring().length)}} |  sort length -Descending | where length -ge 41

Name                                                                               Length

—-                                                                               ——

Disable-NetAdapterEncapsulatedPacketTaskO…                                           47

Enable-NetAdapterEncapsulatedPacketTaskOf…                                           46

Set-WinAcceptLanguageFromLanguageListOptOut                                            43

Remove-VMNetworkAdapterRoutingDomainMapping                                            43

Remove-VpnConnectionTriggerDnsConfiguration                                            43

Get-WinAcceptLanguageFromLanguageListOptOut                                            43

Get-NetAdapterEncapsulatedPacketTaskOffload                                            43

Set-NetAdapterEncapsulatedPacketTaskOffload                                            43

Get-VMNetworkAdapterFailoverConfiguration                                              41

Remove-VpnConnectionTriggerTrustedNetwork                                              41

Reset-MsolStrongAuthenticationMethodByUpn                                              41

Set-VMNetworkAdapterFailoverConfiguration                                              41

Reset-MsolStrongAuthenticationMethodByUpn                                              41

When I have a cmdlet that is 47 characters long, I have little hope of fitting the command on a single line. So what do I do?

Pipe to the left

The easiest thing to do with a Windows PowerShell script is to break the line at the pipe character, and then continue the script on the next line. In the following examples, I am using the Windows PowerShell ISE with Windows PowerShell 4.0 on my Windows 8.1 laptop.

Note  If I am typing interactively at the Windows PowerShell console, I can keep typing and the command will wrap and go to the next line. The problem comes when I try to paste that command into a Word document or into a blog. It confuses people, and often when they try to copy and paste from the blog to the Windows PowerShell ISE, the script simply does not work. This can be really frustrating. One solution is to upload the script to the Script Center Repository and simply let people download it. This is what I do for longer scripts.

Breaking the script at the pipe character often works well. It is my preferred way of doing things. Here is what my previous script works out to be:

Get-Command |

select name, @{LABEL='length';EXPRESSION={($_.name.tostring().length)}} | 

sort length -Descending |

where length -ge 41

Break at commas to create incomplete commands

Another easy way to break the script is to break it at the comma. When I do that, Windows PowerShell realizes that there will be more to the command, and it automatically looks to the next line. So again using my previous script as an example, I can break at the comma between Name and my new property, Length:

Get-Command |

select name,

@{LABEL='length';EXPRESSION={($_.name.tostring().length)}} | 

sort length -Descending |

where length -ge 41

Break at a semicolon

Using the same principle as the comma, I can also break my command at a semicolon. I can even indent a bit, to line things up and make it easier to read. This is shown here:

Get-Command |

select name,

  @{LABEL='length';

       EXPRESSION={($_.name.tostring().length)}} | 

sort length -Descending |

where length -ge 41

Break at the equals sign

I can also break the script at the equals sign. So as shown here, at Expression =, I break the command at the equals sign:

Get-Command |

select name,

  @{LABEL='length';

       EXPRESSION=

         {($_.name.tostring().length)}} | 

sort length -Descending |

where length -ge 41

When it doesn't work…

There are times, however, when it just doesn't seem to work out the way I would like it to. For example, when I use the following script, an error message appears that says –unique is not a recognizable command.

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

    Select-Object -Property processname, id,

        handles | Sort-Object -Property processname -Descending

        -unique

What if I leave the hyphen ( ) on the upper line, and hope Windows PowerShell is smart enough to continue to the next line?

Nope. The following command also generates an error message:

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

    Select-Object -Property processname, id,

        handles | Sort-Object -Property processname -Descending –

        unique

This is where I use line continuation

For those occasions where I cannot break a command logically so that Windows PowerShell realizes I want to go to the next line to complete the command, I have to use the line continuation character. The line continuation character is the backtick ( ` ). (This is also known as the "grave accent." On my keyboard, it appears under the tilde ( ~ ).)

The revised script is shown here:

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

    Select-Object -Property processname, id,

        handles | Sort-Object -Property processname -Descending `

        -unique

Here is the command and output from the command as seen in my Windows PowerShell ISE:

Image of command output

Join me tomorrow when I begin a discussion of WMI and Windows PowerShell.

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

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • Nir Sim

    So simple and so significant `
    Thanks