Winter Scripting Games (2013) Event 2

The Winter Scripting Games 2013 warmup is now closed but the Official

Bear in mind that:

The Official 2013 Scripting Games are now hosted by PowerShell.org, and will kick off at the PowerShell Summit North America 2013. Stay tuned! We will be posting more information in April 2013.

Source: http://powershell.org/games/

Someone asked on the Scripting Games forums:

It appears that I’ve saved it in the following image:

as well as a text version:

    Covering Your Assets (Open Until Tuesday, February 12, 2013)

    Your organization is preparing to renew maintenance contracts on all of your server computers.
    You need to provide management with a report that details each server’s computer name, manufacturer,
    model, number of logical processors, and installed physical memory.
    Most of the servers do not have Windows PowerShell installed.
    None of the servers a separated from your client computer by a firewall.
    The server computer names are provided to you in a file named C:\Servers.txt, which contains one computer name per line.

    Minimum Requirements

    Optional Criteria
    Suppress error messages if a computer cannot be contacted

    Desired Output
    ComputerName Model Manufacturer LogicalProcs PhysicalRAM
    SERVER2 PowerEdge Dell 8 128 SERVER3 Proliant Compaq 2 4

Here the solution I submitted for this event:

$Cred = (Get-Credential)            
Get-content C:\Servers.txt | ForEach-Object -Process {            
    $Sys = $proc = $Mem = $WMIresult = $null            
    $WMIHT = @{            
        ErrorAction = 'Stop'             
        ComputerName = $_            
        Credential = $Cred            
    }            
    try {            
        $Sys  = Get-WmiObject -Class Win32_ComputerSystem @WMIHT            
        $Proc = Get-WmiObject -Class Win32_Processor      @WMIHT            
        $Mem  = Get-WmiObject -Class Win32_PhysicalMemory @WMIHT            
        $WMIresult = $true            
    } catch {            
        # Silent fail            
    }            
    if ($WMIresult) {            
        New-Object -TypeName PSObject -Property @{            
            ComputerName = $Sys.Name            
            Manufacturer = $Sys.Manufacturer            
            Model = $Sys.Model            
            LogicalProcs = @($Proc).Count            
            PhysicalRAM = '{0:n2} GB ' -f ($Mem | % { $_.Capacity/1Gb } | Measure-Object -Sum).Sum            
        }            
    }            
} | Select-Object -Property ComputerName,Manufacturer,Model,LogicalProcs,PhysicalRAM |            
Format-Table  -AutoSize

I typed the following code on my non-domain joined Windows 8 computer and targeted a 2003 server, a Windows 2008 R2 and a Windows Server 2012.

I’ve got the following console output:

I first store my domain credentials in a variable named $cred.

The second step is to get the content of the servers.txt file. I didn’t specify the ReadCount argument of the Get-Content cmdlet as it’s set by default to 1 which means that lines are submitted one by one through the pipeline. This allows to create a loop on each server using the Foreach-Object cmdlet.

Then I choose to reset every variable I intend to use in the foreach loop.

Now, let’s talk about the event description details that will dictate how to communicate with these servers and how to gather the requested data from them.

As servers don’t even have Powershell installed locally and as they can be running any Windows operating system, WMI is the best way to go. In the event description, it’s said that we shouldn’t care about the firewall. In real life we do and WMI must be explicitely allowed in firewall rules.

The next step is to identify the WMI classes that have the requested properties. If you don’t know them, you should search it on the web as it’s the easiest approach. You can do it with Powershell but it won’t be very straight-forward. If you type the following key words in a browser, “WMI class get manufacturer model”, you can land for example on this technet page, Collecting Information About Computers, which is a good starting point.

If you’ve found the name of the WMI class Win32_OperatingSystem, you should check the complete MSDN documentation on this page as well as check its properties with Powershell. Usually, just listing properties like this should be enough…

gwmi Win32_OperatingSystem | fl *

…but, sometimes it may be also a good idea to look at the current schema of the class.
The most human readable version can be obtained with the following trick:

([wmiclass]"Win32_OperatingSystem").gettext([Management.TextFormat]::Mof)

You can read more on the subject on this Hey Scripting Guy blog post. If you’re looking for super combo tricks, you should have a look to Bartek Bielawski‘s favorites ones on this page.

Now that all the properties have been identified, the next step is to query WMI with the shortest code as possible. One way to achieve this is to use the splatting technique. Splatting consists in passing a predefined hashtable of parameters with their values to a cmdlet. A hashtable is defined by using the following notation @{}. If you’ve Powershell 3.0 and updated your help using this command:

Update-help -Force -UICulture $host.CurrentUICulture

…you can actually read the help about splatting written by Rohn Edwards, the winner of the Advanced Division of the 2012 Scripting Games 😀

Get-help about_Splatting

As the event description mentioned that we had to suppress error messages if a computer cannot be contacted , I could have used the -ErrorAction SilentlyContinue but I intentionally didn’t and still have a preference for the try/catch block.

Don Jones wrote about the Winter Scripting Games content and gave a highly valuable feedback about it where he also mentions how to use the -ErrorAction SilentlyContinue: http://powershell.org/wp/2013/02/11/winter-scripting-camp-the-post-mortem/

That’s it for today. Last word, enroll in the Scripting Games this year if you never did as it’s an excellent way of learning Powershell and have fun 😎

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s