I use scriptblocks quite a bit in my PowerShell work, often saved as variables. These are handy for commands you want to run again, but don’t necessarily need to turn into permanent functions.
$freec={(get-wmiobject win32_logicaldisk -filter "deviceid='c:'" -property Freespace).FreeSpace/1mb}
Now in PowerShell I can invoke the scriptblock.
PS S:\> &$freec
94079.72265625
Ok then. I have a number of these defined. I decided I wanted an easy way to identify them when I run Get-Variable. For example, if I remembered all the variable names I could just do this:
PS S:\> get-variable freec,dirt
Name Value
---- -----
freec (gwmi win32_logicaldisk -filter "deviceid='c:...
dirt Param([string]$Path=$env:temp) Get-ChildItem ...
But needless to say that’s asking too much. When I first looked at this problem I went down the path of trying to parse values I saw with Get-Variable to identify potential script blocks. Then I realized this was a rookie mistake. PowerShell is all about the objects. Now a variable is also an object with a value property. This value could be a string, and integer or a pscredential. So my task then was to identify each value type.
Every object in PowerShell has a built in method called GetType().
PS S:\> $s=get-service spooler
PS S:\> $s.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False ServiceController System.ComponentM...
This is actually another object with a Name property.
PS S:\> $s.GetType().name
ServiceController
Aha! Let’s look at this with my variable.
PS S:\> (get-variable freec).value.GetType().Name
ScriptBlock
This is a one-line shortcut that gets the Value property of the Freec variable and then runs the GetType() method followed by retrieving just the Name property. This is promising. Here’s one way I can use this:
get-variable | Where {$_.value.GetType().Name -eq "ScriptBlock"}
As you can see there is still an issue with variables with no values.
I’ll just add another condition to my Where expression.
get-variable | Where {$_.value -AND $_.value.GetType().Name -eq "ScriptBlock"}
Success!
These are in fact all of the scriptblocks in my current session. But now I can take this a step further and look at my other variables and their type.
get-variable | select Name,@{Name="Type";Expression={$_.value.GetType().Name}}
Or I might try grouping.
get-variable | select Name,@{Name="Type";Expression={$_.value.GetType().Name}} | where {$_.type} | Group Type | Sort Count -Descending
I wanted to filter out empty values so I’m only keeping objects that have a defined type in my grouped output.
The bottom line is never forget about the object!





Pingback: Get My PowerShell Variable Revisited | The Lonely Administrator