Coming Soon: GET:IT Endpoint Management 1-Day Conference on September 28th at 9:30 AM ET Coming Soon: GET:IT Endpoint Management 1-Day Conference on September 28th at 9:30 AM ET
PowerShell

Extending Objects in Windows PowerShell, Part 3

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:

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.

$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.

Sponsored Content

Say Goodbye to Traditional PC Lifecycle Management

Traditional IT tools, including Microsoft SCCM, Ghost Solution Suite, and KACE, often require considerable custom configurations by T3 technicians (an expensive and often elusive IT resource) to enable management of a hybrid onsite + remote workforce. In many cases, even with the best resources, organizations are finding that these on-premise tools simply cannot support remote endpoints consistently and reliably due to infrastructure limitations.

$obj = [pscustomobject]@{
  Name = $env:username
  Computer = $env:computername
  OS = (Get-CimInstance Win32_OperatingSystem).Caption
  PSVersion = $PSVersionTable.PSVersion
}

In either event, you get an object.

Our new object in Windows PowerShell. (Image Credit: Jeff Hicks)
Our new object in Windows PowerShell. (Image Credit: Jeff Hicks)

This type of object can also be extended by using the same techniques I showed earlier.

$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.

Our new script properties and methods. (Image Credit: Jeff Hicks)
Our new script properties and methods. (Image Credit: Jeff Hicks)

I can use this object to get some useful management information from the local computer.

Using the uptime property to gather meaningful information. (Image Credit: Jeff Hicks)
Using the uptime property to gather meaningful information. (Image Credit: Jeff Hicks)

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.

$computername = "chi-test01"

Next, I’ll outline a few standard properties.

$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.

$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.

$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.

$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.

$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.

$managed.Reboot()
Using our refresh method in Windows PowerShell. (Image Credit: Jeff Hicks)
Using our refresh method in Windows PowerShell. (Image Credit: Jeff Hicks)

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.

$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.

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.

Related Topics:

BECOME A PETRI MEMBER:

Don't have a login but want to join the conversation? Sign up for a Petri Account

Register
Comments (0)

Leave a Reply

Live Webinar: Active Directory Security: What Needs Immediate Priority!Live on Tuesday, October 12th at 1 PM ET

Attacks on Active Directory are at an all-time high. Companies that are not taking heed are being punished, both monetarily and with loss of production.

In this webinar, you will learn:

  • How to prioritize vulnerability management
  • What attackers are leveraging to breach organizations
  • Where Active Directory security needs immediate attention
  • Overall strategy to secure your environment and keep it secured

Sponsored by: