11
Get-WmiObject -Class win32_logicaldisk -Filter 'DeviceID="C:"'

does what I want,

$var="C:"
Get-WmiObject -Class win32_logicaldisk -Filter 'DeviceID="{$var}"'

does nothing. I tried to change the quotes, to concatenate strings, and other 1000 things, but they didn't work. Why the above example doesn't work, and what would work?

Andrei
  • 961
  • 1
  • 9
  • 29
  • `-Filter "DeviceID='$var'"` (notice the double-quotes around the filter string) – Mathias R. Jessen Dec 01 '16 at 16:16
  • @MathiasR.Jessen as mentioned, I tried to reverse the quotes, it doesn't work – Andrei Dec 01 '16 at 16:20
  • 1
    Did you actually try it? In your example you've put `{}` around the variable, which will surely make the query return nothing – Mathias R. Jessen Dec 01 '16 at 16:22
  • didn't notice the `{}`. Now it works. I can't believe this did not happen to be one of the 1000 things I've tried, because for sure I tried `'DeviceID="$var"'`, and I thought that `' '`and `" "` are the same, but each one goes inside the other. Still, do you know why the `{}` didn't work? I used `{$var}` inside strings a lot of times, and just now it didn't work. Also, you can add your solution as an answer. – Andrei Dec 01 '16 at 16:26
  • 1
    `${var}` would have worked, and resulted in the string `C:`, but `{$var}` would result in the string `{C:}` – Mathias R. Jessen Dec 01 '16 at 16:30
  • [Here](https://stackoverflow.com/a/74757686/1147688) I provide a few different methods, to expand *commandlet* arguments, using variables. – not2qubit Dec 11 '22 at 01:10

3 Answers3

13

When you start a string literal with ' (single-quotes), you're creating a verbatim string - that is, every character inside the string is interpreted literally and variable references and expressions won't expand!

Use " if you want the variable to be expanded:

$var = 'C:'
Get-WmiObject -Class win32_logicaldisk -Filter "DeviceID='$var'"

If your variable name has weird characters, or is followed by a word character, you can qualify the variable name with curly brackets {} immediately after the $:

$var = 'C:'
Get-WmiObject -Class win32_logicaldisk -Filter "DeviceID='${var}'"
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
6

If, for instance, you're getting data from a file with select-string, the return is a single quote string. If that string contains variables they won't expand. Invoke-Expression can be used if the variable is clean - not mixed in with other text:

$abc = 123
$a = '$abc'
iex $a -> 123

If the variable is part of a path name, this doesn't work. Use $ExecutionContext.InvokeCommand.ExpandString($var)

$path = '$Home/HiMum'
$ExecutionContext.InvokeCommand.ExpandString($path)
-> /home/JoeBlogs/HiMum

You lucky sods on Windows might be able to use Convert-String to change singles to doubles.

gryphonB
  • 89
  • 1
  • 1
3

I didn't find expanding expressions in PowerShell, but here's what I found.

# Let's set some varaible
$ComputerName = 'some-value'

# Let's store this variable name
$name = 'ComputerName'

# Get value by `Get-Item`.
(Get-Item variable:$name).Value # throws an exception for undefined variables.

# Get value by `Invoke-Expression`
Invoke-Expression "`$variable:$name"
Invoke-Expression "`$$name"

The same but for environment variables

(Get-Item env:$name).Value # throws an exception for undefined environments.
Invoke-Expression "`$env:$name"

I prefer Get-Item as it "fails loudly".

And Get-Item allows to use additional literals during this process, as well as Invoke-Expression.
I.e. see the Computer literal below before the $ sign.

$otherName = 'Name'

(Get-Item variable:Computer$otherName).Value
(Get-Item env:Computer$otherName).Value
it3xl
  • 2,372
  • 27
  • 37