2

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

AirAzure
  • 97
  • 1
  • 5
  • My question perhaps has too many sub-questions. One is: if I pass as variable of type string to a parameter that requires a string, is it always true that it does not require quotes to handle spaces? If that is true, what is the rule? – AirAzure Jun 02 '20 at 06:26
  • In another case, I have taken the value of a property that does not have spaces, and passed it to a parameter that requires a string. This fails, unless I enclose the value in quotes. The value I am using is ```$group.ExternalDirectoryObjectId```. To make it simpler, I have first converted this to another variable: ```$groupId = $group.ExternalDirectoryObjectId```. Then I have used ```$team = New-Team -GroupId "$groupId"```. This fails unless I put "$groupId" in quotes. I am assuming this is because $groupId is not a string, and that putting it in quotes converts it. – AirAzure Jun 02 '20 at 06:32
  • Seems to be the result of testing error on my part. After stripping it down and starting again, ```groupId``` does not require quotes. I also found that the ```ExternalDirectoryObjectId``` is a string, even though all the other types of Id are GUID types. So even less reason to need quotes. But the responses helped me to identify what should and shouldn't work. Thanks. – AirAzure Jun 02 '20 at 15:46

2 Answers2

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

    • String literals require quoting if they contain any of the following: spaces or, more generally, PowerShell metacharacters[1], and commands or expressions as part of a larger string (which must then be enclosed in $(...) - see below).
  • 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, 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 would work - even if the resulting string 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 "..." and use $(...), the subexpression operator around the expression / command (e.g., "$($group.ExternalDirectoryObjectId)/more"; referencing a variable by itself inside "..." does not require $(...)).

    • "$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.

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).

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Your answer is very helpful. Bullets: 1) Yes. 2.1) They don't work. 2.2) Thanks, that's the bit I didn't know. Is there a rule for that? 3) Yes. 3.1) Ah, now I can see why that would not work. Also, as you clarified later. So, I am left with the puzzle about why ```$team = New-Team -GroupId "$groupId"``` requires the quotes. There must be something else going on, because I also find I cannot combine the parameter with other splatted parameters. I will mark this as answered, and raise another question specifically on "New-Team". Thanks. – AirAzure Jun 02 '20 at 06:45
  • @AirAzure Please see the new footnote I've just added to the answer. Re the need to quote `$groupId`: mysterious, indeed; good idea to ask a separate question focused just on that. – mklement0 Jun 02 '20 at 13:00
0

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.

js2010
  • 23,033
  • 6
  • 64
  • 66