Monday, 21 September 2015

Next-Level Scripting - Using Export-CSV With Custom Objects

Welcome to the next post in my Next-Level Scripting series where I show you the PowerShell scripting techniques that take your scripts to the next level - a level defined by concise, well-written code that conforms to best practices and uses the built-in tools in PowerShell whenever possible to handle common scripting tasks.

Sometimes it’s Easy, Sometimes it Ain’t

One of the most common things you will need to do as a Next-Level scripter is collect information from various sources and then display that information on the screen and/or export it to a file.  As we’ll see, this is not very difficult to do when you’re just collecting information from one place using one cmdlet but when you’re getting information from multiple sources it becomes significantly more challenging.

Let’s look at the easy scenario first.  We just want a list of services whose name begins with “Hyper-V” as well as the state of the service and its name.  We can just stick with Get-Service and then export straight to CSV as shown below.

001
002

Get-Service | where {$_.DisplayName -like "Hyper-V*"} | select Name,Status,DisplayName `
| Export-Csv C:\Temp\Services.csv -NoTypeInformation

Now let’s imagine a different scenario where we want to do the following:

  1. Read list of usernames from a file
  2. Find the account corresponding to that name in Active Directory
  3. Get the profile path for the account
  4. Get the home drive path for the account
  5. Check if the roaming profile path exists on a file server
  6. Check if the home drive folder exists on a file server

Since we are pulling information from various sources, we can’t just export straight to CSV like we did in the first example.  Without knowing exactly what to do, this scenario can appear very daunting.  Armed with the right knowledge however, it becomes a cookie cutter approach that you can easily copy between scripts for widely varying purposes.

Custom Objects and Hashtables

In this example, we are going to be working with hashtables, arrays and custom objects.  Now if you don’t understand exactly what arrays, hashtables and custom objects are, don’t worry too much.  You can essentially copy the approach I’m going to show you and with a few basic modifications use it for just about any scenario where you want to collect and display information from multiple different sources.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021

$allResults = @()

foreach ($user in (Get-Content C:\Temp\Users.txt
))
{
   
$thisUserInfo =
 @{}
   
   
$thisUser = Get-ADUser $user -Properties ProfilePath,HomeDrive
  
   
$thisUserInfo.UserName = $thisUser.
SamAccountName
   
$thisUserInfo.RoamingProfilePath = $thisUser.
ProfilePath
   
$thisUserInfo.HomeDrivePath = $thisUser.
HomeDrive
   
$thisUserInfo.ProfileExists = Test-Path \\FileServer1\Profiles\$user
    $thisUserInfo.HomeDriveExists = Test-Path \\FileServer2\HomeDrives\$user
 
   
   
$object = New-Object PsObject -Property $thisUserInfo
   
   
$allResults += $object
}

$allResults
$allResults
 | Export-Csv C:\Temp\Results.csv -NoTypeInformation

Let’s look at the important lines in this script.

  • Line 1: Create an empty array which will hold the results for every user
  • Line 5: Create a hashtable which will hold the results for the current user we are processing.  It’s important to understand that this hashtable only holds the results for the current user and is recreated each time the script hits line 5
  • Lines 9 through 13:  Populate the hashtable with the various bits and pieces of information we are looking for.  The names you choose for these values will become the column headers in your results
  • Line 15: Create a custom object and populate it with the information from the hashtable
  • Line 17: Copy the newly created object into the allResults array

And you can see the results of your magnificent script at the end when you display the allResults array on the screen:

image

And then to cap it off, your concise and beautiful output is ready for export to a CSV file which we do on line 21.