Create Better Lists with PowerShell

If you are like the majority of PowerShell admins, you often use lists in your daily work. The typical use case is a list of computer names that you incorporate into some PowerShell command or script. Given that, I thought I would share some tips and techniques for creating lists and how to best utilize them in your work. The list, by the way, doesn’t mean something stored in a text file. You can just as easily define a variable for a bunch of computer names.

​
But I'm going to assume you have more persistent needs. In fact, you might even have a computer list file like this.
A computer list with problems (Image Credit: Jeff Hicks)
A computer list with problems (Image Credit: Jeff Hicks)
Hopefully your list isn't as badly formed, but I have a reason for that madness. But typically your list should be a column list, one name per line. What most admins will do is import the list into a variable.
​
In my example, this creates nine entries.
Getting a count of computer names (Image Credit: Jeff Hicks)
Getting a count of computer names (Image Credit: Jeff Hicks)
Clearly that is incorrect because I have blank lines. If I were to try and use this collection of names, I would get errors. Depending on how you built your file in the first place, you might have a blank line at the end, which is hard to detect in Notepad. The other issue might be extra leading and trailing spaces.
Extra spaces are bad (Image Credit: Jeff Hicks)
Extra spaces are bad (Image Credit: Jeff Hicks)
Even though WIN81-ENT-01 is a valid name, the extra spaces are treated as part of the name. They need to be trimmed.
Trimmed results work better (Image Credit: Jeff Hicks)
Trimmed results work better (Image Credit: Jeff Hicks)
To avoid these problems, clean up the computer names when you bring them into your variable.
​
This expression is filtering out any line that doesn't contain a word character and then trimming leading and trailing spaces from each result. Now my variable of names is accurate and clean.
Creating a clean list (Image Credit: Jeff Hicks)
Creating a clean list (Image Credit: Jeff Hicks)
I don't know if all of these computer names are still valid, but that is an issue I'll address later. Another option is to build a list of computer names from a CSV file. If you have an Excel workbook, don't try to mess with the COM interface to walk through the worksheet. Save the file or worksheet as a CSV file. I have a sample CSV file I want to use.
My sample CSV file (Image Credit: Jeff Hicks)
My sample CSV file (Image Credit: Jeff Hicks)
Importing the CSV file is straightforward.
​
But this is when you need to start thinking about how your list is going to be used. Right now, $computers is a collection of objects.
Imported objects (Image Credit: Jeff Hicks)
Imported objects (Image Credit: Jeff Hicks)
The property names are the same as the column names in the CSV file. Your names might vary, although the fact that the property that reflects the server name is called Computername is fortunate. Here's why. Let's say I intend to use Get-Service to check the status of a service on all of the computers in the list. The cmdlet has a Computername parameter.
Checking a parameter detail (Image Credit: Jeff Hicks)
Checking a parameter detail (Image Credit: Jeff Hicks)
As you can see the parameter accepts pipeline input by property name. This means that if I pipe an object to Get-Service, and the object has a property called Computername, PowerShell will take the value and pass it to the –Computername parameter. This makes it very easy to run a command like this:
Piping a list of objects (Image Credit: Jeff Hicks)
Piping a list of objects (Image Credit: Jeff Hicks)
The variable $Computers is an array, and I am using the index number [ ] to get a subset of objects. In this case, I am getting items starting with index number 0 through 3. The '..' is the range operator. The computername property of each object was hooked up to the corresponding parameter in Get-Service and then magic happens. There was no need to parse out names or jump through hoops. But this won't always be so easy.
Pipeline failure (Image Credit: Jeff Hicks)
Pipeline failure (Image Credit: Jeff Hicks)
Why did this fail? Get-WmiObject also has a computername parameter. But this is why you need to be in the habit of reading help.
Parameter detail for Get-WmiObject (Image Credit: Jeff Hicks)
Parameter detail for Get-WmiObject (Image Credit: Jeff Hicks)
In this particular cmdlet, -Computername doesn't take any pipeline input. If you want to use the parameter you have explicitly define it. In my situation, this means I will need to use a ForEach-Object loop to process each object one at a time.
Processing objects one at a time (Image Credit: Jeff Hicks)
Processing objects one at a time (Image Credit: Jeff Hicks)
By the way, if my CSV column heading was something other than Computername, I would have had to use this same technique with Get-Service. In my next article, I'll show you a workaround and explore what else we can do to create effective lists.