2

Im trying to build a variable consisting of several other variables to then include, eg:

$myString = "{$_.Name -like "
$myString += $computer[0]
$myString += " -Or $_.Name -like "
$myString += $computer[1]+"}"

Get-VM | Where $myString

I've tried all possible combinations with $($myString),$myString,${$myString}, etc ... It still lists all computers as if there been no filter to it. If i ECHO the Get-VM... it looks prefectly fine and if i cut'n'paste it it works.

Any one got a clue?

1
  • You can't use a string in this way, you need a scriptblock. Commented Mar 19, 2013 at 14:59

2 Answers 2

3

Where-Object filters are scriptblocks. Script blocks are compiled before runtime, and the variable references in them are fixed in the scriptblock then. One way to delay that is to use [scriptblock]::create to create the script block after the local variables are set, just before you use it.

$myString = "$_.Name -like "
$myString += $computer[0]
$myString += " -Or $_.Name -like "
$myString += $computer[1]

$filter = [scriptblock]::create($myString)

Get-VM | Where $filter
Sign up to request clarification or add additional context in comments.

1 Comment

My savior! Thanks for both the explanation of ScriptBlocks and the solution! Worked like a charm. :)
1

You should use a scriptblock. It will expand the variables every time you call it. I got Hyper-V installed myself, so I made an example for you:

PS > $computer = "DC", "SQL"

$mywherestatement = { $_.Name -like $Computer[0] -or $_.Name -like $Computer[1] }

Get-VM | Where $mywherestatement

Name State CPUUsage(%) MemoryAssigned(M) Uptime   Status
---- ----- ----------- ----------------- ------   ------
DC   Saved 0           0                 00:00:00 Operating normally
SQL  Saved 0           0                 00:00:00 Operating normally



PS > $computer = "CLIENT", "WebDev"

Get-VM | Where $mywherestatement

Name   State CPUUsage(%) MemoryAssigned(M) Uptime   Status
----   ----- ----------- ----------------- ------   ------            
CLIENT Saved 0           0                 00:00:00 Operating normally
WebDev Saved 0           0                 00:00:00 Operating normally

If your $computer array only contains the names you want to check, I'd use -contains instead, because it will work with arrays of any size. Ex:

PS > $computer = "DC", "SQL", "CLIENT", "WebDev"

Get-VM | Where { $Computer -contains $_.Name }

Name   State CPUUsage(%) MemoryAssigned(M) Uptime   Status            
----   ----- ----------- ----------------- ------   ------            
CLIENT Saved 0           0                 00:00:00 Operating normally
DC     Saved 0           0                 00:00:00 Operating normally
SQL    Saved 0           0                 00:00:00 Operating normally
WebDev Saved 0           0                 00:00:00 Operating normally

6 Comments

Thanks C.B. and Graimer, the problem is that i can be either 1, 5, 14 computers i want to filter so i have to dynamicaly build the $_.Name -like according to the numbers of computers i want to filter thats why im built in a string, what i didnt mention in my original post is that i do a loop building the string based on number of computers.
see the updated answer. If you really need to build the string ($computers has more then the VMs you want to get), you should use mjolinor's answer. Personally I would've made the script work with -contains :)
Going nuts, what i have is ForEach($VM in (Get-VM | where $mywherestatement)) { with the -containsit comes up empty, i'll have a go with mjolionr's answer and see if it goes better...
I'm sorry, but if it didn't work, you didn't use it right. The last example in my answer works perfectly, using -contains works perfectly with ForEach($VM in (Get-VM | where { $Computer -contains $_.Name })) {.
No need to be sorry @Graimer, you're help was most appreciated. Can it be because i'm using a wildcard in the $Computer-array? This is my result if trying with -contains: Where-Object : Cannot convert 'dc-cust* ' to the type System.Management.Automation.ScriptBlock' required by parameter 'FilterScript'. Specified method is not supported.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.