Reputation: 20494
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
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
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