AirAzure
AirAzure

Reputation: 117

When do values passed to a parameter require quotes?

I have been working with Exchange Online unified groups and Microsoft Teams teams in powershell: New-UnifiedGroup, Set-UnifiedGroup, Get-UnifiedGroup, New-Team, Get-Team etc. I have been creating groups and teams from PowerShell.

I am interested in understanding a bit better when a value for a parameter requires quotes and when it does not.

When I import from CSV, it seems the values are automatically interpreted as strings. When I supply them to a parameter that requires a string, the value does not require quotes even if it has spaces e.g New-UnifiedGroup -DisplayName $item.displayName does not require quotes even when the display name has spaces.

But when I want to create a team from an existing group, and I get the ID of the group, the group id requires quotes: New-Teams -GroupId "$group.ExternalDirectoryObjectId". In this case the parameter -GroupId requires a string value, although the ExternalDirectoryObjectId that it requires is not a string.

Is there a rule that a value does not require quotes if it is a string, and a string value is expected? Does it help to declare a variable as a string before passing it to a parameter that requires a string? For example, if I have a $path variable, I usually have to provide it as -Path "$path". If I declared the path as [String]$path =, would I then not need to use the quotes in -Path $path

Upvotes: 3

Views: 1323

Answers (2)

mklement0
mklement0

Reputation: 437176

  • Generally, only ever use quoting in PowerShell to explicitly pass a value as a string ([string]).

    • String-literal arguments require quoting if they contain any of the following: spaces or, more generally, PowerShell metacharacters[1], as well as commands or expressions (enclosed in $(...)) if they are part of a larger string (see below).

    • If a string-literal argument is to be used verbatim, use '...' i.e. enclose it in a single-quoted aka verbatim string (use '' to embed a literal ').

  • To pass the value of a variable, one of its properties, or even the result of a method call on it, you do not need quoting in PowerShell (except as part of a larger string - see below), which will pass the resulting value with its original data type; however, when the value is bound to its target parameter, PowerShell may automatically convert it to the parameter's type.

    • If the target parameter is [string]-typed (as is the case with New-Team's -GroupId parameter), PowerShell will automatically convert any non-string argument to a string, essentially by calling .ToString() on it[2]. If the resulting string isn't the right representation, you must perform explicit stringification, by way of an expression or command.

    • E.g., both -GroupId $groupId and -GroupId $group.ExternalDirectoryObjectId work without quoting - even if the string value being passed contains embedded spaces or other PowerShell metacharacters.

  • If you need to pass an object's property, a method call, or any type of command or expression as part of a larger string, enclose the argument in "..." (i.e. a double-quoted, so-called expandable (interpolating) string) (use `" or "" to embed a literal ") and use $(...), the subexpression operator around the expression / command; e.g., "$($group.ExternalDirectoryObjectId)/more"; referencing a variable (including an environment variable) by itself inside "..." does not require $(...); e.g. "$HOME\Project" or "user:$env:USERNAME".

    • Note that "$group.ExternalDirectoryObjectId" definitely does not work as intended, because only variable reference $group by itself is recognized - and stringified - whereas the .ExternalDirectoryObjectId part is treated literally - see first link below for why.

    • A variable-as-a-whole reference preceded or followed by a literal - e.g. $HOME\projects or user:$env:USERNAME - does not strictly need double-quoting, but to avoid edge cases it's better to use it.

Further reading:


[1] The metacharacters are (some only need quoting if at the start of the argument):
<space> ' " ` , ; ( ) { } | & < > @ #

[2] The exact stringification rules, where culture-sensitivity factors in as well, are detailed in this answer.
Generally, PowerShell has a very flexible automatic type-conversion system whose rules are complex and not explicitly documented - a peek at the source code may help.
PowerShell always tries to automatically convert a given value to the target type, where the target type may be dictated by a parameter's type or the (usually) LHS operand of an operator-based expression (e.g., 42 + "1" yields 43).

Upvotes: 5

js2010
js2010

Reputation: 27428

That's strange. Usually you only need quotes to pass a literal string that has a space in it.

get-childitem -path 'foo 2'

I can pass an object property without quotes usually:

$a = [pscustomobject]@{path = 'foo 2'}
get-childitem -path $a.path

This is more rare, but if a string looks like an array element, I've found I have to quote it:

select-xml -XPath "//*[@a='hi']" -Path file.xml

Even using something like an integer works without quotes, because it can be 'coerced' into a string.

Upvotes: 0

Related Questions