Extending Objects in Windows PowerShell, Part 3
Posted on by Jeff Hicks in PowerShell
In the last part of this series, I demonstrated how to extend results that you might get back from a cmdlet. As you hopefully know, you can create an object out of thin air in PowerShell by using the New-Object cmdlet.
Extending Objects in PowerShell Article Series:
- Extending Objects in Windows PowerShell, Part 1
- Extending Objects in Windows PowerShell, Part 2
- Extending Objects in Windows PowerShell, Part 3
- Extending Objects in Windows PowerShell, Part 4
Revisiting How to Make an Object in PowerShell
To create an object in PowerShell, all you need to do is specify a hashtable of property values.
1 2 3 4 5 6 |
$obj = New-Object psobject -Property @{ Name = $env:username Computer = $env:computername OS = (Get-CimInstance Win32_OperatingSystem).Caption PSVersion = $PSVersionTable.PSVersion } |
You can also use the [PSCustomObject] type accelerator.
1 2 3 4 5 6 |
$obj = [pscustomobject]@{ Name = $env:username Computer = $env:computername OS = (Get-CimInstance Win32_OperatingSystem).Caption PSVersion = $PSVersionTable.PSVersion } |
In either event, you get an object.
This type of object can also be extended by using the same techniques I showed earlier.
1 2 3 4 5 6 |
$obj | Add-Member -MemberType ScriptProperty -Name Uptime -value { (Get-Date) - (Get-CimInstance win32_operatingsystem).LastBootUpTime } $m1= {get-service | where {$_.status -eq "stopped"}} $m2= {Param([string]$log="System") Get-Eventlog -logname $log -newest 10} $obj | Add-Member -MemberType ScriptMethod -Name GetRunning -Value $m1 $obj | Add-Member -MemberType ScriptMethod -Name GetLastLogs -Value $m2 |
I went ahead and added a script property and a few methods.
I can use this object to get some useful management information from the local computer.
Creating a Custom Server Management Framework
With this in mind, it seemed to me that I could create a custom server management framework. Here’s how this might work.
First, I need a computer name.
1 |
$computername = "chi-test01" |
Next, I’ll outline a few standard properties.
1 2 |
$os = Get-Ciminstance -ClassName Win32_operatingsystem -ComputerName $computername $PSVersion = Invoke-Command {$PSVersionTable.PSVersion} -HideComputerName -computername $Computername |
This is probably enough information to create an object.
1 2 3 4 5 6 7 |
$managed = [pscustomobject]@{ Computername = $computername.ToUpper() PSVersion = $PSVersion OperatingSystem = $os.Caption ServicePack = $os.CSDVersion LastBoot = $os.LastBootUpTime } |
Now to add some custom methods I can use as management tools.
1 2 3 4 5 6 7 8 |
$managed | Add-Member -MemberType ScriptProperty -Name ProcessCount -Value {(Get-Process -ComputerName $this.computername).count} $managed | Add-Member -MemberType ScriptProperty -Name Uptime -Value { (Get-Date) - (Get-Ciminstance win32_operatingsystem -computername $this.computername).lastBootUptime } -force $managed | Add-Member -MemberType AliasProperty -name OS -Value OperatingSystem $managed | Add-Member -MemberType ScriptMethod -Name GetFreeSpace -Value { Param([string]$Drive="c:") $disk = Get-CimInstance -Classname win32_logicaldisk -filter "deviceid = '$drive'" -ComputerName $this.computername $disk.Freespace} $managed | Add-Member -MemberType ScriptMethod -Name Reboot -value { Restart-Computer -ComputerName $this.computername -force} |
There’s one item that I haven’t show you, and that’s a property set. With a property set, you can reference a collection of properties by using a single name.
1 |
$managed | Add-Member -MemberType PropertySet -Name Boot -Value Computername,LastBoot,Uptime |
I hope that you realize that there’s no limit to the type of information and methods you could include here. Although one step I think I should have is an option to refresh the object. Should something change, I need to be able to update any static properties.
1 2 3 4 5 6 7 8 |
$refresh = { $this.PSVersion = Invoke-Command {$PSVersionTable.PSVersion} -HideComputerName -computername $this.Computername $os = Get-Ciminstance -ClassName Win32_operatingsystem -ComputerName $this.computername $this.OperatingSystem = $os.Caption $this.LastBoot = $os.LastBootUpTime $this.ServicePack = $os.CSDVersion } $managed | Add-Member -MemberType ScriptMethod -Name Refresh -value $refresh |
I’ll test by rebooting the server.
1 |
$managed.Reboot() |
What have we ended up with in terms of a management object?
By default I get all of the properties, including my alias. It might be more useful to define a default display. We can do this by defining a custom type for this object.
1 2 |
$myType = "my.ManagedComputer" $managed.psobject.TypeNames.Insert(0, $myType) |
These commands insert a new type name for my object.
Now that I have a unique type name, I can use Update-TypeData and define a default property set.
1 |
Update-TypeData -TypeName $myType -DefaultDisplayPropertySet Computername,OS,PSVersion,LastBoot,Uptime |
Notice the change?
The other properties and methods are still available should I need them.
In the final article, we’ll take one final step and explore how to use this techniques to manage at scale.