I had to re-write the post because stackoverflow detects the post as already solved in another thread and i had to delete it. But the thread that referenced the forum was for C# and in anycase even reading it I can't find out a solution for my problem.
So, hello again guys :D
I did find somewhere online a code that allows me to detect usb devices and relative files, it works but not very well because each time i plug or unplug the usb device i get:
"System.NullReferenceException", i will not write the rest of the error to avoid that stackoverflow closes the thread, anyway you should have understood my issue.
Here the code:
Imports System.IO
Public Class Form1
#Region "USB EVENT"
Private WM_DEVICECHANGE As Integer = &H219
Public Enum WM_DEVICECHANGE_WPPARAMS As Integer
DBT_CONFIGCHANGECANCELED = &H19
DBT_CONFIGCHANGED = &H18
DBT_CUSTOMEVENT = &H8006
DBT_DEVICEARRIVAL = &H8000
DBT_DEVICEQUERYREMOVE = &H8001
DBT_DEVICEQUERYREMOVEFAILED = &H8002
DBT_DEVICEREMOVECOMPLETE = &H8004
DBT_DEVICEREMOVEPENDING = &H8003
DBT_DEVICETYPESPECIFIC = &H8005
DBT_DEVNODES_CHANGED = &H7
DBT_QUERYCHANGECONFIG = &H17
DBT_USERDEFINED = &HFFFF
End Enum
Private Structure DEV_BROADCAST_VOLUME
Public dbcv_size As Int32
Public dbcv_devicetype As Int32
Public dbcv_reserved As Int32
Public dbcv_unitmask As Int32
Public dbcv_flags As Int16
End Structure
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Try
If m.Msg = WM_DEVICECHANGE Then
Dim Volume As DEV_BROADCAST_VOLUME
Volume = DirectCast(Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_VOLUME)), DEV_BROADCAST_VOLUME)
If Not GetDriveLetterFromMask(Volume.dbcv_unitmask).ToString.Trim = String.Empty Then
Dim DriveLetter As String = (GetDriveLetterFromMask(Volume.dbcv_unitmask) & ":\")
Select Case m.WParam
Case WM_DEVICECHANGE_WPPARAMS.DBT_DEVICEARRIVAL
LblUSB.Text = DriveLetter
GetFiles()
MsgBox("Usb connected")
' Code When add USB
Case WM_DEVICECHANGE_WPPARAMS.DBT_DEVICEREMOVECOMPLETE
LblUSB.Text = ""
CheckedListBox1.Items.Clear()
MsgBox("Usb disconnected")
' Code When Remove USB
End Select
End If
End If
Catch ex As Exception
End Try
MyBase.WndProc(m)
End Sub
Private Function GetDriveLetterFromMask(ByRef Unit As Int32) As Char
For i As Integer = 0 To 25
If Unit = (2 ^ i) Then
Return Chr(Asc("A") i)
End If
Next
Return ""
End Function
#End Region
Sub GetFiles()
Try
Dim Path = LblUSB.Text
Dim LstFiles = My.Computer.FileSystem.GetFiles(Path, FileIO.SearchOption.SearchTopLevelOnly)
For Each File In LstFiles
Dim F As New IO.FileInfo(File)
CheckedListBox1.Items.Add(F.Name)
Next
Catch ex As Exception
End Try
End Sub
End Class
The System.NullReferenceException i get is at this point:
Volume = DirectCast(Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_VOLUME)), DEV_BROADCAST_VOLUME)
I did read that this error happens when the value is null and there should be a value associated, i tried different approaches but none did work and i hope that someone of you could give me a solution and an explaination to better understand that.
Thank you very much guys for the help!
CodePudding user response:
When one runs the code in VS 2019, beneath the System.NullReferenceException
it states: System.Runtime.InteropServices.Marshal.PtrToStructure(...) returned Nothing which occurs because m.LParam
is 0
. This can be observed by placing the following code just before the DirectCast statement:
Debug.WriteLine($"m.LParam: '{m.LParam.ToString()}'")
.
There isn't a need to attempt to get a drive letter until it's been detected that the USB device has been inserted. If one refactors the code as shown below, the issue doesn't occur:
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_DEVICECHANGE Then
Debug.WriteLine($"m.LParam: '{m.LParam.ToString()}'")
Select Case CInt(m.WParam)
Case WM_DEVICECHANGE_WPPARAMS.DBT_DEVICEARRIVAL
Debug.WriteLine($" DBT_DEVICEARRIVAL")
Dim Volume As DEV_BROADCAST_VOLUME
Volume = DirectCast(Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, GetType(DEV_BROADCAST_VOLUME)), DEV_BROADCAST_VOLUME)
If Not GetDriveLetterFromMask(Volume.dbcv_unitmask).ToString.Trim = String.Empty Then
Dim DriveLetter As String = (GetDriveLetterFromMask(Volume.dbcv_unitmask) & ":\")
LblUSB.Text = DriveLetter
GetFiles()
MsgBox("Usb connected")
' Code When add USB
End If
Case WM_DEVICECHANGE_WPPARAMS.DBT_DEVICEREMOVECOMPLETE
LblUSB.Text = ""
CheckedListBox1.Items.Clear()
MsgBox("Usb disconnected")
' Code When Remove USB
End Select
End If
MyBase.WndProc(m)
End Sub
A side note: It's recommended to enable Option Strict for your project.
Resources: