Recently, I was wondering how much code I would need to do basic hardware and software inventory on several remote systems. After experimenting a little bit I came up with the following line of code:

Get-Content pcs.txt | foreach { Write-Host $_ -f Green; $pc=$_; Get-Content wmi.txt | foreach { Get-WmiObject $_ -ComputerName $pc } }

That’s right! Just one line of code. 🙂

I’m reading the computers from a text file (pcs.txt). Then I use a foreach-clause to iterate through the list of pc’s. Write the name of the PC on the screen in green to easily identify which system we’re processing. Then I’m reading the different elements to report on from another text file (wmi.txt). For the current system in the loop I’m running a Get-WmiObject on all the items from the second text file and write that on the screen also.

I have to store the name of the current PC in a variable with the command $pc=$_ because I’m entering a nested loop. Whithin the nested loop $_ get’s filled with the current WMI-class, instead of the current PC. I can still refer to the name of the PC through the $pc variable.

Here are both textfiles. They’re just examples, feel free to supply your own items.
wmi.txt:
Win32_Bios
Win32_LogicalDisk
Win32_OperatingSystem
Win32_Product

 

pcs.txt:

server1
server2

Here’s the same line of code but the using the shortest possible notation:

gc p|%{Write-Host $_ -f Green;$p=$_;gc w|%{gwmi $_ -Co $p}}

Sixty characters! I’m really pushing my luck here doing nasty things like abbreveating parameters (-Co instead of -Computername), using all sorts of aliases (gc for Get-Content, % for ForEach, and gwmi for Get-WmiObject) and using textfiles with a name of just one letter. But hey, for the purpose of writing the shortest line of code, it will do! 😉

Let’s get serious again. PowerShell chooses a different layout than you would expect. To compensate, just use Out-Default.

Get-Content pcs.txt | foreach { Write-Host $_ -f Green; $pc=$_; Get-Content wmi.txt | foreach { Get-WmiObject $_ -ComputerName $pc | Out-Default } }

With Out-Default you can’t write to a text file anymore. Instead of Out-Default, consider using Out-File to create a report.

Get-Content pcs.txt | foreach { "===== Computer $_ ====="; $pc=$_; Get-Content wmi.txt | foreach { Get-WmiObject $_ -ComputerName $pc } } | Out-File report.txt
 Invoke-Item .\report.txt

When you want to use computers from Active Directory the script becomes a little bit different. Be carefull when running this command in a production environment! Escpecially when it’s large!

Get-ADComputer -filter * | foreach { $pc=$_.dnshostname; Write-Host $pc -f Green; Get-Content wmi.txt | foreach { Get-WmiObject $_ -ComputerName $pc } }

Don’t forget to import the ActiveDirectory module if you’re still running PowerShell 2. PowerShell 3 loads this module automatically for you if it’s installed. Check wheter the AD-module is installed with this command:

Import-Module ServerManager; Get-WindowsFeature RSAT-AD-PowerShell

If you don’t want to use any textfiles at all then use this peace of code:

$wmi = "Win32_Bios", "Win32_LogicalDisk", "Win32_OperatingSystem"
Get-ADComputer -filter * | foreach { $pc=$_.dnshostname; Write-Host $pc -f Green; $wmi | foreach { Get-WmiObject $_ -ComputerName $pc } }

Using the new outputmode of Out-GridView in PowerShell 3 we can list the computers graphically, select several of them, and after the press of the OK button only the selected systems are processed.

Get-ADComputer -filter * | Out-GridView -OutputMode Multiple | foreach { Write-Host $_ -f Green; $pc =$_; Get-Content wmi.txt | foreach { Get-WmiObject $_ -ComputerName $pc } }

And here’s an example script file:

# create a collection of interesting WMI classes
$wmi = "Win32_Bios", "Win32_LogicalDisk", "Win32_OperatingSystem"
# get computers from AD, feel free to change the filter
Get-ADComputer -filter * |   foreach {
  # store the dnshostname for reference in the next loop
  $pc=$_.dnshostname

  Write-Host $pc -ForegroundColor Green

  # send the collection of WMI-classes into the pipe
  $wmi |       foreach {
    # run Get-WmiObject on the computer currently stored in $pc
    Get-WmiObject $_ -ComputerName $pc
  }
}

There are a lot of other interesting WMI-sources. Consider these for your WMI-selection:

Win32_Account
Win32_Battery
Win32_Bios
Win32_BootConfiguration
Win32_ComputerSystem
Win32_DiskPartition
Win32_Environment
Win32_LogicalDisk
Win32_NetworkAdapter
Win32_OperatingSystem
Win32_Printer
Win32_Processor
Win32_Product
Win32_ScheduledJob
Win32_Service
Win32_Share
Win32_TimeZone

Please send me a message if you have any questions.

Good luck!

Dimitri

 

Leave a Reply