I saw a question on Twitter the other day about how to include the Notes property when running the Get-VM Hyper-V cmdlet. I'm reading between the lines, but I think the desired goal was to include the Notes property. Here are a few ways you might tackle this problem. And even if you don't use Hyper-V, the concepts are equally valid should you need to customize the output from a different PowerShell command.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
PowerShell is all about objects, which is a good thing. Fortunately for us, the PowerShell team planned ahead and didn't create commands that emitted fixed objects. They gave us the tools to customize the output to meet our needs. That is the case here.
You typically get an easy-to-read result when you run a cmdlet in PowerShell, especially one from Microsoft. When the command was being developed, someone decided what information to display and how to display it. Many commands, like Get-VM, write a rich object to the pipeline. However, you only see a subset of that information. It is easy to see all available properties using Select-Object.
If I want to view something, all I have to do is tell PowerShell to show it to me.
Get-VM | Where-Object state -EQ running |
Select-Object -Property Name, State, Version, Uptime, AutomaticStartAction, Notes
But let's suppose I want to get these properties frequently. It will become pretty tedious to keep re-typing the Select-Object statement. Here is one option.
Property Sets
PowerShell has a concept of property sets. A property set allows you to use a single property name to retrieve a group of properties. Some of these sets are defined by default. To see for yourself, run this command.
Get-Process | Select-Object PSResources
You'll get a group of related properties. In the case of the virtual machine, it would be nice to have a property set that includes Notes property. But there's a slight catch. You use Update-TypeData to extend objects. But a property set requires a specially formatted ps1xml file. Don't panic. I got your back.
Install the PSTypeExtensionTools module from the PowerShell Gallery. I've written a command that will generate the XML file for you.
$splat = @{
Typename = 'Microsoft.HyperV.PowerShell.VirtualMachine'
Name = 'MgmtInfo'
FilePath = 'C:\scripts\mgmtinfo.types.ps1xml'
Properties = 'Name', 'State', 'Version', 'Uptime', 'AutomaticStartAction', 'Notes'
}
New-PSPropertySet @splat
The Typename value is what you see when piping an object to Get-Member. The Name value will be the name of the new property set. The path is self-explanatory. The typical naming convention is objectType.types.ps1xml. I deviated slightly. And, of course, the properties are the members of the new set.
Running this command generates this XML file.
<?xml version="1.0" encoding="utf-8"?>
<!--
This file was created with New-PSPropertySet from the
PSTypeExtensionTools module which you can install from
the PowerShell Gallery.
Use Update-TypeData to append this file in your PowerShell session.
Created 01/18/2022 08:33:05
-->
<Types>
<Type>
<Name>Microsoft.HyperV.PowerShell.VirtualMachine</Name>
<Members>
<PropertySet>
<Name>MgmtInfo</Name>
<ReferencedProperties>
<Name>Name</Name>
<Name>State</Name>
<Name>Version</Name>
<Name>Uptime</Name>
<Name>AutomaticStartAction</Name>
<Name>Notes</Name>
</ReferencedProperties>
</PropertySet>
</Members>
</Type>
</Types>
To use this in my PowerShell session, I need to import it.
Update-TypeData -AppendPath $splat.FilePath
I now have a new property.
You must separate the idea of what to display from how to display it. Formatting is a separate task.
The property set is no different than any other property. I could just as easily run a command like this:
Get-VM | Where-Object state -EQ running |
Select-Object -Property MgmtInfo | Out-GridView
By the way, this property set is only defined for the duration of my PowerShell session. If this is something I want all the time, I would add the Update-TypeData command to my PowerShell profile script.
Changing the Defaults
Technically, you can use Update-TypeData to change the default property set. Use Get-TypeData to discover.
However, this list of default properties doesn't necessarily mean this is what you see.
The default output for Get-VM is a formatted table. See the distinction between what to display and how it should be displayed?
I can update the DefaultDisplayPropertySet easily enough.
The default table view doesn't have a definition for the Notes property, so I don't see it. But I can fix that, too.
Custom Format File
I've written about this step several times. The easiest step is to create a custom formatted view using the New-PSFormatXML command from the PSScriptTools module. I'll assume the desired result is the current view with the addition of the Notes property.
To use the command, you need a sample object with a value for all the properties you want to use.
$splat = @{
Path = 'c:\scripts\vmnotes.format.ps1xml'
ViewName = 'notes'
Wrap = $true
Properties = 'Name','State','CpuUsage','MemoryAssigned',
'Uptime',@{Name='Version';Expression={$_.status}},'Notes'
}
Get-VM dom1 | New-PSFormatXML @splat
I'm going to create a new table view called 'notes.' I'll point out that as I was writing this I discovered a minor bug in New-PSFormatXML. If you run this code you might get an error that CpuUsage is a read-only property. This won't affect the result, and you can ignore the error. I'll have to look into this later.
Like the types ps1xml file, you need to update PowerShell to use the new format.
Update-FormatData $splat.path
You'll notice that some of the data is a bit raw, like the MemoryAssigned values. Notes in the XML file show you how to customize and format the output.
Summary
When it comes to extending PowerShell, there are several approaches you can take. It ultimately comes down to how you intend to consume the information. Do you need a custom property set to simplify your PowerShell command? Or do you need a formatted result with the desired information? Hopefully, this will get my friend on track.
Well, it’s really nice how a tweet turned into a great tutorial. I’m glad I commented on that, it got me a great resource for how customize the display of PowerShell output.