Communicating Through USB Ports with Visual Basic

Introduction

Welcome to my article. Today, I would like to show you how to determine whether or not a USB stick has been inserted or removed.

There are various ways, some easy and some not so easy, to determine USB disk insertion. You could use several APIs, such as RegisterDeviceNotification and UnregisterDeviceNotification, just to name a couple. Today, I will take a different approach (for a change) and not go the API route but go the WMI route instead.

What Is API?

The Windows API is a set of several hundred functions and subroutines that are located in a set of files called Dynamic Link Libraries (DLLs). You can make a function from the Windows API available to your Visual Basic program by declaring the function to be callable from your program. You then can use the Windows API function as you would any built-in Visual Basic function or a function that you have written yourself.

End users cannot access these functions; however, programmers can access the code written in the DLLs through the API and use this code in their programs. This enables you to use existent code in the DLLs and save you time in the programming development cycle. The advantage of using Windows APIs in your code is that they can save development time because they contain dozens of useful functions that are already written and waiting to be used. The disadvantage is that Windows APIs can be difficult to work with and unforgiving when things go wrong.

What Is WMI?

WMI (Windows Management Instrumentation), as quoted from MSDN, is the infrastructure for management data and operations on Windows-based operating systems. Okay, in layman’s terms, this means that via the use of WMI, we can retrieve data that is at the heart of our hardware and/or services. We’ll cover the preceding list of topics today, especially the hard disk serial number, which is not as easy to come by usually.

System.Management Namespace

Have a read through the linked article for more information on the System.Management Namespace.

Practical

Open Visual Studio and create a new VB Windows Forms project. Once the project is loaded, add two buttons to your form.

Add the necessary Namespaces:

Imports System.Management

Create the ManagementEventWatcher object:

Private WithEvents MediaConnectWatcher As ManagementEventWatcher

Through this object, we will be notified of device insertion or removal.

Add the following code for the first button’s click event:

   Private Sub Button1_Click(ByVal sender As System.Object, _
         ByVal e As System.EventArgs) Handles Button1.Click
      Dim query As String = "SELECT * _
         FROM __InstanceOperationEvent _
         WITHIN 10 WHERE TargetInstance ISA _
         ""Win32_DiskDrive"""
      MediaConnectWatcher = New ManagementEventWatcher(query)
      MediaConnectWatcher.Start()
   End Sub

This sets everything in motion. The query simply checks to see if there has been a suitable device inserted and starts the ManagementEventWatcher object.

Add the Inserted sub:

   Private Sub Inserted(ByVal sender As Object, _
         ByVal e As System.Management.EventArrivedEventArgs) _
         Handles MediaConnectWatcher.EventArrived
      Dim mbo, obj As ManagementBaseObject

      mbo = CType(e.NewEvent, ManagementBaseObject)
         obj = CType(mbo("TargetInstance"), _
            ManagementBaseObject)

      Select Case mbo.ClassPath.ClassName
         Case "__InstanceCreationEvent"
            If obj("InterfaceType") = "USB" Then
               MsgBox(obj("Caption") & " (Drive letter " & _
                  GetDriveLetterFromDisk(obj("Name")) & ") _
                  has been plugged in")
            End If
         Case "__InstanceDeletionEvent"
            If obj("InterfaceType") = "USB" Then
               MsgBox(obj("Caption") & " has been unplugged")
            End If
      End Select

   End Sub

This simply produces a message informing you that the stick has been inserted. This procedure also calls a procedure named GetDriveLetterFromDisk to provide the correct drive letter. Let’s add this procedure now:

   Private Function GetDriveLetterFromDisk(ByVal Name As String) _
         As String
      Dim oq_part, oq_disk As ObjectQuery
      Dim mos_part, mos_disk As ManagementObjectSearcher
      Dim obj_part, obj_disk As ManagementObject
      Dim ans As String

      Name = Replace(Name, "", "\")

      oq_part = New ObjectQuery("ASSOCIATORS OF _
         {Win32_DiskDrive.DeviceID=""" & Name & """} _
         WHERE AssocClass = Win32_DiskDriveToDiskPartition")
      mos_part = New ManagementObjectSearcher(oq_part)
      For Each obj_part In mos_part.Get()

         oq_disk = New ObjectQuery("ASSOCIATORS OF _
            {Win32_DiskPartition.DeviceID=""" & _
            obj_part("DeviceID") & """} _
            WHERE AssocClass = Win32_LogicalDiskToPartition")
         mos_disk = New ManagementObjectSearcher(oq_disk)
         For Each obj_disk In mos_disk.Get()
            ans &= obj_disk("Name") & ","
         Next
      Next

      Return ans.Trim(","c)
   End Function

Finally, add the second button’s code:

   Private Sub Button2_Click(ByVal sender As System.Object, _
         ByVal e As System.EventArgs) Handles Button2.Click
      MediaConnectWatcher.Stop()
   End Sub

This stop the ManagementEventWatcher object from listening to more events.

Conclusion

As you can see, getting messages fired upon device insertion or device removal is quite easy through WMI. Until next time, cheers!

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read