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!