ElektroStudios
ElektroStudios

Reputation: 20494

Get Monitor display name without API or WMI usage?

I would like to know if .NET framework Classes provides a way to retrieve a monitor display name (eg: LG TV) without recurring to WMI or WinAPI usage, I already know how to retrieve the monitor names through those alternatives, this question is for curiosity to avoid API or WMI usage in case that it could be done using the .NET ClassLibrary, to improve the coding in general.

Thanks.

Upvotes: 2

Views: 825

Answers (2)

Christbaum Schmuck
Christbaum Schmuck

Reputation: 31

Maybe over the Registry? It will got through all your Displays. It will return the Name out of the EDID.

BUT, there was a Change in Win10! Win10 has no "Control" but a "Properties" SubKey (Workaround at the IF/OR) #untested!

Public Function GetMonitorDetails() As List(Of String())
    Dim sReturn As List(Of String()) = New List(Of String())

    'Open the Display Reg-Key
    Dim Display As RegistryKey = Registry.LocalMachine
    Dim bFailed As Boolean = False
    Try
        Display = Registry.LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Enum\DISPLAY")
    Catch ex As Exception
        sReturn.Add({"Error", ex.Message})
        bFailed = True
    End Try
    If Not bFailed And (Display IsNot Nothing) Then
        'Get all MonitorIDss
        For Each sMonitorID As String In Display.GetSubKeyNames()
            Dim MonitorID As RegistryKey = Display.OpenSubKey(sMonitorID)
            If MonitorID IsNot Nothing Then
                'Get all Plug&Play ID's
                For Each sPNPID As String In MonitorID.GetSubKeyNames()
                    Dim PnPID As RegistryKey = MonitorID.OpenSubKey(sPNPID)
                    If PnPID IsNot Nothing Then
                        Dim sSubkeys As String() = PnPID.GetSubKeyNames()
                        Dim ssSubkeys As String = String.Join(".", sSubkeys)
                        'Check if Monitor is active
                        If (ssSubkeys.Contains("Control") Or ssSubkeys.Contains("Properties")) And ssSubkeys.Contains("Device Parameters") Then
                            Dim DevParam As RegistryKey = PnPID.OpenSubKey("Device Parameters")
                            Dim sSerial As String = ""
                            Dim sModel As String = ""
                            Dim tmpMfg As String = ""
                            Dim tmpVer As String = ""
                            Dim tmpDev As String = ""
                            Dim iWeek As Integer = 0
                            Dim iYear As Integer = 0

                            'Define Search Keys
                            Dim sSerFind As New String(New Char() {ChrW(0), ChrW(0), ChrW(0), ChrW(&HFF)})
                            Dim sModFind As New String(New Char() {ChrW(0), ChrW(0), ChrW(0), ChrW(&HFC)})
                            'Get the EDID code
                            Dim bObj As Byte() = TryCast(DevParam.GetValue("EDID", Nothing), Byte())
                            If bObj IsNot Nothing Then
                                'Get the 4 Vesa descriptor blocks
                                Dim sDescriptor As String() = New String(3) {}
                                sDescriptor(0) = Encoding.[Default].GetString(bObj, &H36, 18)
                                sDescriptor(1) = Encoding.[Default].GetString(bObj, &H48, 18)
                                sDescriptor(2) = Encoding.[Default].GetString(bObj, &H5A, 18)
                                sDescriptor(3) = Encoding.[Default].GetString(bObj, &H6C, 18)

                                iWeek = Asc(Encoding.[Default].GetString(bObj, &H10, 1))
                                iYear = Asc(Encoding.[Default].GetString(bObj, &H11, 1)) + 1990

                                Dim tmpEDIDMfg As String
                                Dim Char1, Char2, Char3 As Integer
                                Dim Byte1, Byte2 As Byte
                                tmpEDIDMfg = Encoding.[Default].GetString(bObj, &H8, 2)
                                Char1 = 0 : Char2 = 0 : Char3 = 0
                                Byte1 = CByte(Asc(Left(tmpEDIDMfg, 1)))
                                Byte2 = CByte(Asc(Right(tmpEDIDMfg, 1)))

                                If (Byte1 And 64) > 0 Then Char1 = Char1 + 16
                                If (Byte1 And 32) > 0 Then Char1 = Char1 + 8
                                If (Byte1 And 16) > 0 Then Char1 = Char1 + 4
                                If (Byte1 And 8) > 0 Then Char1 = Char1 + 2
                                If (Byte1 And 4) > 0 Then Char1 = Char1 + 1
                                If (Byte1 And 2) > 0 Then Char2 = Char2 + 16
                                If (Byte1 And 1) > 0 Then Char2 = Char2 + 8
                                If (Byte2 And 128) > 0 Then Char2 = Char2 + 4
                                If (Byte2 And 64) > 0 Then Char2 = Char2 + 2
                                If (Byte2 And 32) > 0 Then Char2 = Char2 + 1

                                Char3 = Char3 + (Byte2 And 16)
                                Char3 = Char3 + (Byte2 And 8)
                                Char3 = Char3 + (Byte2 And 4)
                                Char3 = Char3 + (Byte2 And 2)
                                Char3 = Char3 + (Byte2 And 1)
                                tmpMfg = Chr(Char1 + 64) & Chr(Char2 + 64) & Chr(Char3 + 64)

                                Dim tmpEDIDMajorVer, tmpEDIDRev As Integer
                                tmpEDIDMajorVer = Asc(Encoding.[Default].GetString(bObj, &H12, 1))
                                tmpEDIDRev = Asc(Encoding.[Default].GetString(bObj, &H13, 1))
                                tmpVer = Chr(48 + tmpEDIDMajorVer) & "." & Chr(48 + tmpEDIDRev)

                                Dim tmpEDIDDev1, tmpEDIDDev2 As String
                                tmpEDIDDev1 = Hex(Asc(Encoding.[Default].GetString(bObj, &HA, 1)))
                                tmpEDIDDev2 = Hex(Asc(Encoding.[Default].GetString(bObj, &HB, 1)))
                                If Len(tmpEDIDDev1) = 1 Then tmpEDIDDev1 = "0" & tmpEDIDDev1
                                If Len(tmpEDIDDev2) = 1 Then tmpEDIDDev2 = "0" & tmpEDIDDev2
                                tmpDev = tmpEDIDDev2 & tmpEDIDDev1

                                'Search the Keys
                                For Each sDesc As String In sDescriptor
                                    If sDesc.Contains(sSerFind) Then
                                        sSerial = sDesc.Substring(4).Replace(vbNullChar, "").Trim()
                                    End If
                                    If sDesc.Contains(sModFind) Then
                                        sModel = sDesc.Substring(4).Replace(vbNullChar, "").Trim()
                                    End If
                                Next
                            End If
                            If Not String.IsNullOrEmpty(sPNPID & sSerFind & sModel & sMonitorID) Then
                                sReturn.Add({sMonitorID, sModel, sPNPID, tmpDev, tmpVer, tmpMfg, iWeek, iYear, sSerial})
                            End If
                        End If
                    End If
                Next
            End If
        Next
    End If

    Return sReturn
End Function

Upvotes: 0

Erti-Chris Eelmaa
Erti-Chris Eelmaa

Reputation: 26318

As far I know, the answer would be NO. There is winforms class Screen.cs that can do few basic things, but that does not expose monitor display name. It exposes though DeviceName that can be used for further analysis, if that helps:

Screen.AllScreens[0].Dump()

would give you:

Screen[Bounds={X=0,Y=0,Width=1920,Height=1200} 
       WorkingArea={X=0,Y=0,Width=1920,Height=1160} 
       Primary=True 
       DeviceName=\\.\DISPLAY1]

I did start MultiMonitorHelper library that should aim to "abstract" away all this meaningless WinAPI/WMI gibberish, but I never got around doing it. It is on my "want-to-do" things list though :p

Upvotes: 2

Related Questions