Skip to content

Instantly share code, notes, and snippets.

@ararog
Created November 5, 2013 10:01
Show Gist options
  • Save ararog/7316613 to your computer and use it in GitHub Desktop.
Save ararog/7316613 to your computer and use it in GitHub Desktop.
This script does a computer monitor lookup.
[CmdletBinding(DefaultParameterSetName="ComputerName")]
param (
[Parameter(Mandatory = $FALSE, ParameterSetName="ComputerName", HelpMessage="Name of computer to check")]
[String]
$ComputerName
)
Function InArray($element, $array, $position) {
If($array.Count -eq 0) {
return $False
}
foreach($item in $array) {
If($item.Count -gt 0) {
If($item[$position] -eq $element) {
return $True
}
}
}
return $False
}
Function EchoAndLog ($message) {
#Echo output and write to log
write-output $message
$message >> $logFile
}
Function Show-Msgbox {
Param([string]$message=$(Throw "You must specify a message"),
[string]$button="okonly",
[string]$icon="information",
[string]$title="Message Box"
)
#Buttons: OkOnly, OkCancel, AbortRetryIgnore, YesNoCancel, YesNo, RetryCancel
#Icons: Critical, Question, Exclamation, Information
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Visualbasic") | Out-Null
[Microsoft.Visualbasic.Interaction]::Msgbox($message, "$button, $icon", $title)
}
$batch = $false
If(! $ComputerName) {
[Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$ComputerName = [Microsoft.VisualBasic.Interaction]::InputBox("Check Monitor info for what PC", "PC Name?", "$env:computername")
}
else {
$batch = $true
}
If(! $ComputerName) {
exit
}
$ComputerName = $ComputerName.ToUpper()
$MonitorCount = 0
$StringArrayRawEDIDs = @()
$logFile = "$env:userprofile\Desktop\MonitorInfo.csv"
$message = ""
If($batch) {
$header = $false
$file_exists = test-path $logFile
If(! $file_exists) {
$header = $true
}
if($header) {
"Computer,Model,Serial #,Vendor ID,Manufacture Date,Messages" > $logFile
}
}
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", "$ComputerName")
$displayKey = $reg.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\")
foreach ($displayKeyValue in $displayKey.GetSubKeyNames()) {
$monitorIdKey = $displayKey.OpenSubKey("$displayKeyValue")
foreach ($pnpIdKeyValue in $monitorIdKey.GetSubKeyNames()) {
$pnpIdKey = $monitorIdKey.OpenSubKey("$pnpIdKeyValue")
foreach($hardwareIdKeyValue in $pnpIdKey.GetValue("HardwareID")) {
If($hardwareIdKeyValue.ToLower().IndexOf("monitor\") -gt -1) {
foreach ($pnpDetailsKeyValue in $pnpIdKey.GetSubKeyNames()) {
$strRawEDID = ""
If($pnpDetailsKeyValue -eq "Control") {
$deviceParametersKey = $pnpIdKey.OpenSubKey("Device Parameters")
$edid = $deviceParametersKey.GetValue("EDID")
if(! $edid) {
$strRawEDID = "EDID Not Available"
}
else {
foreach($byteValue in $edid) {
$strRawEDID = $strRawEDID + [char]$byteValue
}
}
$StringArrayRawEDIDs += $strRawEDID
$MonitorCount += 1
}
}
}
}
}
}
$ArrayMonitorInfo = @()
$Location = @("", "", "", "")
$intSerFoundAt, $intMdlFoundAt, $findit = 0
$tmp, $tmpser, $tmpmdl, $tmpctr = ""
foreach($string in $StringArrayRawEDIDs) {
if($string -ne "EDID Not Available") {
$Location[0] = $string.Substring(0x36, 19)
$Location[1] = $string.Substring(0x48, 19)
$Location[2] = $string.Substring(0x5a, 19)
$Location[3] = $string.Substring(0x6c, 19)
#you can tell If the location contains a serial number If it starts with &H00 00 00 ff
$strSerFind = ([char](0x00)) + ([char](0x00)) + ([char](0x00)) + ([char](0xff))
#or a model description If it starts with &H00 00 00 fc
$strMdlFind = ([char](0x00)) + ([char](0x00)) + ([char](0x00)) + ([char](0xfc))
$intSerFoundAt = -1
$intMdlFoundAt = -1
for($findit = 0; $findit -le 3; $findit++) {
If($Location[$findit].IndexOf($strSerFind) -gt -1) {
$intSerFoundAt = $findit
}
If($Location[$findit].IndexOf($strMdlFind) -gt -1) {
$intMdlFoundAt = $findit
}
}
#If a location containing a serial number block was found then store it
If($intSerFoundAt -ne -1) {
$tmp = $Location[$intSerFoundAt]
$tmp = $tmp.substring($tmp.length - 14, 14)
If($tmp.IndexOf([char](0x0a)) -gt -1) {
$tmpser = $tmp.substring(0, $tmp.IndexOf([char](0x0a))).Trim()
}
else {
$tmpser = $tmp.Trim()
}
#although it is not part of the edid spec it seems as though the
#serial number will frequently be preceeded by &H00, this
#compensates for that
If($tmpser.substring(0, 1) -eq [char](0)) {
$tmpser = $tmpser.substring($tmpser.length - 1, 1)
}
}
else {
$tmpser = "Not Found"
}
#If a location containing a model number block was found then store it
If($intMdlFoundAt -ne -1) {
$tmp = $Location[$intMdlFoundAt]
$tmp = $tmp.substring($tmp.length - 14, 14)
If($tmp.IndexOf([char](0x0a)) -gt -1) {
$tmpmdl = $tmp.substring(0, $tmp.IndexOf([char](0x0a))).Trim()
}
else {
$tmpmdl = $tmp.Trim()
}
#although it is not part of the edid spec it seems as though the
#serial number will frequently be preceeded by &H00, this
#compensates for that
If($tmpmdl.substring(0, 1) -eq [char](0)) {
$tmpmdl = $tmpmdl.substring($tmpmdl.length - 1, 1)
}
}
else {
$tmpmdl = "Not Found"
}
#**************************************************************
#Next get the mfg date
#**************************************************************
$tmpmfgweek, $tmpmfgyear, $tmpmdt = ""
#the week of manufacture is stored at EDID offset &H10
$tmpmfgweek = [byte][char]($string.substring(0x10, 1))
#the year of manufacture is stored at EDID offset &H11
#and is the current year -1990
$tmpmfgyear = ([byte][char]($string.substring(0x11, 1))) + 1990
#store it in month/year format
$calendar = [System.Globalization.CultureInfo]::InvariantCulture.Calendar
$date = $calendar.AddWeeks([datetime]("1/1/" + $tmpmfgyear), $tmpmfgweek)
$tmpmdt = $date.ToString("MM") + "/" + $tmpmfgyear
#**************************************************************
#Next get the edid version
#**************************************************************
#the version is at EDID offset &H12
$tmpEDIDMajorVer, $tmpEDIDRev, $tmpVer = ""
$tmpEDIDMajorVer = [byte][char]($string.substring(0x12, 1))
#the revision level is at EDID offset &H13
$tmpEDIDRev = [byte][char]($string.substring(0x13, 1))
#store it in month/year format
$tmpver = [char](48 + $tmpEDIDMajorVer) + "." + [char](48 + $tmpEDIDRev)
#**************************************************************
#Next get the mfg id
#**************************************************************
#the mfg id is 2 bytes starting at EDID offset &H08
#the id is three characters long. using 5 bits to represent
#each character. the bits are used so that 1=A 2=B etc..
#
#get the data
$tmpEDIDMfg, $tmpMfg
$Char1, $Char2, $Char3
$Byte1, $Byte2
$tmpEDIDMfg = $string.substring(0x08, 2)
$Char1, $Char2, $Char3 = 0
$Byte1 = [byte][char]($tmpEDIDMfg.substring(0, 1)) #get the first half of the string
$Byte2 = [byte][char]($tmpEDIDMfg.substring($tmpEDIDMfg.length - 1, 1)) #get the first half of the string
#now shift the bits
#shift the 64 bit to the 16 bit
If (($Byte1 -band 64) -gt 0) {
$Char1 = $Char1 + 16
}
#shift the 32 bit to the 8 bit
If (($Byte1 -band 32) -gt 0) {
$Char1 = $Char1 + 8
}
#etc....
If (($Byte1 -band 16) -gt 0) {
$Char1 = $Char1 + 4
}
If (($Byte1 -band 8) -gt 0) {
$Char1 = $Char1 + 2
}
If (($Byte1 -band 4) -gt 0) {
$Char1 = $Char1 + 1
}
#the 2nd character uses the 2 bit and the 1 bit of the 1st byte
If (($Byte1 -band 2) -gt 0) {
$Char2 = $Char2 + 16
}
If (($Byte1 -band 1) -gt 0) {
$Char2 = $Char2 + 8
}
#and the 128,64 and 32 bits of the 2nd byte
If (($Byte2 -band 128) -gt 0) {
$Char2 = $Char2 + 4
}
If (($Byte2 -band 64) -gt 0) {
$Char2 = $Char2 + 2
}
If (($Byte2 -band 32) -gt 0) {
$Char2 = $Char2 + 1
}
#the bits for the 3rd character don't need shifting
#we can use them as they are
$Char3 = $Char3 + ($Byte2 -band 16)
$Char3 = $Char3 + ($Byte2 -band 8)
$Char3 = $Char3 + ($Byte2 -band 4)
$Char3 = $Char3 + ($Byte2 -band 2)
$Char3 = $Char3 + ($Byte2 -band 1)
$tmpmfg = [char]($Char1 + 64) + [char]($Char2 + 64) + [char]($Char3 + 64)
#**************************************************************
#Next get the device id
#**************************************************************
#the device id is 2bytes starting at EDID offset &H0a
#the bytes are in reverse order.
#this code is not text. it is just a 2 byte code assigned
#by the manufacturer. they should be unique to a model
$tmpEDIDDev1, $tmpEDIDDev2, $tmpDev
$tmpEDIDDev1 = "{0:X}" -f ([byte][char]($string.substring(0x0a, 1)))
$tmpEDIDDev2 = "{0:X}" -f ([byte][char]($string.substring(0x0b, 1)))
If($tmpEDIDDev1.length -eq 1) {
$tmpEDIDDev1 = "0" + $tmpEDIDDev1
}
If($tmpEDIDDev2.length -eq 1){
$tmpEDIDDev2 = "0" + $tmpEDIDDev2
}
$tmpdev = $tmpEDIDDev2 + $tmpEDIDDev1
#**************************************************************
#finally store all the values into the array
#**************************************************************
#Kaplan adds code to avoid duplication...
$test = InArray($tmpser, $arrayMonitorInfo, 3)
If(! $test) {
$monitorInfo = @($tmpmfg, $tmpdev, $tmpmdt, $tmpser, $tmpmdl, $tmpVer)
$arrayMonitorInfo += (,$monitorInfo)
}
}
}
#For now just a simple screen print will suffice for output.
#But you could take this output and write it to a database or a file
#and in that way use it for asset management.
$i = 0
foreach($info in $arrayMonitorInfo) {
If ($info[1] -ne "" -and $info[0] -ne "PNP") {
If ($batch) {
EchoAndLog($ComputerName + "," + $info[4] + "," + $info[3] + "," + $info[0] + "," + $info[2])
}
Else {
$message = $message + "Monitor " + [char]($i+65) + ")`nModel Name: " + $info[4] + "`nSerial Number: " + $info[3] + "`nVESA Manufacturer ID: " + $info[0] + "`nManufacture Date: " + $info[2] + "`n`n"
$i += 1
}
}
}
If(! $batch) {
show-msgbox -message $message -icon "information" -button "OKOnly" -title $ComputerName + " Monitor Info"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment