PDA

Click to See Complete Forum and Search --> : Safely Remove USB Flash Drive


Ellis Dee
Jun 22nd, 2008, 11:38 AM
Thanks to rm_03 for linking this solution. I pared down the German code to the barest essentials. This will be included in my XP library next time I update it, but until then:Option Explicit

Private Declare Function CM_Get_DevNode_Status Lib "setupapi.dll" (lStatus As Long, lProblem As Long, ByVal hDevice As Long, ByVal dwFlags As Long) As Long
Private Declare Function CM_Get_Parent Lib "setupapi.dll" (hParentDevice As Long, ByVal hDevice As Long, ByVal dwFlags As Long) As Long
Private Declare Function CM_Locate_DevNodeA Lib "setupapi.dll" (hDevice As Long, ByVal lpDeviceName As Long, ByVal dwFlags As Long) As Long
Private Declare Function CM_Request_Device_EjectA Lib "setupapi.dll" (ByVal hDevice As Long, lVetoType As Long, ByVal lpVetoName As Long, ByVal cbVetoName As Long, ByVal dwFlags As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpszValueName As String, ByVal lpdwReserved As Long, lpdwType As Long, lpData As Any, lpcbData As Long) As Long

' Safely remove USB flash drive
Public Function SafelyRemove(ByVal pstrDrive As String) As Boolean
Const DN_REMOVABLE = &H4000
Dim strDeviceInstance As String
Dim lngDevice As Long
Dim lngStatus As Long
Dim lngProblem As Long
Dim lngVetoType As Long
Dim strVeto As String * 255

pstrDrive = UCase$(Left$(pstrDrive, 1)) & ":"
strDeviceInstance = StrConv(GetDeviceInstance(pstrDrive), vbFromUnicode)
If CM_Locate_DevNodeA(lngDevice, StrPtr(strDeviceInstance), 0) = 0 Then
If CM_Get_DevNode_Status(lngStatus, lngProblem, lngDevice, 0) = 0 Then
Do While Not (lngStatus And DN_REMOVABLE) > 0
If CM_Get_Parent(lngDevice, lngDevice, 0) <> 0 Then Exit Do
If CM_Get_DevNode_Status(lngStatus, lngProblem, lngDevice, 0) <> 0 Then Exit Do
Loop
If (lngStatus And DN_REMOVABLE) > 0 Then SafelyRemove = (CM_Request_Device_EjectA(lngDevice, lngVetoType, StrPtr(strVeto), 255, 0) = 0)
End If
End If
End Function

Private Function GetDeviceInstance(pstrDrive As String) As String
Const HKEY_LOCAL_MACHINE = &H80000002
Const KEY_QUERY_VALUE = &H1
Const REG_BINARY = &H3
Const ERROR_SUCCESS = 0&
Dim strKey As String
Dim strValue As String
Dim lngHandle As Long
Dim lngType As Long
Dim strBuffer As String
Dim lngLen As Long
Dim bytArray() As Byte

strKey = "SYSTEM\MountedDevices"
strValue = "\DosDevices\" & pstrDrive
If RegOpenKeyEx(HKEY_LOCAL_MACHINE, strKey, 0&, KEY_QUERY_VALUE, lngHandle) = ERROR_SUCCESS Then
If RegQueryValueEx(lngHandle, strValue, 0&, lngType, 0&, lngLen) = 234 Then
If lngType = REG_BINARY Then
strBuffer = Space$(lngLen)
If RegQueryValueEx(lngHandle, strValue, 0&, 0&, ByVal strBuffer, lngLen) = ERROR_SUCCESS Then
If lngLen > 0 Then
ReDim bytArray(lngLen - 1)
bytArray = Left$(strBuffer, lngLen)
strBuffer = StrConv(bytArray, vbFromUnicode)
Erase bytArray
If Left$(strBuffer, 4) = "\??\" Then
strBuffer = Mid$(strBuffer, 5, InStr(1, strBuffer, "{") - 6)
GetDeviceInstance = Replace(strBuffer, "#", "\")
End If
End If
End If
End If
End If
RegCloseKey lngHandle
End If
End FunctionSample usage:If SafelyRemove("F:") Then
MsgBox "Safe to remove", vbInformation, "Notice"
End If

we0038
May 17th, 2009, 08:04 PM
Dear Ellis Dee and Others,
It been a month for me searching for how to safely remove USB drive using VB.net. I found no place better than vbforums.com for VB.net. So, thank you all for everything your doing here.

Ellis Dee, the code above looks very neat code :) but for some reason I can't get it run. I use VB express 2008 and it gives errors which you can see in RED:

Private Declare Function CM_Get_DevNode_Status Lib "setupapi.dll" (lStatus As Long, lProblem As Long, ByVal hDevice As Long, ByVal dwFlags As Long) As Long
Private Declare Function CM_Get_Parent Lib "setupapi.dll" (hParentDevice As Long, ByVal hDevice As Long, ByVal dwFlags As Long) As Long
Private Declare Function CM_Locate_DevNodeA Lib "setupapi.dll" (hDevice As Long, ByVal lpDeviceName As Long, ByVal dwFlags As Long) As Long
Private Declare Function CM_Request_Device_EjectA Lib "setupapi.dll" (ByVal hDevice As Long, lVetoType As Long, ByVal lpVetoName As Long, ByVal cbVetoName As Long, ByVal dwFlags As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpszValueName As String, ByVal lpdwReserved As Long, lpdwType As Long, lpData As Any, lpcbData As Long) As Long

' Safely remove USB flash drive
Public Function SafelyRemove(ByVal pstrDrive As String) As Boolean
Const DN_REMOVABLE = &H4000
Dim strDeviceInstance As String
Dim lngDevice As Long
Dim lngStatus As Long
Dim lngProblem As Long
Dim lngVetoType As Long
Dim strVeto As String * 255

pstrDrive = UCase$(Left$(pstrDrive, 1)) & ":"
strDeviceInstance = StrConv(GetDeviceInstance(pstrDrive), vbFromUnicode)
If CM_Locate_DevNodeA(lngDevice, StrPtr(strDeviceInstance), 0) = 0 Then
If CM_Get_DevNode_Status(lngStatus, lngProblem, lngDevice, 0) = 0 Then
Do While Not (lngStatus And DN_REMOVABLE) > 0
If CM_Get_Parent(lngDevice, lngDevice, 0) <> 0 Then Exit Do
If CM_Get_DevNode_Status(lngStatus, lngProblem, lngDevice, 0) <> 0 Then Exit Do
Loop
If (lngStatus And DN_REMOVABLE) > 0 Then SafelyRemove = (CM_Request_Device_EjectA(lngDevice, lngVetoType, StrPtr(strVeto), 255, 0) = 0)
End If
End If
End Function

Private Function GetDeviceInstance(pstrDrive As String) As String
Const HKEY_LOCAL_MACHINE = &H80000002
Const KEY_QUERY_VALUE = &H1
Const REG_BINARY = &H3
Const ERROR_SUCCESS = 0&
Dim strKey As String
Dim strValue As String
Dim lngHandle As Long
Dim lngType As Long
Dim strBuffer As String
Dim lngLen As Long
Dim bytArray() As Byte

strKey = "SYSTEM\MountedDevices"
strValue = "\DosDevices\" & pstrDrive
If RegOpenKeyEx(HKEY_LOCAL_MACHINE, strKey, 0&, KEY_QUERY_VALUE, lngHandle) = ERROR_SUCCESS Then
If RegQueryValueEx(lngHandle, strValue, 0&, lngType, 0&, lngLen) = 234 Then
If lngType = REG_BINARY Then
strBuffer = Space$(lngLen)
If RegQueryValueEx(lngHandle, strValue, 0&, 0&, ByVal strBuffer, lngLen) = ERROR_SUCCESS Then
If lngLen > 0 Then
ReDim bytArray(lngLen - 1)
bytArray = Left$(strBuffer, lngLen)
strBuffer = StrConv(bytArray, vbFromUnicode)
Erase bytArray
If Left$(strBuffer, 4) = "\??\" Then
strBuffer = Mid$(strBuffer, 5, InStr(1, strBuffer, "{") - 6)
GetDeviceInstance = Replace(strBuffer, "#", "\")
End If
End If
End If
End If
End If
RegCloseKey lngHandle
End If
End Function

I'm totally a beginner in VB all I need is to make this code works as it should be.

thank you very much.

Ellis Dee
May 21st, 2009, 09:39 PM
This is VB6 code. You need .NET code.

SNIPER.PS
Jan 10th, 2010, 04:18 AM
thanks

whitefloux90
Aug 29th, 2010, 06:07 AM
:thumbs:

ThePiper
Nov 2nd, 2010, 09:02 AM
Thanks Ellis; Well done! :wave:

Nightwalker83
Nov 2nd, 2010, 05:42 PM
@ Ellis Dee

Could you modify the above source to detect which processes are still using the usb device if any before running the above code? If so how?

Ellis Dee
Nov 2nd, 2010, 06:03 PM
That's beyond my ability. I'd recommend posting a question in the main forum asking how to identify which processes are using a flash drive. I could name at least a couple people still posting who might have the expertise.

Nightwalker83
Nov 2nd, 2010, 06:33 PM
That's beyond my ability. I'd recommend posting a question in the main forum asking how to identify which processes are using a flash drive. I could name at least a couple people still posting who might have the expertise.

I have started a new thread in the Visual Basic 6 section on the subject.

whitefloux90
Nov 21st, 2010, 11:11 AM
so which 1 is an updated code?