Create Custom Objects in Your PowerShell Script

Summary: Learn how to create custom objects in your Windows PowerShell script to maximize utility and reusability of your script.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have Steven Murawski as our guest blogger. Steven will tell us a little about himself then go on to talk about objects.

Photo of Steven Murawski

I’m a senior Windows system engineer for Edgenet. In this role, I support a dynamic infrastructure that pushes the boundaries of the Windows platform. Windows PowerShell allows me to support this infrastructure in a more consistent and efficient manner. I’m an advocate for Windows PowerShell because I believe it encourages administrative best practices, and it allows developers to provide additional access to their applications, without needing to explicitly write code for each administrative feature. Part of my advocacy for Windows PowerShell includes my blog, appearances on various podcasts, and involvement with local user groups (Greater Milwaukee Script Club, and the Greater Milwaukee IT Pro User Community). I am also a cohost of Mind of Root (a weekly audio podcast about systems administration, tech news, and topics). We stream our show live on Sunday evenings at 7:30 PM CST.

Steven’s contact information:
Blog: Use PowerShell: The Shell Is Calling
Greater Milwaukee Script Club
Greater Milwaukee IT Pro User Community
Mind of Root on UStream

It’s All About the Objects

I had the honor of serving as one of the judges for the 2011 Scripting Games. Having the opportunity to read so many scripts and watch the intense involvement that the competitors displayed was truly a treat. I saw some very interesting solutions to problems, and I want to thank everyone who contributed a script for any event.

The 2011 Scripting Games provided an opportunity to showcase several themes that make Windows PowerShell a unique automation framework and scripting language. In my opinion, one of those key themes is the use of objects. Windows PowerShell is an object-based environment. Before you run screaming off into the woods, if you’ve dealt with WMI, VBScript, or automated Microsoft Office at all, you are already familiar with working with objects. Objects represent a logical grouping of data, and they provide a way for us as scripters to more easily find the information we are looking for. All of those previous technologies (and many other areas of the Microsoft ecosystem) express their structure as objects. Getting comfortable with using objects is an important ability in the PowerShell world.

In Windows PowerShell, everything is represented by an object (yes, everything, including text). Being designed to work with objects provides Windows PowerShell a great advantage in its pipeline. Objects can contain data called properties. Those properties can be used to provide input to the next command. This is a key strength that allows you, the scripter, to allow your scripts or functions to become the input for other commands, perhaps enabling scenarios that you never imagined.

Here is where I put on my infomercial salesman hat…

But wait, there’s more! For the same price of embracing an object-based shell and designing your output to be objects, we’ll include a great number of cmdlets that provide support for formatting, converting, and exporting the objects emitted from your scripts. Now how much would you expect to pay?

When your scripts and functions are designed to output objects, the formatting and export commands in Windows PowerShell are instantly available to work with the output of your script. Need to export your data as a CSV file? That is covered by Export-CSV or ConvertTo-CSV (if you are not ready to put your output in a file). How about turning the results into HTML or XML? ConvertTo-HTML and ConvertTo-XML have you covered. I can go on and on, but I will leave you with a quick command so that you can see some of the options you have:

Get-Command –verb Format, Out, Export, ConvertTo

Because these output and formatting options exist, you can stop worrying about the format of and export of the results of your function and concentrate on the functionality you want to provide. Let’s run through an example. This example is based on a task my boss asked me to do in preparation for moving a data center.

I need to create a script to gather network information about the servers in my environment in preparation for a data center move and network redesign. I would like to know the physical interface, IP address assigned, subnet mask, default gateway, DNS servers, and domain suffix. I only care about adapters that are enabled and have IP address information.

I need to get this information from several hundred servers of varying operating system versions and in different domains, so I’ve decided to use WMI as my tool to gather the network stack information. The first version of this script manually creates a report and writes it to the console, as shown here.

Function Get-NetworkConfiguration


    param (





        [Alias(‘__ServerName’, ‘Server’, ‘Computer’, ‘Name’)]   


        $ComputerName = $env:COMPUTERNAME,







        $WMIParameters = @{

            Class = ‘Win32_NetworkAdapterConfiguration’

            Filter = “IPEnabled = ‘true'”

            ComputerName = $ComputerName



        if ($Credential -ne $Null)


            $WmiParameters.Credential = $Credential


        foreach ($adapter in (Get-WmiObject @WMIParameters))


            $OFS = ‘, ‘

            Write-Host “Server: $($adapter.DNSHostName)”

            Write-Host “Adapter: $($adapter.Description)”

            Write-Host “IP Address: $($adapter.IpAddress)”

            Write-Host “Subnet Mask: $($adapter.IPSubnet)”

            Write-Host “Default Gateway: $($adapter.DefaultIPGateway)”

            Write-Host “DNS Servers: $($adapter.DNSServerSearchOrder)”

            Write-Host “DNS Domain: $($adapter.DNSDomain)”






Here is the script output:

Image of command output

Not too shabby for a quick script, if I don’t say so myself. The script will run through and give me the information I need and display it to the console; however, that would be the end of its utility.

How can I make this more useful? Changing Write-Host to Write-Output would allow me to redirect the output to a file or to use a text parsing tool to manipulate the results, but that is still too limited.

Let’s jazz this script up a bit by making one critical change. Instead of the Write-Host or Write-Output commands with some text, we are going to change this to emit a custom object. We’ve already done most of the work. The New-Object cmdlet offers a way to turn a hash table into the properties of a custom object.

$My SampleProperties = @{name=’Steve’;title=’Guest Blogger’}

New-Object PSObject –Property $MySampleProperties

Here is the output:

Image of command output

We’ll use this same technique and swap out the Write-Host statements in the Foreach loop and create a hash table with the same properties that we wanted in the text report, and then we can create a custom object with those properties. The Foreach loop will then look like this:

foreach ($adapter in (Get-WmiObject @WMIParameters))


            $AdapterProperties = @{

                Server = $adapter.DNSHostName

                Adapter =  $adapter.Description

                IPAddress = $adapter.IpAddress

                SubnetMask = $adapter.IPSubnet

                DefaultGateway = $adapter.DefaultIPGateway

                DNSServers = $adapter.DNSServerSearchOrder

                DNSDomain = $adapter.DNSDomain



            New-Object PSObject -Property $AdapterProperties


The output looks like this:

Image of command output

The output looks pretty similar, but now there are some key differences. Windows PowerShell also offers a variety of formatting resources, so I can turn my output into a customized table (or list) as follows:

Get-NetworkConfiguration ‘Server1’, ‘Server2’, ‘Server3’ | Format-Table Server, Adapter, SubnetMask, DefaultGateway –auto –wrap

As an object, I can work with these various properties in other ways as well. For example, if I had a DNS server go bad (this happened just the other week to me), I can run this against all the computers in a certain site and find which machines have that DNS setting:

Get-ADComputer –filter * | Get-NetworkConfiguration | Where-Object {$_.DNSServers –contains $IPofMyTroublesomeDNSServer}

Or if you would like to get a count of how many machines are using different default gateways, you could do something like this:

Get-ADComputer -filter * | Get-NetworkConfiguration | Group-Object DefaultGateway -NoElement

This is shaping up to become a great auditing tool, in addition to solving my initial reporting problem. The final script is available in the Technet ScriptCenter Repository.

When you begin to output options from your functions, the reusability and extensibility options soar. Objects allow you to take advantage of the pipeline (which allows your objects to be the input to other commands), allow your commands to use incoming objects (via the Parameter attribute and ValueFromPipelineByPropertyName switch), and most importantly, allow you to leverage the formatting and output system that Windows PowerShell provides, which keeps you from having to design your own output options and saves your effort for the real work—getting your job done!

Thank you, Steven, for writing this explanation of working with objects in Windows PowerShell. Join us tomorrow, as Andy Schneider is the guest blogger.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy