How to get Bus Reported Device Description using VB.net

Viewed 664

I am able to retrieve and list all the USB-to-serial virtual comm port names in my app, but am unable to retrieve the bus reported device description for any given port/device, which I'd like to compare against a specific string to match against a particular converter...are there any vb.net interfaces or setupapi.dll propery calls that return the bus reported device description?

Note: Using VS2017 on a Windows 10 pc.

Current code for listing ports is as follows:


 <DllImport("setupapi.dll")>
    Private Shared Function SetupDiClassGuidsFromNameA(ByVal ClassN As String, ByRef guids As Guid, ByVal ClassNameSize As UInt32, ByRef ReqSize As UInt32) As Boolean
    End Function

    <DllImport("setupapi.dll")>
    Private Shared Function SetupDiGetClassDevsA(ByRef ClassGuid As Guid, ByVal Enumerator As UInt32, ByVal hwndParent As IntPtr, ByVal Flags As UInt32) As IntPtr
    End Function

    <DllImport("setupapi.dll")>
    Private Shared Function SetupDiEnumDeviceInfo(ByVal DeviceInfoSet As IntPtr, ByVal MemberIndex As UInt32, ByVal DeviceInfoData As SP_DEVINFO_DATA) As Boolean
    End Function

    <DllImport("setupapi.dll")>
    Private Shared Function SetupDiDestroyDeviceInfoList(ByVal DeviceInfoSet As IntPtr) As Boolean
    End Function

    <DllImport("setupapi.dll")>
    Private Shared Function SetupDiGetDeviceRegistryPropertyA(ByVal DeviceInfoSet As IntPtr, ByVal DeviceInfoData As SP_DEVINFO_DATA, ByVal Propert As UInt32, ByVal PropertyRegDataType As UInt32, ByVal PropertyBuffer As StringBuilder, ByVal PropertyBufferSize As UInt32, ByVal RequiredSize As IntPtr) As Boolean
    End Function

  Private Shared Function EnumerateDevices(ByVal DeviceIndex As UInt32, ByVal ClassName As String, ByVal DeviceName As StringBuilder) As Integer
        Dim RequiredSize As UInt32 = 0
        Dim guid As Guid = Guid.Empty
        Dim guids As Guid() = New Guid(0) {}
        Dim NewDeviceInfoSet As IntPtr
        Dim DeviceInfoData As SP_DEVINFO_DATA = New SP_DEVINFO_DATA()

        Dim res As Boolean = SetupDiClassGuidsFromNameA(ClassName, guids(0), RequiredSize, RequiredSize)
        If RequiredSize = 0 Then
            'incorrect class name:
            DeviceName = New StringBuilder("")
            Return -2
        End If

        If (Not res) Then
            guids = New Guid(System.Convert.ToInt32(RequiredSize) - 1) {}
            res = SetupDiClassGuidsFromNameA(ClassName, guids(0), RequiredSize, RequiredSize)

            If (Not res) OrElse RequiredSize = 0 Then
                'incorrect class name:
                DeviceName = New StringBuilder("")
                Return -2
            End If
        End If

        'get device info set for our device class
        NewDeviceInfoSet = SetupDiGetClassDevsA(guids(0), 0, IntPtr.Zero, DIGCF_PRESENT)
        If NewDeviceInfoSet.ToInt32() = -1 Then
            'device information is unavailable:
            DeviceName = New StringBuilder("")
            Return -3
        End If

        DeviceInfoData.cbSize = 28
        'is devices exist for class
        DeviceInfoData.DevInst = 0
        DeviceInfoData.ClassGuid = System.Guid.Empty
        DeviceInfoData.Reserved = 0

        res = SetupDiEnumDeviceInfo(NewDeviceInfoSet, DeviceIndex, DeviceInfoData)
        If (Not res) Then
            'no such device:
            SetupDiDestroyDeviceInfoList(NewDeviceInfoSet)
            DeviceName = New StringBuilder("")
            Return -1
        End If

        DeviceName.Capacity = MAX_DEV_LEN

        If (Not SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, 0, DeviceName, MAX_DEV_LEN, IntPtr.Zero)) Then
            res = SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC, 0, DeviceName, MAX_DEV_LEN, IntPtr.Zero)
            If (Not res) Then
                'incorrect device name:
                SetupDiDestroyDeviceInfoList(NewDeviceInfoSet)
                DeviceName = New StringBuilder("")
                Return -4
            End If
        End If

        Return 0
    End Function
````


1 Answers

You can do this without any external functions by passing this query to WMI: Select * From Win32_USBHub. Add a reference to assembly System.Management.

Dim mos = New System.Management.ManagementObjectSearcher("Select * From Win32_USBHub").Get()
For Each mo In mos
    Console.Write(mo("Description") & ": ")
    Console.WriteLine(mo)
Next

mo("Description") should have what you are looking for.

EDIT Seems like it doesn't have what you need. This writes everything to console and to a text file:

Dim header = $"Availability{vbTab}Caption{vbTab}ClassCode{vbTab}ConfigManagerUserConfig{vbTab}CreationClassName{vbTab}CurrentAlternateSettings[]{vbTab}CurrentConfigValue{vbTab}Description{vbTab}ErrorCleared{vbTab}ErrorDescription{vbTab}GangSwitched{vbTab}InstallDate{vbTab}LastErrorCode{vbTab}NumberOfConfigs{vbTab}NumberOfPorts{vbTab}PNPDeviceID{vbTab}PowerManagementCapabilities[]{vbTab}PowerManagementSupported{vbTab}ProtocolCode{vbTab}Status{vbTab}StatusInfo{vbTab}SubclassCode{vbTab}SystemCreationClassName{vbTab}SystemName{vbTab}USBVersion{vbTab}ConfigManagerErrorCode{vbTab}DeviceID{vbTab}Name"
Dim mos = New System.Management.ManagementObjectSearcher("Select * From Win32_USBHub").Get()
Console.WriteLine(header)
For Each mo In mos
    Console.WriteLine($"{mo("Availability")}{vbTab}{mo("Caption")}{vbTab}{mo("ClassCode")}{vbTab}{mo("ConfigManagerUserConfig")}{vbTab}{mo("CreationClassName")}{vbTab}{mo("CurrentAlternateSettings")}{vbTab}{mo("CurrentConfigValue")}{vbTab}{mo("Description")}{vbTab}{mo("ErrorCleared")}{vbTab}{mo("ErrorDescription")}{vbTab}{mo("GangSwitched")}{vbTab}{mo("InstallDate")}{vbTab}{mo("LastErrorCode")}{vbTab}{mo("NumberOfConfigs")}{vbTab}{mo("NumberOfPorts")}{vbTab}{mo("PNPDeviceID")}{vbTab}{mo("PowerManagementCapabilities")}{vbTab}{mo("PowerManagementSupported")}{vbTab}{mo("ProtocolCode")}{vbTab}{mo("Status")}{vbTab}{mo("StatusInfo")}{vbTab}{mo("SubclassCode")}{vbTab}{mo("SystemCreationClassName")}{vbTab}{mo("SystemName")}{vbTab}{mo("USBVersion")}{vbTab}{mo("ConfigManagerErrorCode")}{vbTab}{mo("DeviceID")}{vbTab}{mo("Name")}")
Next
Using sr As New StreamWriter("output.txt", False, Text.Encoding.UTF8)
    sr.WriteLine(header)
    For Each mo In mos
        sr.WriteLine($"{mo("Availability")}{vbTab}{mo("Caption")}{vbTab}{mo("ClassCode")}{vbTab}{mo("ConfigManagerUserConfig")}{vbTab}{mo("CreationClassName")}{vbTab}{mo("CurrentAlternateSettings")}{vbTab}{mo("CurrentConfigValue")}{vbTab}{mo("Description")}{vbTab}{mo("ErrorCleared")}{vbTab}{mo("ErrorDescription")}{vbTab}{mo("GangSwitched")}{vbTab}{mo("InstallDate")}{vbTab}{mo("LastErrorCode")}{vbTab}{mo("NumberOfConfigs")}{vbTab}{mo("NumberOfPorts")}{vbTab}{mo("PNPDeviceID")}{vbTab}{mo("PowerManagementCapabilities")}{vbTab}{mo("PowerManagementSupported")}{vbTab}{mo("ProtocolCode")}{vbTab}{mo("Status")}{vbTab}{mo("StatusInfo")}{vbTab}{mo("SubclassCode")}{vbTab}{mo("SystemCreationClassName")}{vbTab}{mo("SystemName")}{vbTab}{mo("USBVersion")}{vbTab}{mo("ConfigManagerErrorCode")}{vbTab}{mo("DeviceID")}{vbTab}{mo("Name")}")
    Next
End Using

Seems like Name, Description, and Caption are all pretty much the same thing you don't need. Sorry it didn't work out.

Related