How to get non working devices using Vb.net


When it comes to hardware interaction, many .net developers feel frustrated and uncertain about the capability of doing what they have in mind. One common problem we face is to enumerate the devices installed on your computer. A harder problem is to get the devices that are not working properly or disabled!. If you are writing an application that requires the existence of a specific hardware device, it makes common sense to test whether the desired device is working and enabled.

In Windows, you can view the lis of devices from the Device Manager. Disabled devices appear with a down arrow next to the device and devices that are not working properly appear with a yellow exclamation mark icon next to it:

The solution to such problems in .Net Framework languages becomes simple if we make us of WMI Queries or Windows Management Instrumentation. Writing a WMI query to retrieve system information is as simple as wrting an SQL Query.In fact, it’s almost exactly the same syntax except the objects we are querying do differ. Take a look at the WMI query below that retrieves all installed devices on the local system:

    Select * from Win32_PnPEntity

As simple as that, the Win32_PnpEntity stores information about installed devices. So if want to filter out the results by getting only the non working devices, we simply add a Where clause just like we do if we filtering data from an sql table.

    Select * from Win32_PnPEntity WHERE ConfigManagerErrorCode  0

The ConfigManagerErrorCode property stores the state of the device, a value of 0 means Working and any other different value means the device is not working or disabled.

Lets create a Device class to convert each retrieved device to an object that we can deal with in our application. After all, we would want to list out all non working devices and bind the list to some bindable data object such as a DataGrid or a ListView.

Below is our base Device class having all the properties we need to show:

Public Class Device

    Private mName As String
    Private mManufacturer As String
    Private mDescription As String
    Private mService As String
    Private mDeviceID As String
    Private mPNPDeviceID As String
    Private mClassGUID As String

    Public Property Name() As String
        Get
            Return mName
        End Get
        Set(ByVal value As String)
            mName = value
        End Set
    End Property

    Public Property Manufacturer() As String
        Get
            Return mManufacturer
        End Get
        Set(ByVal value As String)
            mManufacturer = value
        End Set
    End Property

    Public Property Description() As String
        Get
            Return mDescription
        End Get
        Set(ByVal value As String)
            mDescription = value
        End Set
    End Property

    Public Property Service() As String
        Get
            Return mService
        End Get
        Set(ByVal value As String)
            mService = value
        End Set
    End Property

    Public Property DeviceID() As String
        Get
            Return mDeviceID
        End Get
        Set(ByVal value As String)
            mDeviceID = value
        End Set
    End Property

    Public Property PNPDeviceID() As String
        Get
            Return mPNPDeviceID
        End Get
        Set(ByVal value As String)
            mPNPDeviceID = value
        End Set
    End Property

    Public Property ClassGUID() As String
        Get
            Return mClassGUID
        End Get
        Set(ByVal value As String)
            mClassGUID = value
        End Set
    End Property
End Class

We are ready now to implement our two main function, GetAllDevices and GetNonWorkingDevices and add them to the Device class. Both methods will be Shared methods because they are generic and produce the same result across all instances of the Device class. Below is the impelemtation of both methods, note the use of the GetObject method which retrieves an instance of WMI on the local computer system:

Public Shared Function GetAllDevices() As List(Of Device)
    Dim pc As String = "." 'local
    Dim wmi As Object = GetObject("winmgmts:\\" & pc & "\root\cimv2")
    Dim allDevices As New List(Of Device)
    Dim devices As Object = wmi.ExecQuery("Select * from Win32_PnPEntity")
    Dim device As Device
    For Each d As Object In devices
        device = New Device
        With Device
        .mClassGUID = IIf(IsDBNull(d.ClassGuid), 0, d.ClassGuid)
        .mDescription = IIf(IsDBNull(d.Description), 0, d.Description)
        .DeviceID = IIf(IsDBNull(d.DeviceID), 0, d.DeviceID)
        .Manufacturer = IIf(IsDBNull(d.Manufacturer), 0, d.Manufacturer)
        .Name = IIf(IsDBNull(d.Name), 0, d.Name)
        .PNPDeviceID = IIf(IsDBNull(d.PNPDeviceID), 0, d.PNPDeviceID)
        .Service = IIf(IsDBNull(d.Service), 0, d.Service)
        End With
        allDevices.Add(device)
    Next
    Return allDevices
End Function

Public Shared Function GetNonWorkingDevices() As List(Of Device)
    Dim pc As String = "." 'local
    Dim wmi As Object = GetObject("winmgmts:\\" & pc & "\root\cimv2")
    Dim notWorking As New List(Of Device)
    Dim devices As Object = wmi.ExecQuery("Select * from " & _
          "Win32_PnPEntity WHERE ConfigManagerErrorCode  0")
    Dim device As Device
    For Each d As Object In devices
        device = New Device
        With Device
        .mClassGUID = IIf(IsDBNull(d.ClassGuid), 0, d.ClassGuid)
        .mDescription = IIf(IsDBNull(d.Description), 0, d.Description)
        .DeviceID = IIf(IsDBNull(d.DeviceID), 0, d.DeviceID)
        .Manufacturer = IIf(IsDBNull(d.Manufacturer), 0, d.Manufacturer)
        .Name = IIf(IsDBNull(d.Name), 0, d.Name)
        .PNPDeviceID = IIf(IsDBNull(d.PNPDeviceID), 0, d.PNPDeviceID)
        .Service = IIf(IsDBNull(d.Service), 0, d.Service)
        End With
        notWorking.Add(device)
    Next
    Return notWorking
End Function

Our Device class is now ready, we can simply now bind the results of each method to a DataGrid as i have done in the figure below:

Here is the code that produces the above results after adding a DatagridView to a form:

Private Sub Form1_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    DataGridView1.DataSource = Device.GetNonWorkingDevices
End Sub

The project with its source code can be downloaded here(remove the .jpg extension).

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: