Weekend Scripter: Why Does PowerShell Hide Stuff?
Summary: Microsoft Scripting Guy, Ed Wilson, talks about how Windows PowerShell decides what to display.
Microsoft Scripting Guy, Ed Wilson, is here. This morning I received an email from a friend with whom I used to work a long time ago. (He was one of the reviewers on the WMI book I wrote in the VBScript days.) Here is his email:
Hey, Mr. Ed! How are you and the Scripting Wife? Hope you are well! I enjoy seeing your Facebook posts about your antics with your personal trainer. I have a quick Windows PowerShell question for you that has been nagging me for a while. I have a simple script that runs via Group Policy at computer startup:
$computername = gc env:computername
$applications= Get-WmiObject Win32_ComputerSystem
$applications | out-file “\serversharecomputerWin32_ComputerSystem$computername.txt”
The output of this script contains only a few of the many properties of the Win32_ComputerSystem class. Specifically, they are Domain, Manufacturer, Model, Name, PrimaryOwnerName, and TotalPhysicalMemory.
But the Win32_ComputerSystem has lots more properties than that. When I type the following command, the *.csv file contains all of the properties:
$applications | export-csv “\serversharecomputerComputerSystem$computername.csv”
How does Out-File have the audacity to pick and choose which properties to write to the file, and how does it chose them? Is there a way to tell it to write all of the properties without having to hand pick them?
Here is my reply…
It’s great to hear from you. Out-File is simply redirecting a standard output stream. With many of the WMI classes, such as Win32_ComputerSystem, we have a Format*xml file that we created to select the main properties of interest from the WMI class. The file is called DotNetTypes.format.ps1xml and it is located in the $pshome directory (which normally resolves to C:WindowsSystem32WindowsPowerShellv1.0). You can create your own Format*xml file and choose additional properties, but that is hard core.
Your variable, $applications, will hold the deserialized Win32_ComputerSystem object and permit you to call methods and access all of the properties.
But when you send it to the output formatter, it will use the format from the Format*xml file.This is the same as typing gwmi win32_computersystem at the Windows PowerShell console. Only the main properties display.
You can get around this by using Select-Object (or Format-List/Table) to choose *. This will retrieve all of the properties that are available from the Win32_ComputerSystem WMI class. Here is an example of how you might approach this:
$c = gwmi win32_computersystem
$c | select *
Now you can redirect or use Out-File to send the returned information to a text file:
$c | select * >> c:fsoc.txt
$c | select * | Out-File c:fsoc.txt
By default, te reason you get the complete information is that Export-CSV is creating a deserialized object represented as a CSV file. You can even reconstitute the object by using Import-CSV. This is a different output stream.
To select specific properties going to Export-CSV, you can again use the Select object—but this time, only select the specific properties:
$c | select Domain, Name, Manufacturer, Model | Export-Csv c:fsoc.csv
Hope all is well with you, and that this information helps clarify what you have been seeing. Stay in touch.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy