Powershell PC Info Script (WMI)

August 10th, 2010 by

This tool will find a lot of information on remote computers using Powershell’s Get-WmiObject cmdlet.

It can easily find:

  • PC Serial Number
  • PC Printer Info
  • Current User
  • OS Info
  • System Info
  • Add/Remove Program List
  • Process List
  • Service List
  • USB Devices
  • Uptime
  • Disk Space
  • Memory Info
  • Processor Info
  • Monitor Serial Numbers (registry)


Hopefully someone out there will find this useful.  If this won’t work for your needs – it can at least give you a guide to Get-WmiObject with Powershell.  I am planning on releasing a Get-WmiObject/wmic cheat sheet sometime soon.

[START CODE]

#########################################################
#           Powershell PC Info Script V1.0b             #
#              Coded By:Trenton Ivey(kno)               #
#########################################################

function Pause ($Message="Press any key to continue..."){
    ""
    Write-Host $Message
    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}

function GetCompName{
    $compname = Read-Host "Please enter a computer name or IP"
    CheckHost
}

function CheckHost{
    $ping = gwmi Win32_PingStatus -filter "Address='$compname'"
    if($ping.StatusCode -eq 0){$pcip=$ping.ProtocolAddress; GetMenu}
    else{Pause "Host $compname down...Press any key to continue"; GetCompName}
}

function GetMenu {
    Clear-Host
    "  /----------------------\"
    "  |     PC INFO TOOL     |"
    "  \----------------------/"
    "  $compname ($pcip)"
    ""
    ""
    "1) PC Serial Number"
    "2) PC Printer Info"
    "3) Current User"
    "4) OS Info"
    "5) System Info"
    "6) Add/Remove Program List"
    "7) Process List"
    "8) Service List"
    "9) USB Devices"
    "10) Uptime"
    "11) Disk Space"
    "12) Memory Info"
    "13) Processor Info"
    "14) Monitor Serial Numbers"
    ""
    "C) Change Computer Name"
    "X) Exit The program"
    ""
    $MenuSelection = Read-Host "Enter Selection"
    GetInfo
}

function GetInfo{
    Clear-Host
    switch ($MenuSelection){
        1 { #PC Serial Number
            gwmi -computer $compname Win32_BIOS | Select-Object SerialNumber | Format-List
            Pause
            CheckHost
          }

        2 { #PC Printer Information
            gwmi -computer $compname Win32_Printer | Select-Object DeviceID,DriverName, PortName | Format-List
            Pause
            CheckHost
          }

        3 { #Current User
            gwmi -computer $compname Win32_ComputerSystem | Format-Table @{Expression={$_.Username};Label="Current User"}
            ""
            #May take a very long time if on a domain with many users
            #"All Users"
            #"------------"
            #gwmi -computer $compname Win32_UserAccount | foreach{$_.Caption}
            Pause
            CheckHost
          }

        4 { #OS Info
            gwmi -computer $compname Win32_OperatingSystem | Format-List @{Expression={$_.Caption};Label="OS Name"},SerialNumber,OSArchitecture
            Pause
            CheckHost
          }

        5 { #System Info
            gwmi -computer $compname Win32_ComputerSystem | Format-List Name,Domain,Manufacturer,Model,SystemType
            Pause
            CheckHost
          }        

        6 { #Add/Remove Program List
            gwmi -computer $compname Win32_Product | Sort-Object Name | Format-Table Name,Vendor,Version
            Pause
            CheckHost
          }

        7 { #Process Listx

            gwmi -computer $compname Win32_Process | Select-Object Caption,Handle | Sort-Object Caption | Format-Table
            Pause
            CheckHost
          }

        8 { #Service List
            gwmi -computer $compname Win32_Service | Select-Object Name,State,Status,StartMode,ProcessID, ExitCode | Sort-Object Name | Format-Table
            Pause
            CheckHost
          }

        9 { #USB Devices
            gwmi -computer $compname Win32_USBControllerDevice | %{[wmi]($_.Dependent)} | Select-Object Caption, Manufacturer, DeviceID | Format-List
            Pause
            CheckHost
          }

        10 { #Uptime
            $wmi = gwmi -computer $compname Win32_OperatingSystem
            $localdatetime = $wmi.ConvertToDateTime($wmi.LocalDateTime)
            $lastbootuptime = $wmi.ConvertToDateTime($wmi.LastBootUpTime)

            "Current Time:      $localdatetime"
            "Last Boot Up Time: $lastbootuptime"

            $uptime = $localdatetime - $lastbootuptime
            ""
            "Uptime: $uptime"
            Pause
            CheckHost
          }
        11 { #Disk Info
            $wmi = gwmi -computer $compname Win32_logicaldisk
            foreach($device in $wmi){
                    Write-Host "Drive: " $device.name
                    Write-Host -NoNewLine "Size: "; "{0:N2}" -f ($device.Size/1Gb) + " Gb"
                    Write-Host -NoNewLine "FreeSpace: "; "{0:N2}" -f ($device.FreeSpace/1Gb) + " Gb"
                    ""
             }
            Pause
            CheckHost
          }
        12 { #Memory Info
            $wmi = gwmi -computer $compname Win32_PhysicalMemory
            foreach($device in $wmi){
                Write-Host "Bank Label:     " $device.BankLabel
                Write-Host "Capacity:       " ($device.Capacity/1MB) "Mb"
                Write-Host "Data Width:     " $device.DataWidth
                Write-Host "Device Locator: " $device.DeviceLocator
                ""
            }
            Pause
            CheckHost
          }
        13 { #Processor Info
            gwmi -computer $compname Win32_Processor | Format-List Caption,Name,Manufacturer,ProcessorId,NumberOfCores,AddressWidth
            Pause
            CheckHost
          }
        14 { #Monitor Info

            #Turn off Error Messages
            $ErrorActionPreference_Backup = $ErrorActionPreference
            $ErrorActionPreference = "SilentlyContinue"

            $keytype=[Microsoft.Win32.RegistryHive]::LocalMachine
            if($reg=[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$compname)){
                #Create Table To Hold Info
                $montable = New-Object system.Data.DataTable "Monitor Info"
                #Create Columns for Table
                $moncol1 = New-Object system.Data.DataColumn Name,([string])
                $moncol2 = New-Object system.Data.DataColumn Serial,([string])
                $moncol3 = New-Object system.Data.DataColumn Ascii,([string])
                #Add Columns to Table
                $montable.columns.add($moncol1)
                $montable.columns.add($moncol2)
                $montable.columns.add($moncol3)

                $regKey= $reg.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\DISPLAY" )
                $HID = $regkey.GetSubKeyNames()
                foreach($HID_KEY_NAME in $HID){
                    $regKey= $reg.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\$HID_KEY_NAME" )
                    $DID = $regkey.GetSubKeyNames()
                    foreach($DID_KEY_NAME in $DID){
                        $regKey= $reg.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\$HID_KEY_NAME\\$DID_KEY_NAME\\Device Parameters" )
                        $EDID = $regKey.GetValue("EDID")
                        foreach($int in $EDID){
                            $EDID_String = $EDID_String+([char]$int)
                        }
                        #Create new row in table
                        $monrow=$montable.NewRow()

                        #MonitorName
                        $checkstring = [char]0x00 + [char]0x00 + [char]0x00 + [char]0xFC + [char]0x00
                        $matchfound = $EDID_String -match "$checkstring([\w ]+)"
                        if($matchfound){$monrow.Name = [string]$matches[1]} else {$monrow.Name = '-'}

                        #Serial Number
                        $checkstring = [char]0x00 + [char]0x00 + [char]0x00 + [char]0xFF + [char]0x00
                        $matchfound =  $EDID_String -match "$checkstring(\S+)"
                        if($matchfound){$monrow.Serial = [string]$matches[1]} else {$monrow.Serial = '-'}

                        #AsciiString
                        $checkstring = [char]0x00 + [char]0x00 + [char]0x00 + [char]0xFE + [char]0x00
                        $matchfound = $EDID_String -match "$checkstring([\w ]+)"
                        if($matchfound){$monrow.Ascii = [string]$matches[1]} else {$monrow.Ascii = '-'}         

                        $EDID_String = ''

                        $montable.Rows.Add($monrow)
                    }
                }
                $montable | select-object  -unique Serial,Name,Ascii | Where-Object {$_.Serial -ne "-"} | Format-Table
            } else {
                Write-Host "Access Denied - Check Permissions"
            }
            $ErrorActionPreference = $ErrorActionPreference_Backup #Reset Error Messages
            Pause
            CheckHost
          }
        1337 { Write-Host "Program Made By Trenton Ivey (Trenton@hackyeah.com)";Pause; CheckHost}
        c {Clear-Host;$compname="";GetCompName}
        x {Clear-Host; exit}
        default{CheckHost}
      }
}

#---------Start Main--------------
$compname = $args[0]
if($compname){CheckHost}
else{GetCompName}

[END CODE]
  1. Chris says:

    Hi there great script.

    I have two queries:

    1) When i run the printer info it doesnt show me the networked printer on the users machine.

    2) I wish to use this for our service desk users so that they can remote to peoples machines…How do i alter it so hat it asks for a username and password? Also would like the password not to be shown.

    Many thanks

    • Trenton says:

      Chris,

      1) This will only show locally installed printers. If however, the network printer was installed using a tcp/ip port (instead of a network share), it will show up.

      2)That is great that you are going to use this for your service desk! Let me know how it works. To get it to work with username/passwords (in case your techs are not local admins on the pc’s) You can have it prompt for a password, and then send it with the get-wmiobject. To do so, you will first need to prompt for a username and password. I think the best way to do this is to change the main area to something like:

      $compname = $args[0]
      $cred = Get-Credential
      if($compname){CheckHost}
      else{GetCompName}

      And then for each get-wmiobject (gwmi) user the -credential flag. So for the serialnumber it would look like:

      gwmi -computer $compname Win32_BIOS -Credential $cred | Select-Object SerialNumber | Format-List

      Hope that helps….let me know how it goes.

      (P.S. – The monitor serial number uses the registry instead of wmi, and that may take some more tweaking to get it to work with authentication)

  2. Mike says:

    Excellent script.

    One question. Is there a way to get just the serial numbers of the installed monitor(s)? Some of our systems have had 3 or 4 monitors over their lifetime and it would be nice to get just the currently used monitor info. Or if the systems are imaged it contains the monitor from the original base system.

  3. Trenton says:

    @Mike – I have found no easy way to keep track of the current monitors. For desktops that are running windows Vista/7 I believe that there is now a WMI object you can query to get monitor serial numbers. For XP however, the only place I have been able to get this information is in the registry. It is possible to sort the registry data by date – and then just assume the current monitor is the most recent one. Although, this is not always the case.

    Check out http://www.nirsoft.net/utils/monitor_info_view.html . This tool pulls a lot of monitor information from a PC. It is just an extended version of my powershell script (as an exe), but it is dedicated just to monitors.

  4. Mike says:

    Thanks Trenton. I was hoping there might be a way of combining the Get-WMIObject class win32_DesktopMonitor with what you’re pulling from the registry.

  5. Matt says:

    I’m an idiot, so forgive me. This is what I’m looking for at work but I’m not a code writer at all. Could you please tell me how I use this and what type of script this is?

    Thank you.

  6. Rasson says:

    Hi there im a noob when it comes to scripting and i like this code but not sure how to set it up. What would be the best way to use this ?

  7. I do like things nice and easy. I found something that is just like that Easy Button that they advertise on TV for Staples. This technology was secretly “copied” from one of the top internet enterprises. The fact is, that this software is 100% legal, “white hat” and ethical, that even giant enterprises use it. And the best part – it is really running on full autopilot. This super affiliate push button software is the real thing, so if you’re planning to use it unethically, or use it for scam purposes, this software isn’t for you! If you can spend no more than 3 minutes to download and setup this software, and then click the ‘Start Button’ just once to start this autopilot push button software… Then you can make money online. This never seen before push button software proved that the best and most profitable traffic on the internet is free traffic. You might be tempted to try to disect this software in order to ‘see the magic’ but why bother? All you really need to know is that you can download it (if the link hasn’t been taken down yet) and then push a button and watch the magic. Try it out -> http://adf.ly/1TyCy

  8. Larry Arndorfer says:

    Trenton,

    JAmes and I have made a couple changes to the Monitor section of your script. We exported a list of Laptops out od AD to run in the script. We also only wanted the monitor that are currenty connected. We think that the ones whit a control key are the monitor currentl connected. Let us know what you think.

    Thanks
    Larry

    # ***********************************************
    # * FindMonitor FindMonitorSN.PS1 *
    # * Find Monitor Serial Number *
    # * Creaters: Larry Arndorfer & James Hunt *
    # * Revisions: 2011-05-23 Created *
    # ***********************************************

    Clear-Host

    function Pause ($Message=”Press any key to continue…”){
    “”
    Write-Host $Message
    $null = $Host.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”)
    }

    function GetCompName{
    $list = Import-Csv “C:\AD_Laptops.csv” -Header “Laptops”

    foreach($compname in $list)
    {
    $compname = $($compname.Laptops)
    CheckHost
    }
    }

    function CheckHost{
    $ping = gwmi Win32_PingStatus -filter “Address=’$compname’”
    if($ping.StatusCode -eq 0){$pcip=$ping.ProtocolAddress; GetInfo}
    else{“$compname down”}
    }

    function GetInfo{

    # ********* Monitor Info ************

    #Turn off Error Messages
    $ErrorActionPreference_Backup = $ErrorActionPreference
    $ErrorActionPreference = “SilentlyContinue”

    $keytype=[Microsoft.Win32.RegistryHive]::LocalMachine
    if($reg=[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$compname)){
    #Create Table To Hold Info
    $montable = New-Object system.Data.DataTable “Monitor Info”
    #Create Columns for Table
    $moncol1 = New-Object system.Data.DataColumn Model,([string])
    $moncol2 = New-Object system.Data.DataColumn Serial,([string])
    $moncol3 = New-Object system.Data.DataColumn Ascii,([string])
    $moncol4 = New-Object system.Data.DataColumn Computer,([string])
    #Add Columns to Table
    $montable.columns.add($moncol1)
    $montable.columns.add($moncol2)
    $montable.columns.add($moncol3)
    $montable.columns.add($moncol4)

    $regKey= $reg.OpenSubKey(“SYSTEM\\CurrentControlSet\\Enum\DISPLAY” )
    $HID = $regkey.GetSubKeyNames()
    foreach($HID_KEY_NAME in $HID){
    $regKey= $reg.OpenSubKey(“SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\$HID_KEY_NAME” )
    $DID1 = $regkey.GetSubKeyNames()
    foreach($DID_KEY_NAME in $DID1){
    $CheckActive = “False”
    $regKey2=$reg.OpenSubKey(“SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\$HID_KEY_NAME\\$DID_KEY_NAME”)
    $DID2=$regKey2.GetSubKeyNames()
    foreach($DID2_KEY_NAME in $DID2){
    If($DID2_KEY_NAME -EQ “Control”){
    $regKey= $reg.OpenSubKey(“SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\$HID_KEY_NAME\\$DID_KEY_NAME\\Device Parameters” )
    $EDID = $regKey.GetValue(“EDID”)
    foreach($int in $EDID){
    $EDID_String = $EDID_String+([char]$int)
    }
    #Create new row in table
    $monrow=$montable.NewRow()

    #ComputerName
    $monrow.Computer = $compname

    #MonitorName
    $checkstring = [char]0×00 + [char]0×00 + [char]0×00 + [char]0xFC + [char]0×00
    $matchfound = $EDID_String -match “$checkstring([\w ]+)”
    if($matchfound){$monrow.Model = [string]$matches[1]} else {$monrow.Model = ‘-’}

    #Serial Number
    $checkstring = [char]0×00 + [char]0×00 + [char]0×00 + [char]0xFF + [char]0×00
    $matchfound = $EDID_String -match “$checkstring(\S+)”
    if($matchfound){$monrow.Serial = [string]$matches[1]} else {$monrow.Serial = ‘-’}

    #AsciiString
    $checkstring = [char]0×00 + [char]0×00 + [char]0×00 + [char]0xFE + [char]0×00
    $matchfound = $EDID_String -match “$checkstring([\w ]+)”
    if($matchfound){$monrow.Ascii = [string]$matches[1]} else {$monrow.Ascii = ‘-’}

    $EDID_String = ”

    $montable.Rows.Add($monrow)
    }
    }
    }
    }
    $montable | select-object -unique Computer,Serial,Model,Ascii | Where-Object {$_.Serial -ne “-”} | Format-Table
    } else {
    Write-Host “Access Denied – Check Permissions”
    }
    $ErrorActionPreference = $ErrorActionPreference_Backup #Reset Error Messages
    #Pause
    #CheckHost
    }

    #———Start Main————–
    $compname = $args[0]
    if($compname){CheckHost}
    else{GetCompName}

Leave a Reply