;========================================================================================================================================== ; ; How to enumerate currently active monitors? ; ; Read and parse monitor EDID asset information from the registry. ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; Heavily based on WinBatch script by Deana Falk, Technical SupportWilson WindowWare Inc. ; Based on code found at http://www.robvanderwoude.com/files/dispedid_vbs.txt ; Based on a script by Michael Baird. ; See also: http://en.wikipedia.org/wiki/Extended_display_identification_data ;------------------------------------------------------------------------------------------------------------------------------------------ ; (c)Detlev Dalitz.20120427.20120428. ;========================================================================================================================================== DirChange (DirScript ()) GoSub DEFINE_FUNCTIONS strMsgTitle = "EDID Monitor asset information" strMsgText = "" cstHKLM = ObjectType ("I4", -2147483646) ; 2147483650; &H80000002; HKEY_LOCAL_MACHINE. strComputer = "." objReg = ObjectGet ("winmgmts:{impersonationLevel=impersonate}!//" : strComputer : "/root/default:StdRegProv") strKeyPath = "SYSTEM\CurrentControlSet\Enum\DISPLAY" ; Predefine variables. Their type and value will be adapted when they are used. arrKeys = 0 arrKeysSub1 = 0 arrKeysSub2 = 0 arrEDID = 0 ; Enumerate Keys. objReg.EnumKey(cstHKLM, strKeyPath, arrKeys) intKLast = ArrInfo (arrKeys, 1) - 1 For intK = 0 To intKLast strKeyName = arrKeys[intK] ; Enumerate KeysSub1. strPathKeySub1 = strKeyPath : "\" : arrKeys[intK] objReg.EnumKey(cstHKLM, strPathKeySub1, arrKeysSub1) intSub1Last = ArrInfo (arrKeysSub1, 1) - 1 For intSub1 = 0 To intSub1Last strKeySub1Name = arrKeysSub1[intSub1] ; Enumerate KeysSub2. strPathKeySub2 = strPathKeySub1 : "\" : arrKeysSub1[intSub1] objReg.EnumKey(cstHKLM, strPathKeySub2, arrKeysSub2) intSub2Last = ArrInfo (arrKeysSub2, 1) - 1 ; If device is not active, then continue loop. blnControl = @FALSE For intSub2 = 0 To intSub2Last blnControl = arrKeysSub2[intSub2] == "Control" If blnControl Then Break Next If !blnControl Then Continue ; Try to get valid binary value, otherwise continue loop. ; First check for BAD_EDID value. strPathKeySub3 = strPathKeySub2 : "\Device Parameters" objReg.GetBinaryValue(cstHKLM, strPathKeySub3, "BAD_EDID", arrEDID) If ObjectTypeGet (arrEDID) == "ARRAY|VARIANT" Then Continue ; Then check for EDID value. objReg.GetBinaryValue(cstHKLM, strPathKeySub3, "EDID", arrEDID) If ObjectTypeGet (arrEDID) != "ARRAY|VARIANT" Then Continue ; Parse EDID structure. Get monitor name and serial number. arrResult = udfParseEDID (arrEDID) ; Get other values. strMfg = "" objReg.GetStringValue(cstHKLM, strPathKeySub2, "Mfg", strMfg) If StrIndex (strMfg, ";", 1, @FWDSCAN) Then strMfg = StrSub (strMfg, StrIndex (strMfg, ";", 1, @FWDSCAN) + 1, -1) If strMfg == "" Then strMfg = "unknown" strDeviceDesc = "" objReg.GetStringValue(cstHKLM, strPathKeySub2, "DeviceDesc", strDeviceDesc) If StrIndex (strDeviceDesc, ";", 1, @FWDSCAN) Then strDeviceDesc = StrSub (strDeviceDesc, StrIndex (strDeviceDesc, ";", 1, @FWDSCAN) + 1, -1) If strDeviceDesc == "" Then strDeviceDesc = "unknown" strMsgText = strMsgText : @CRLF : "Manufacturer = " : strMfg : @CRLF : "Description = " : strDeviceDesc : @CRLF : "Model = " : arrResult[0] : @CRLF : "Serial# = " : arrResult[1] : @CRLF Next Next objReg = 0 strMsgText = StrSub (strMsgText, 3, -1) ; Remove leading @CRLF. Pause (strMsgTitle, strMsgText) :CANCEL Exit ;========================================================================================================================================== :DEFINE_FUNCTIONS ;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfParseEDID (arrEDID) arrTestModel = Arrayize ("0,0,0,252", ",") ; Descriptor type: Monitor name (text). arrTestSerial = Arrayize ("0,0,0,255", ",") ; Descriptor type: Monitor serial number (text). arrDescriptors = Arrayize ("54,72,90,108", ",") ; Relevant entry points into the EDID structure (descriptor blocks). arrResult = Arrayize (",", ",") ; Preset result array with two empty elements. For intD = 0 To 3 For intB = 0 To 3 intIndex = arrDescriptors[intD] + intB blnModel = arrTestModel[intB] == arrEDID[intIndex] ; VT UI1, 1-byte unsigned integer. blnSerial = arrTestSerial[intB] == arrEDID[intIndex] ; VT UI1, 1-byte unsigned integer. Next If blnModel || blnSerial strTemp = "" For intB = 5 To 17 intIndex = arrDescriptors[intD] + intB Switch arrEDID[intIndex] Case 0 Case 7 Case 10 Case 13 strTemp = strTemp : " " Break Case arrEDID[intIndex] strTemp = strTemp : Num2Char (arrEDID[intIndex]) EndSwitch Next strTemp = StrTrim (strTemp) If blnModel Then arrResult[0] = strTemp If blnSerial Then arrResult[1] = strTemp EndIf Next Return arrResult #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ Return ; from GoSub DEFINE_FUNCTIONS ;========================================================================================================================================== ; EDID Extended display identification data structure, version 1.3 ; ; Descriptor blocks. ; Detailed timing descriptors, in decreasing preference order. ; After all detailed timing descriptors, additional descriptors are permitted: ; Monitor range limits (required) ; ASCII text (monitor name (required), monitor serial number, or unstructured text) ; 6 Additional standard timing information blocks ; Colour point data ; ; Bytes : Description ; 054071: Descriptor 1 ; 072089: Descriptor 2 ; 090107: Descriptor 3 ; 108125: Descriptor 4 ;------------------------------------------------------------------------------------------------------------------------------------------ ; EDID Descriptor block ; ; Bytes : Description ; 000001: Zero, indicates not a detailed timing descriptor ; 002 : Zero ; 003 : Descriptor type. FAFF currently defined. 000F reserved for vendors. ; 004 : Zero ; 005017: Defined by descriptor type. If text, code page 437 text, terminated (if less than 13 bytes) with LF and padded with SP. ; ; Currently defined descriptor types are: ; 0xFF : Monitor serial number (text) ; 0xFE : Unspecified text (text) ; 0xFD : Monitor range limits. 6- or 13-byte binary descriptor. ; 0xFC : Monitor name (text) ; 0xFB : Additional white point data. 2× 5-byte descriptors, padded with 0A 20 20. ; 0xFA : Additional standard timing identifiers. 6× 2-byte descriptors, padded with 0A. ;==========================================================================================================================================