PowerShell

Can I Quote You on That? Quoting and Variable Expansion in PowerShell

Recently on Twitter there was a brief flurry of tweets regarding best practices when it came to using quotes in PowerShell. That is to say, whether it is better of use single or double quotes. I had my opinion, which surprisingly was at odds with most people so I thought I would revisit the topic. Especially because using quotes throws many beginning PowerShell users.

Quoting and Variable Expansion in PowerShell

First, PowerShell is pretty smart at determining what is a string or text. If you look at cmdlet help, most parameters accept values that will be treated as strings. This means you can run any one of these commands and they will all work.

get-eventlog -LogName system -newest 5 -ComputerName chi-dc04
get-eventlog -LogName "system" -newest 5 -ComputerName "chi-dc04"
get-eventlog -LogName 'system' -newest 5 -ComputerName 'chi-dc04'

For any string that doesn’t contain a space, if PowerShell knows how to treat it as a string, I don’t think you need to include any quotes. But when there are spaces, this is where it gets interesting. Again, if you have simple text, PowerShell doesn’t really care if you use ” or “”. Both of these commands will give you the same result.
get-service -DisplayName "Windows Update"
get-service -DisplayName 'Windows Update'

Now, what happens when you throw a simple variable in the mix.
PS C:> $n = "Jeff"
PS C:> "The current user is $n"

The current user is Jeff
PS C:> 'The current user is $n'

The current user is $n

More on Using Quotes in PowerShell

This is the interesting part of quoting in PowerShell. When you use double quotes, PowerShell will automatically expand the variable with its value. Thus in the first example with double quotes, $n is replaced with its value ‘Jeff’, while in the second example it is not. On Twitter, this behavior was the driving factor behind a recommended best practice. The consensus was to always use single quotes so that you don’t unintentionally expand variables.

However, I always looked at this from the other perspective. If I always use double quotes, then variables will always be expanded if they are in the string. I don’t want someone new to PowerShell to have to figure out whether to use single or double quotes. The question about accidentally expanding a variable puzzles me. Isn’t that the whole point? Now, it may be that your position depends on whether you are approaching PowerShell from a developer or IT pro perspective. I’m definitely in the latter camp.

Sponsored Content

What is “Inside Microsoft Teams”?

“Inside Microsoft Teams” is a webcast series, now in Season 4 for IT pros hosted by Microsoft Product Manager, Stephen Rose. Stephen & his guests comprised of customers, partners, and real-world experts share best practices of planning, deploying, adopting, managing, and securing Teams. You can watch any episode at your convenience, find resources, blogs, reviews of accessories certified for Teams, bonus clips, and information regarding upcoming live broadcasts. Our next episode, “Polaris Inc., and Microsoft Teams- Reinventing how we work and play” will be airing on Oct. 28th from 10-11am PST.

However, variable expansion with double quotes isn’t always easy. This is something else that often trips up beginners. Let’s say you are building a string to display as a message or write to a log file that will show the state of a service and its display name. You most likely will save the service information to a variable.

$s = get-service wuauserv

You might think all you need to do is write a string like this, using the service properties from $s.
PS C:> "The $s.displayname service is currently $s.status"

The System.ServiceProcess.ServiceController.displayname service is currently System.ServiceProcess.ServiceController.status

Not what you might have expected. While we’re at it, here’s the same string but using single quotes.
PS C:> 'The $s.displayname service is currently $s.status'

The $s.displayname service is currently $s.status

Still not what I want, but perhaps easier to read. To solve this problem, we need to use something called a sub-expression.
PS C:> "The $($s.displayname) service is currently $($s.status)"

The Windows Update service is currently Stopped

Wrap it Up! Use Parentheses to Enclose the Object and Property

The way I tell people to remember this is that by wrapping the object and property in parentheses, PowerShell evaluates that expression and holds the result in memory. Sticking a $ in front of it tells PowerShell, “Look, here’s a variable” and because I’m using double quotes it is expanded. And yes, there are other ways to build strings, which I’m not going to cover now. The point is that if I still use single quotes, I don’t get the expansion.

PS C:> 'The $($s.displayname) service is currently $($s.status)'

The $($s.displayname) service is currently $($s.status)

Sometimes, you need to use both single and double quotes. Consider the case where you are writing a script that is building a WMI filter on the fly. You would need to write the command like this:
get-wmiobject win32_service -filter "Name='spooler'"

The filter parameter is expecting a string, which I define with double quotes. The filtering value for name must also be quote for WMI and here I use single quotes. If you try either of these approaches, the command will fail:
get-wmiobject win32_service -filter "Name="spooler""
get-wmiobject win32_service -filter 'Name='spooler''

Although you can work around this by adding more quotes
get-wmiobject win32_service -filter "Name=""spooler"""
get-wmiobject win32_service -filter 'Name=''spooler'''

But I don’t recommend this technique as it is difficult to construct especially with more complex filters. If you are using variables, you can still take advantage of expansion.
$n='spooler'
get-wmiobject win32_service -filter "Name='$n'"

Even though $n is inside single quotes, the entire string is in double quotes so it gets expanded.

Using Quotes in PowerShell: The Final Word?

So what’s the best practice when it comes to quoting? Frankly I’m not sure. I think much depends on how you approach PowerShell and how you intend to use it. If you always use double quotes, simple string will still work and if the string contains a variable, it will automatically be expanded. Just remember that for rich variables, those with multiple properties, you will need to use a sub expression. If you single quotes, you may not get the result you expect, but it might be easier to read. And perhaps your preference will change over time. As a beginner you might appreciate the simplicity of only using double quotes until you have a better idea on how PowerShell works.

To learn more about this topic, be sure to read the PowerShell help topic about_Quoting_Rules.

Related Topics:

BECOME A PETRI MEMBER:

Don't have a login but want to join the conversation? Sign up for a Petri Account

Register
Comments (3)

3 responses to “Can I Quote You on That? Quoting and Variable Expansion in PowerShell”

  1. Best practice is single quotes by default and only use double quotes when interpolating variables. See http://windowsitpro.com/blog/what-do-not-do-powershell-part-7. If you follow this pattern, the quote informs the reader – any reader, whether they are familiar with the code at hand or not – whether what follows is a string literal or will possibly interpolate a variable (alternatively, it will include a lot of non-escaped single quotes or special chars like tab or new line). Additionally, some programmers believe the use of shift for double quotes increases the chance for typos, but I have seen no study on this subject.

  2. The consensus is to always use single quotes so that you don’t unintentionally expand variables. Question: Why should you be prudent when it comes to variable expansion? Answer: Because this is a security issue. In some cases, variable expansion may lead to nasty surprises and security violations, especially if the variable is environmental and/or can be controlled by the user.

  3. Hi, this is much easier to handle strings and variable expansion:
    ‘The {0} service is currently {1}’ -f $s.displayname , $s.Status

Leave a Reply

External Sharing and Guest User Access in Microsoft 365 and Teams

This eBook will dive into policy considerations you need to make when creating and managing guest user access to your Teams network, as well as the different layers of guest access and the common challenges that accompany a more complicated Microsoft 365 infrastructure.

You will learn:

  • Who should be allowed to be invited as a guest?
  • What type of guests should be able to access files in SharePoint and OneDrive?
  • How should guests be offboarded?
  • How should you determine who has access to sensitive information in your environment?

Sponsored by: