Lately I've been writing about my use of PowerShell type extensions as a way to get more done quickly. Or at least give me the information I want with minimal effort. I use Hyper-V a great deal and the Hyper-V cmdlets are invaluable. And while a command like Get-VM provides a lot of information, I always seem to want more so I thought I'd share with you my Hyper-V related type extensions. Even if you don't need or use Hyper-V, you might find my techniques useful.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The object type for a Hyper-V virtual machine is Microsoft.HyperV.PowerShell.VirtualMachine which you can get easily enough by running Get-VM and piping it to Get-Member. Using Update-TypeData, there are a number of script properties I want to define. These are properties where the value is calculated by a PowerShell script block. For example, I want to be able to quickly see if a virtual machine is missing any of its configured disk files. I could run a command like this:
But if I want this information often, that's too much typing. So instead I can create a script property with this script block. This version takes into account that the VM might have multiple disks, one or more of which might be missing.
{ if ($this.HardDrives) { #test if there are any false results if ( ($this | Get-VMHardDiskDrive | Test-Path) -contains $False ) { $False } else { $True } } else { #no hard drive files configured or found $false } }On a related note, I'd like to know how much disk space the virtual machine is consuming.
{ $stat = Get-VMHardDiskDrive -VMName $this.vmname | Get-Item | Measure-Object -Property length -sum [math]::Round($stat.sum/1GB,2) }I also like to know the path to the configuration file. This will be a vmcx file with a file name that matches the virtual machine's ID.
Join-path -Path "$($this.configurationLocation)\Virtual Machines" -ChildPath "$($this.vmid).vmcx" -ResolveIn order to define these, and a few others, I use code like this in my PowerShell profile script.
I define a hashtable where the key will be the property name and the value is the scriptblock I will use.
$extensions = @{ TestVHD = { if ($this.HardDrives) { #test if there are any false results if ( ($this | Get-VMHardDiskDrive | Test-Path) -contains $False ) { $False } else { $True } } else { #no hard drive files configured or found $false } } ConfigurationFile = { Join-path -Path "$($this.configurationLocation)\Virtual Machines" -ChildPath "$($this.vmid).vmcx" -Resolve } Diskpath = {$this.Harddrives.path} Running = { if ($this.state -eq 'Running') {$True} else { $False}} SizeGB = { $stat = Get-VMHardDiskDrive -VMName $this.vmname | Get-Item | Measure-Object -Property length -sum [math]::Round($stat.sum/1GB,2) } }Next I define a hashtable of parameters that I will splat with Update-TypeData.
$params = @{ TypeName = 'Microsoft.HyperV.PowerShell.VirtualMachine' MemberType = 'ScriptProperty' MemberName = '' Value = '' Force = $True }The last step is to enumerate the extensions and update type data.
$extensions.GetEnumerator() | foreach { $params.memberName = $_.key $params.value = $_.value # Write-Host "Creating script property $($_.key)" -ForegroundColor cyan Update-Typedata @params }By using hash tables, my code organized and easier to read.
And now I can run commands like this:
I love that PowerShell provides the flexibility to meet my needs. As always, comments and feedback are welcome.