My Solution: July 2015 PowerShell Scripting Games Puzzle
Last month, PowerShell.org announced that the PowerShell Scripting Games had been re-imagined as a monthly puzzle and the first puzzle was published.
The instructions stated to use a PowerShell one-liner that produces the following output. No more
than one semicolon should be used, do not use the ForEach-Object
cmdlet or one of its aliases. The
one-liner should be able to target more than one computer and feel free to go crazy with a really
short one-liner with aliases and whatever else.
1PSComputerName ServicePackMajorVersion Version BIOSSerial
Although the instructions state that one semicolon can be used, this does not mean that two PowerShell commands separated by a semicolon could be used because that wouldn't be a one-liner. A PowerShell one-liner is one continuous pipeline and not necessarily on one physical line.
Here's my solution with full cmdlet and parameter names so you'll be able to understand it easier. I don't recommend using aliases or positional parameters in any code that you're sharing even if it's a one-liner. The use of full cmdlet and parameter names makes your code much easier to follow and more self-documenting.
1Get-WmiObject -ComputerName $env:COMPUTERNAME -Class Win32_OperatingSystem -PipelineVariable OSInfo |
2Select-Object -Property PSComputerName, ServicePackMajorVersion, Version,
3@{label='BIOSSerial';expression={(Get-WmiObject -ComputerName $OSInfo.CSName -Class Win32_BIOS).serialnumber}}
My solution does require PowerShell version 4 or higher since I'm taking advantage of the
PipelineVariable
common parameter.
You may wonder why I'm using the older Get-WmiObject
cmdlet instead of the Get-CimInstance
cmdlet that was introduced in PowerShell version 3 since I'm using features that require PowerShell
version 4?
If you're using a client machine such as Windows 8.1 or Windows 10 with its default setting of not
having PowerShell remoting enabled, the Get-CimInstance
cmdlet will fail when the ComputerName
parameter is specified and the local computer is targeted:
This is because Get-CimInstance
uses the WSMAN protocol by default, although a CimSession could be
created specifying the DCOM protocol with the New-CimSessionOption
cmdlet or PowerShell remoting
could be enabled on the local computer.
You may also run into similar issues with remote machines when using the Get-WmiObject
cmdlet
which communicates via DCOM which may be blocked on your network or via the firewall on remote
machines.
My solution also works without issue against multiple computers and notice that although this command is on more than one physical line, it is indeed a PowerShell one-liner:
1Get-WmiObject -ComputerName $env:COMPUTERNAME, DC01, SQL04 -Class Win32_OperatingSystem -PipelineVariable OSInfo |
2Select-Object -Property PSComputerName, ServicePackMajorVersion, Version,
3@{label='BIOSSerial';expression={(Get-WmiObject -ComputerName $OSInfo.CSName -Class Win32_BIOS).serialnumber}}
I decided to take my solution one step further. What if no semicolons were allowed? I also saw
someone had posted that their computer didn't have a "BIOSSerial" property. No one's computer has
one. You simply create a hash table with Select-Object
or one of the Format
cmdlets and rename
an existing property. Here's my solution with no semicolons:
1Get-WmiObject -ComputerName $env:COMPUTERNAME, DC01, SQL04 -Class Win32_OperatingSystem -PipelineVariable OSInfo |
2Select-Object -Property PSComputerName, ServicePackMajorVersion, Version,
3@{
4 label='BIOSSerial'
5 expression={(Get-WmiObject -ComputerName $OSInfo.CSName -Class Win32_BIOS).serialnumber}
6}
I did carve up the command and use all of the aliases and shortcuts I could think of and I'll post it here and let you be the judge of whether or not this command or the previous one is easier to follow:
1gwmi Win32_OperatingSystem -cn. -pv c|ft PSC*,S*P*Ma*,V*,@{l='BIOSSerial';e={(gwmi Win32_BIOS -cn $c.CSName).serialnumber}}
There's nothing wrong with using shortcuts such as aliases and positional parameters when working in the console as long as the code isn't being saved or shared. It's also beneficial to know what the aliases are since you'll find others posting code that you'll need to decrypt.
µ