A challenge many new comers to PowerShell face, especially those arriving with a VBScript background, and one that I often talk about, is shifting gears from working with text to working with objects. Here’s a good example.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The Win32_OperatingSystem class returns a value for TotalVisibleMemorySize, which should be the amount of physical memory installed in a computer. Let’s say as a beginner PowerShell user you want to use this number. You know enough PowerShell to know you can use Select-Object to retrieve just that value:
PS C:\> gwmi win32_operatingsystem | select totalvisiblememorysize
totalvisiblememorysize
------------------------
1572144
In the VBScript world, or even other text based shells, you might be tempted to figuring out how to parse that output. Instead,a the PowerShell way is it recognize that the Get-WMIObject cmdlet wrote an object to the pipeline which Select accepted and then wrote another object to the pipeline, albeit one with a single property. You can verify this by piping the expression to Get-Member.
PS C:\> gwmi win32_operatingsystem | select totalvisiblememorysize | gm
TypeName: Selected.System.Management.ManagementObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
totalvisiblememorysize NoteProperty System.UInt64 totalvisiblememorysize=1572144
Here’s the part that may not be so obvious. PowerShell let’s us treat the entire expression as an object and as such let’s us grab just the property using the object.property format.
PS C:\> (gwmi win32_operatingsystem).TotalVisibleMemorySize
1572144
We wrap the expression in parentheses which instructs PowerShell to evaluate this first, which returns the WMI object. We don’t even need to use Select-Object because we can access the property directly. This is easier to read, but this is still an object.
PS C:\> (gwmi win32_operatingsystem).TotalVisibleMemorySize | gm
TypeName: System.UInt64
Name MemberType Definition
---- ---------- ----------
CompareTo Method int CompareTo(System.Object value), int CompareTo(Syste...
Equals Method bool Equals(System.Object obj), bool Equals(System.UIn...
GetHashCode Method int GetHashCode()
GetType Method type GetType()
GetTypeCode Method System.TypeCode GetTypeCode()
ToString Method string ToString(), string ToString(System.IFormatProvid...
If you encounter other challenges as you move to PowerShell, please feel free to use the forums at ScriptingAnswers.com.
I sometimes use the (….).Property syntax, but lately, I’ve been doing a lot more of this (using the script you provided):
gwmi win32_operatingsystem | select -expand TotalvisibleMemorySize
It’s a bit more typing, but it seems a bit more idiomatic in powershell. Now, if I had stored the result of the gwmi in a variable, I would definitely use the dot to get to the properties, but I’m trying to avoid “wide ranging parentheses”.
Just a style choice, but I thought I’d mention it.
There’s nothing wrong with that approach, other than some extra typing. But at least it is clear. Plus you are clearly thinking about objects and not trying to parse output. The final approach anyone might take will likely depend on what they are trying to do with the value. In addition to my examples in the blog entry and your suggestion, this would also work:
PS C:\> $os=gwmi win32_operatingsystem
PS C:\> $os.TotalVisibleMemorySize
This approach has the added benefit of tab completion for the property name.
Excellent post! Coming from perl/php I have had soo much trouble getting my head about this approach to scripting. Actually came across this post because of a problem at work and this solved it in under ten minutes 😀
Thanks alot and keep ’em coming!
/Powershell newbie