The 2013 Scripting Games, Beginner Event #2

Question

Dr. Scripto finally has the budget to buy a few new virtualization host servers, but he needs to make some room in the data center to accommodate them. He thinks it makes sense to get rid of his lowest-powered old servers first… but he needs to figure out which ones those are.All of the virtualization hosts run Windows Server, but some of them don’t haveWindows PowerShell installed, and they’re all running different OS versions. Theo ldest OS version is Windows 2000 Server (he knows, and he’s embarrassed, but he’s just been so darn busy). The good news is that they all belong to the same domain, and that you can rely on having a Domain Admin account to work with. The good Doctor has asked you to write a PowerShell command or script that can show him each server’s name, installed version of Windows, amount of installed physical memory, and number of installed processors. For processors, he’ll be happy getting a count of cores, or sockets, or even both — whatever you can reliably provide across all these different versions of Windows. To help you out, he’s given you a text file, C:\IPList.txt, that contains one server IP address per line. If you can write this as a one-liner — awesome! If not, try to keep your answer is concise and compact as possible (although it’s perfectly okay to use full command and parameter names).

My Answer

Get-Content C:\IPList.txt | 
 Foreach-object {
  Get-WmiObject -Namespace root\CImv2 -Class Win32_ComputerSystem -ComputerName $_ | 
   Select-object Name, 
                 @{Label="OS";Expression={(Get-WmiObject -Namespace root\CImv2 -Class Win32_OperatingSystem).Caption}}, 
                 TotalPhysicalMemory, 
                 NumberOfProcessors, 
                 NumberOfLogicalProcessors
  } | 
   Format-Table -AutoSize

To make PS_2 compatible use __Servername instead of Name

My answer, but rounding up the size calculations

Using the format ( f{}) commands

Get-Content C:\IPList.txt | 
 Foreach-object {Get-WmiObject -Namespace root\CImv2 -Class Win32_ComputerSystem -ComputerName $_ | 
 Select-object Name, 
 @{Label="OS";Expression={(Get-WmiObject -Namespace root\CImv2 -Class Win32_OperatingSystem -ComputerName $_.Name).Caption}}, @{Label="Mem in GB";Expression={"{0:N0}" -f($_.TotalPhysicalMemory / 1GB)}}, 
 NumberOfProcessors, 
 NumberOfLogicalProcessors} | 
Format-Table –AutoSize

Using the .Net Math class

Get-Content C:\IPList.txt | 
 Foreach-object {Get-WmiObject -Namespace root\CImv2 -Class Win32_ComputerSystem -ComputerName $_ | 
 Select-object Name, 
 @{Label="OS";Expression={(Get-WmiObject -Namespace root\CImv2 -Class Win32_OperatingSystem -ComputerName $_.Name).Caption}}, @{Label="MEM in GB";expression={[System.Math]::Round(($_.TotalPhysicalMemory / 1GB),1)}}, 
 NumberOfProcessors, 
 NumberOfLogicalProcessors} | 
 Format-Table –AutoSize

Learning Points

Splatting (Boe Prox)

Use splatting if you plan to use the same info over and over again in a script, in fact it’s not a bad idea to do it all the time

  • Instead of
Send-MailMessage -To user@domain.com -From user1@domain.com -Subject Test -SMTPServer server@domain.com -Body "This is a test"
  • Do
$email = @{
 To = 'user@domain.com'
 From = 'user1@domain.com'
 Subject = 'Test'
 SMTPServer = 'server.domain.com'
}
Send-MailMessage @email

Stop using $ErrorActionPreference (Boe Prox)

This changes it for the entire script, use it as needed for each command using -ErrorAction

Using Passthru to combine different objects (taygibb‘s entry)

The PassThru parameter is one of the common parameters of most PowerShell cmdlets and returns an object when a cmdlet normally wouldn’t return an object. For example, The Copy-Item cmdlet will perform an action but not return any information on the copied object but when specifying the Passthru parameter you can return the copied object and perform further work on it. In TayGibbs script he uses this technique to add a new member to the management object returned from query the 1st set of required WMI information. Normally Add-Member wouldn’t return information to the console. But when using the Passthru cmdlet it will  return the new changed object

Get-WmiObject -Class "Win32_ComputerSystem" -ComputerName localhost | 
 Select-Object -Property Name,
                         TotalPhysicalMemory,
                         NumberOfLogicalProcessors,
                         NumberOfProcessors | 
                            Add-Member -Name "OS Version" -Value $(Get-WmiObject -Class Win32_OperatingSystem -ComputerName localhost | 
                                                                     Select-Object -ExpandProperty Caption) -MemberType NoteProperty -PassThru

Advanced Notes (Art Beane)

  • If your entry calls for array entry in the parameter then make sure to add it, e.g.
    • [string[]]$ComputerName
  • Match your parameter names to the properties of the expected item (e.g. ComputerName and not Server)
  • When working in V3 with CIM why not Try{WSMAN} Catch{DCOM}

Misc Advanced Notes

  • Uses #Requires -version X to show the version your script works with
  • Be careful with shorthand parameter declarations, for examle
    • This works in v2 and v3
      • [Parameter(Position=0,ValueFromPipeline=$True,Mandatory=$True)]
    • This only works in V3
      • [Parameter(Position=0,ValueFromPipeline,Mandatory)]

 

 

About mell9185

IT proffesional. Tech, video game, anime, and punk aficionado.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply