Expert Solution for 2011 Scripting Games Beginner Event 5: Use PowerShell Objects to Gather Basic Computer Information


Summary: Microsoft PowerShell MVP Jeffery Hicks solves 2011 Scripting Games Beginner Event 5, and returns objects with desktop configuration information.

Microsoft Scripting Guy, Ed Wilson, here. Today we have Jeffery Hicks as our expert commentator for Beginner Event 5.


Jeffery Hicks is a Microsoft MVP in Windows PowerShell and an IT veteran with almost 20 years of experience. Much of his time has been spent as an IT consultant specializing in Microsoft server technologies. He works today as an independent author, trainer, and consultant. Jeff also writes the popular Prof. PowerShell column for His latest book is Managing Active Directory with Windows PowerShell 2.0: TFM 2nd Ed. (SAPIEN Press 2011).
Jeff’s contact information:
Blog: The Lonely Administrator

Worked solution

In this event, you were asked to find computer and operating system information and save it to a text file. An advanced solution would most likely center on a reusable advanced function. But for this exercise, I’ll assume that you want more of a workflow approach. The script is a complete set of commands that you might run on a monthly basis. My solution should cover all of the essential elements, and it throws in a few extra goodies that I feel even as a beginner you should be striving to include.

Right off the bat, I hope you notice all the internal comments and use of spacing and indenting. This makes your script much easier to read and troubleshoot. You’ll also notice that I am not using any aliases and I am using full parameter names. It may take a bit longer to initially type, but there’s nothing cryptic to decipher.

When you start reading the script, you’ll notice that it accepts parameters.

Param (






This allows maximum flexibility, although I’ve hard coded in some default values. My solution will go through all the computers in the comptuers.txt file and save the results to ComputerReport.txt. Any computers that can’t be contacted will end up in the Failed.txt log file. The Append parameter is a switch. If you use the parameter, it has a value. It might look like this:

PS C:\> MyScript –file computers.txt –switch

I’m using the parameter to indicate if the results should be appended the log file.

My version of the script gets all computer names from the text file and saves them to a variable.

#retrieve computer names filtering out any blank lines

    $Computers=Get-Content -Path $file | Where {$_}

I pipe the file contents to Where-Object so that only lines that exist will be saved. This is a nifty trick for filtering out blank lines. The next special feature I’ve added is to ping the ComputerName first by using Test-Connection.

if (Test-Connection -ComputerName $Computer -Count 2 -Quiet)

Test-Connection has a Quiet parameter that suppresses the ping information and simply returns True or False. Any failures will result in writing the computer name to the error log.



            #computer is not pingable

            $Computer.ToUpper() | Add-Content -Path $ErrorLog


Otherwise, the script uses WMI to get the necessary information.



   #attempt to retrieve WMI information and if there is an error catch it

   $OperatingSystem=Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer -ErrorAction Stop

   $ComputerSystem=Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Computer -ErrorAction Stop

In my version I’m taking advantage of Try/Catch to handle any errors. For example, even though I might be able to ping the computer, I might not have the right permissions (my version doesn’t support alternate credentials), or there might be a WMI problem. If there is an exception, the code in the Catch script block is executed.



                Write-Warning “There was a problem retrieving information from $($Computer.ToUpper())”

                #write the exception message as a warning

                Write-Warning $_.Exception.Message

                #write the failed computername to a text file

                $computer.ToUpper() | Add-Content -Path $ErrorLog

            } #close Catch scriptblock

By the way, I hope you notice my use of Write-Host and Write-Warning. I use the former to display status messages and the latter to display more serious messages without having to throw a complete exception.

Assuming that I was able to get the WMI information, I use New-Object to create a custom object. The data came from two different WMI classes, so this is an easy way to synthesize a custom object. Using the Property parameter and a hash table makes this a pretty easy process and one that I use very frequently in my scripting.

if ($OperatingSystem -AND $ComputerSystem)


    #create a custom object using a property hash table

    #I’m including ServicePack information since that might come in handy

    $data+=New-Object -TypeName PSObject -Property @{









The Reported property will contain the value of the Get-Date expression. In my version, I add the custom object for each computer to a previously initialized array.

When all the computers have been processed, all that is left is to create the text file. But it only makes sense if information was returned.

#measure how many computers were queried and save the count property to a variable

  $count=($data | measure-object).Count

  Write-Host “Successfully queried $Count computers.” -ForegroundColor Cyan

  #write the WMI information to a log file if $data has anything in it

  if ($count -gt 0)


If there is data, I check to see if the Append parameter was used. If so, the data is piped to Out-File by using its Append parameter. Otherwise a new file is created. In both instances, I’m specifying the encoding to be ASCII.

#if -Append then add the data to the file

if ($Append)


   $data | Out-File -FilePath $LogFile -Encoding ASCII -Append




   #write the data to a new file

   $data | Out-File -FilePath $LogFile -Encoding ASCII



   Write-Host “See $LogFile for details and $ErrorLog for failed computers.” -ForegroundColor Cyan

Here’s an example of what you might see when you run my script.

Image of script output

The log file will have an entry like this for every computer:

Domain      : JDHIT

Commputer   : SERENITY

Reported    : 3/22/2011 3:03:22 PM

ServicePack : 0

User        : JDHIT\Jeff

Model       : Qosmio X505

OS          : Microsoft Windows 7 Ultimate

The error log file will be a list of computer names that I could troubleshoot, and when it is ready, I could use this file as my new source file.

Even though this is a beginner event, there are still a number of scripting best practices you should attempt to incorporate that I hope I’ve demonstrated in this solution.

Thank you, Jeffrey, for providing this solution to Beginner Event 5.

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


Comments are closed.