Assistance Please - Monitor Serial Numbers of Remote Machines ps script

This topic contains 6 replies, has 2 voices, and was last updated by  Don Jones 1 month ago.

  • Author
    Posts
  • #82301

    IT_Support
    Participant

    Hi All,
    I came across the below script and tried modifying it to instead of just use the one Hostname, use a Text file with get-content,
    However i keep getting errors no mater which way i try to format it,
    Is someone able to tell me what im doing wrong please.
    Thanks,

    I changed from the original code below to be: [String[]]$ComputerName = get-content c:\temp\machinelist.txt
    I tried moving down a few lines as well but same issue,
    Any help would be great.
    Thanks.
    —————————-

     Get-Monitor.ps1 -ComputerName SSL1-F1102-1G2Z
          Manufacturer Model    SerialNumber AttachedComputer
          ------------ -----    ------------ ----------------
          HP           HP E241i CN12345678   SSL1-F1102-1G2Z 
          HP           HP E241i CN91234567   SSL1-F1102-1G2Z 
          HP           HP E241i CN89123456   SSL1-F1102-1G2Z
          .EXAMPLE
          PS C:/> $Computers = @("SSL7-F108F-9D4Z","SSL1-F1102-1G2Z","SSA7-F1071-0T7F")
          PS C:/> Get-Monitor.ps1 -ComputerName $Computers
          Manufacturer Model      SerialNumber AttachedComputer
          ------------ -----      ------------ ----------------
          HP           HP LA2405x CN12345678   SSL7-F108F-9D4Z
          HP           HP E241i   CN91234567   SSL1-F1102-1G2Z 
          HP           HP E241i   CN89123456   SSL1-F1102-1G2Z 
          HP           HP E241i   CN78912345   SSL1-F1102-1G2Z
          HP           HP ZR22w   CN67891234   SSA7-F1071-0T7F
      #>
    
    
      [CmdletBinding()]
      PARAM (
        [Parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        [String[]]$ComputerName = $env:ComputerName
      )
      
      #List of Manufacture Codes that could be pulled from WMI and their respective full names. Used for translating later down.
      $ManufacturerHash = @{ 
        "AAC" =	"AcerView";
        "ACR" = "Acer";
        "AOC" = "AOC";
        "AIC" = "AG Neovo";
        "APP" = "Apple Computer";
        "AST" = "AST Research";
        "AUO" = "Asus";
        "BNQ" = "BenQ";
        "CMO" = "Acer";
        "CPL" = "Compal";
        "CPQ" = "Compaq";
        "CPT" = "Chunghwa Pciture Tubes, Ltd.";
        "CTX" = "CTX";
        "DEC" = "DEC";
        "DEL" = "Dell";
        "DPC" = "Delta";
        "DWE" = "Daewoo";
        "EIZ" = "EIZO";
        "ELS" = "ELSA";
        "ENC" = "EIZO";
        "EPI" = "Envision";
        "FCM" = "Funai";
        "FUJ" = "Fujitsu";
        "FUS" = "Fujitsu-Siemens";
        "GSM" = "LG Electronics";
        "GWY" = "Gateway 2000";
        "HEI" = "Hyundai";
        "HIT" = "Hyundai";
        "HSL" = "Hansol";
        "HTC" = "Hitachi/Nissei";
        "HWP" = "HP";
        "IBM" = "IBM";
        "ICL" = "Fujitsu ICL";
        "IVM" = "Iiyama";
        "KDS" = "Korea Data Systems";
        "LEN" = "Lenovo";
        "LGD" = "Asus";
        "LPL" = "Fujitsu";
        "MAX" = "Belinea"; 
        "MEI" = "Panasonic";
        "MEL" = "Mitsubishi Electronics";
        "MS_" = "Panasonic";
        "NAN" = "Nanao";
        "NEC" = "NEC";
        "NOK" = "Nokia Data";
        "NVD" = "Fujitsu";
        "OPT" = "Optoma";
        "PHL" = "Philips";
        "REL" = "Relisys";
        "SAN" = "Samsung";
        "SAM" = "Samsung";
        "SBI" = "Smarttech";
        "SGI" = "SGI";
        "SNY" = "Sony";
        "SRC" = "Shamrock";
        "SUN" = "Sun Microsystems";
        "SEC" = "Hewlett-Packard";
        "TAT" = "Tatung";
        "TOS" = "Toshiba";
        "TSB" = "Toshiba";
        "VSC" = "ViewSonic";
        "ZCM" = "Zenith";
        "UNK" = "Unknown";
        "_YV" = "Fujitsu";
          }
          
      
      #Takes each computer specified and runs the following code:
      ForEach ($Computer in $ComputerName) {
      
        #Grabs the Monitor objects from WMI
        $Monitors = Get-WmiObject -Namespace "root\WMI" -Class "WMIMonitorID" -ComputerName $Computer -ErrorAction SilentlyContinue
        
        #Creates an empty array to hold the data
        $Monitor_Array = @()
        
        
        #Takes each monitor object found and runs the following code:
        ForEach ($Monitor in $Monitors) {
          
          #Grabs respective data and converts it from ASCII encoding and removes any trailing ASCII null values
          If ([System.Text.Encoding]::ASCII.GetString($Monitor.UserFriendlyName) -ne $null) {
            $Mon_Model = ([System.Text.Encoding]::ASCII.GetString($Monitor.UserFriendlyName)).Replace("$([char]0x0000)","")
          } else {
            $Mon_Model = $null
          }
          $Mon_Serial_Number = ([System.Text.Encoding]::ASCII.GetString($Monitor.SerialNumberID)).Replace("$([char]0x0000)","")
          $Mon_Attached_Computer = ($Monitor.PSComputerName).Replace("$([char]0x0000)","")
          $Mon_Manufacturer = ([System.Text.Encoding]::ASCII.GetString($Monitor.ManufacturerName)).Replace("$([char]0x0000)","")
          
          #Filters out "non monitors". Place any of your own filters here. These two are all-in-one computers with built in displays. I don't need the info from these.
          If ($Mon_Model -like "*800 AIO*" -or $Mon_Model -like "*8300 AiO*") {Break}
          
          #Sets a friendly name based on the hash table above. If no entry found sets it to the original 3 character code
          $Mon_Manufacturer_Friendly = $ManufacturerHash.$Mon_Manufacturer
          If ($Mon_Manufacturer_Friendly -eq $null) {
            $Mon_Manufacturer_Friendly = $Mon_Manufacturer
          }
          
          #Creates a custom monitor object and fills it with 4 NoteProperty members and the respective data
          $Monitor_Obj = [PSCustomObject]@{
            Manufacturer     = $Mon_Manufacturer_Friendly
            Model            = $Mon_Model
            SerialNumber     = $Mon_Serial_Number
            AttachedComputer = $Mon_Attached_Computer
          }
          
          #Appends the object to the array
          $Monitor_Array += $Monitor_Obj
    
        } #End ForEach Monitor
      
        #Outputs the Array
        $Monitor_Array
        
    } #End ForEach Computer
    
  • #82309

    Don Jones
    Keymaster

    Since it's a little hard to cold-read someone else's code, can you share the problem your'e having and any error message?

  • #82369

    IT_Support
    Participant

    Hi Don,
    Thanks for the prompt response.
    I am finding that it is only working for the first machine listed in the text file, not the additional machines, even if ii change hostnames etc. I had a colleague look at it and was advised when trying to debug it, that it only seems to pass through the first machine, not additional ones.
    One recommendation given to me was to try invoke the script remotely on our office machines however was advised by a colleague that we aren't able to do that, instead I would need to log into one machine with my admin and run it from there to remotely capture the details.

    I need to do an AssetManagement capture, so I am after a script that I can run on one machine, feed in a Text file of the hostnames and capture the results into a txt or csv file – I need the Hostname, and MOnitor Make as well as Serial Numbers to be all displayed,
    THings such as Last Logged in User or OS would be a great extra but not a necessity at this stage.

    Thanks,

    *************************************************************************************
    Error:
    PS T:\AU_Support\_Scripts_And_Batch Files\Asset_Scans> C:\Temp\MonitorScan_v8.ps1

    Manufacturer Model SerialNumber AttachedComputer
    ———— —– ———— —————-
    Dell DELL U2415 G7W7975D35RS SYDAC02955D
    Dell DELL U2415 G7W797680YJS SYDAC02955D
    Get-WmiObject : Not supported
    At C:\Temp\MonitorScan_v8.ps1:116 char:17
    + $Monitors = Get-WmiObject -Namespace "root\WMI" -Class "WMIMonitorID" -Compu ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

    PS T:\AU_Support\_Scripts_And_Batch Files\Asset_Scans>

  • #82372

    Don Jones
    Keymaster

    So, I guess I should point out that you're taking kind of a non-PowerShell approach to the way you've designed your script. You're accumulating data in an array, for example, which is kind of a Bad Sign (https://devops-collective-inc.gitbooks.io/the-big-book-of-powershell-gotchas/content/manuscript/accumulating-output-in-a-function.html). The approach is a bit of what makes this harder to debug.

    You've also got SilentlyContinue enabled, which is a terrible idea, because any useful errors we might be seeing are being suppressed.

    I realize you didn't write this, just pointing it out 😉

    The "Not supported" error is telling you that the remote computer doesn't want to provide a response. It's possible it lacks a root\WMI namespace, or that the WMIMonitorID class doesn't exist. That information has to be exposed by the vendor to Windows; it's not something Windows itself provides. So support does differ across machines.

    • #82375

      IT_Support
      Participant

      ok np,
      Yeh, as I'm still trying to learn in my spare time, I basically copied and tried modifying someone else's script.
      I came across another one that I was thinking I may be able to edit and source out the Monitor details?
      Any suggestions please?

      A)I just get numbers for the Monitor Details instead of the actual Text,
      B)Not sure how this will handle multiple Monitors as i am testing on a Laptop at the moment
      C)Still trying to figure out how to make it output to a Text file instead of screen
      Thanks
      ———

      # Remote System Information
      # Shows hardware and OS details from a list of PCs
      
      #$ArrComputers =  "."
      $ArrComputers =  get-content c:\scripts\machinelist.txt
      #Specify the list of PC names in the line above. "." means local system
      
      Clear-Host
      foreach ($Computer in $ArrComputers) 
      {
          $computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
          $computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
          $computerOS = get-wmiobject Win32_OperatingSystem -Computer $Computer
          $MonitorInfo = Get-WmiObject -Namespace root\wmi -Class WmiMonitorID -ComputerName $Computer
          #$computerCPU = get-wmiobject Win32_Processor -Computer $Computer
          $computerHDD = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter drivetype=3
              write-host "System Information for: " $computerSystem.Name -BackgroundColor DarkCyan
              "-------------------------------------------------------"
              "Manufacturer: " + $computerSystem.Manufacturer
              "Model: " + $computerSystem.Model
              "Serial Number: " + $computerBIOS.SerialNumber
              #"CPU: " + $computerCPU.Name
              #"HDD Capacity: "  + "{0:N2}" -f ($computerHDD.Size/1GB) + "GB"
              "HDD Space: " + "{0:P2}" -f ($computerHDD.FreeSpace/$computerHDD.Size) + " Free (" + "{0:N2}" -f ($computerHDD.FreeSpace/1GB) + "GB)"
              "RAM: " + "{0:N2}" -f ($computerSystem.TotalPhysicalMemory/1GB) + "GB"
              "Operating System: " + $computerOS.caption + ", Service Pack: " + $computerOS.ServicePackMajorVersion
              "User logged In: " + $computerSystem.UserName
              "Last Reboot: " + $computerOS.ConvertToDateTime($computerOS.LastBootUpTime)
              "Monitor Make: " + $MonitorInfo.ManufacturerName
              "Monitor Model: " + $MonitorInfo.ManufacturerName
              "Monitor Serial: " + $MonitorInfo.SerialNumberid
      }        
              ""
              "-------------------------------------------------------"
      

      Thanks again

    • #82382

      IT_Support
      Participant

      Update- I tried using "| Out-File -FilePath C:\scripts\testlog.txt -Append", however it only seems to output some of the details into a text file, not all that i can see on the screen.
      Is it technically not possible to output this type of script to a text file?
      Thanks

  • #82391

    Don Jones
    Keymaster

    Grab a copy of "Learn Windows PowerShell in a Month of Lunches" sometime; it explains the formatting system. Short answer: If you don't tell it which properties to include, it defaults to an 80-column output files and chooses as many properties as will fit. It isn't intended to be a duplicate of what's on screen. Solution? Pipe to Format-Table first, and indicate which properties you want.

You must be logged in to reply to this topic.