none
VB.Net 如何卸除USB裝置 RRS feed

  • 問題

  • 各位先進好
    我用VB2005進行程式編輯
    練習抽取式磁碟的讀取與卸除
    讀取的部分已經完成,但卸除卻花了較多的時間,在網路上爬文大多是說明如何讀取訊息

    讀取我是使用DriveInfo 類別完成。

    想請教我要如何做才能達到卸除抽取式磁碟機的功能。

    2012年4月18日 上午 09:42

解答

所有回覆

  • 或許你可以參考這篇既有的討論。

    http://social.msdn.microsoft.com/Forums/zh-TW/232/thread/3eb332a8-bda7-4d50-a81f-d2af9312aa60/


    以上說明若有錯誤請指教,謝謝。
    http://www.dotblogs.com.tw/terrychuang/

    2012年4月18日 上午 09:49
  • 您可以參考這個範例:USB Safe Eject [VB.NET]
    2012年4月18日 上午 11:47
  • tihs 您好

    我有用過Process.Start的方式卸除USB,不過卸除時都會跑出對話匡,如下:

    Process.Start("RUNDLL32.exe", "SHELL32.dll,Control_RunDLL hotplug.dll")

    您給的那篇範例,可以執行,不過執行起來感覺有點複雜

    我用單步執行發現,他的BusDeviceID也會掃瞄到ACPI或ROOT等

    而卸除USB會一次卸除全部,若要針對單一USB個別卸除,該怎麼修改才可以達到這樣的功能?

    2012年4月19日 上午 08:21
  • 各位大大好

    我參考這個範例:USB Safe Eject [VB.NET]

    	Public Sub EjectUsbDrive(ByVal DriveLetter As String)
    		Dim GUID_DEVINTERFACE_VOLUME As Guid = New Guid(&H53F5630D, &HB6BF, &H11D0, &H94, &HF2, &H0, &HA0, &HC9, &H1E, &HFB, &H8B)
    		Dim hDevInfo As Integer = SetupDiGetClassDevs(GUID_DEVINTERFACE_VOLUME, IntPtr.Zero, 0, DIGCF_PRESENT + DIGCF_DEVICEINTERFACE)
    		If hDevInfo <> INVALID_HANDLE_VALUE Then
    			Dim MemberIndex As Integer = 0
    			Dim did As New SP_DEVINFO_DATA
    			did.cbSize = Marshal.SizeOf(did)
    			Dim didPtr As IntPtr = Marshal.AllocHGlobal(did.cbSize)
    			Marshal.StructureToPtr(did, didPtr, True)
    			While SetupDiEnumDeviceInfo(hDevInfo, MemberIndex, didPtr) <> 0
    				Marshal.PtrToStructure(didPtr, did)
    				Console.WriteLine(did.DevInst & ": " & GetDeviceID(hDevInfo, didPtr) & "\")
    				Console.WriteLine("Mounted volume: " & GetVolumeName(hDevInfo, did))
    				Dim pDevInst As Integer
    				CM_Get_Parent(pDevInst, did.DevInst, 0)
    				Console.WriteLine(vbTab & pDevInst & ": " & GetDeviceID(pDevInst))
    				CM_Get_Parent(pDevInst, pDevInst, 0)
    				Dim BusDeviceID As String = GetDeviceID(pDevInst)
    				Console.WriteLine(vbTab & vbTab & pDevInst & ": " & BusDeviceID)
    				If BusDeviceID.StartsWith("USB\") Then
    					Console.WriteLine("Requesting USB drive removal...")
    					If CM_Request_Device_Eject(pDevInst, IntPtr.Zero, IntPtr.Zero, 0, 0) = 0 Then
    						Console.WriteLine("*** It's now safe to remove your USB drive")
    					Else
    						Console.WriteLine("*** Request failed!")
    					End If
    				End If
    				MemberIndex += 1
    				Console.WriteLine()
    			End While
    			Marshal.FreeHGlobal(didPtr)
    			SetupDiDestroyDeviceInfoList(hDevInfo)
    		End If
    	End Sub
    	Public Function GetDeviceID(ByVal hDevInfo As Integer, ByVal didPtr As IntPtr) As String
    		Dim DeviceID As String = ""
    		Dim idPtr As IntPtr = Marshal.AllocHGlobal(1024)
    		If SetupDiGetDeviceInstanceId(hDevInfo, didPtr, idPtr, 1024, IntPtr.Zero) <> 0 Then
    			Try
    				DeviceID = Marshal.PtrToStringAnsi(idPtr, 1024)
    				DeviceID = Left(DeviceID, InStr(DeviceID, Chr(0)) - 1)
    			Catch ex As Exception
    			End Try
    		End If
    		Marshal.FreeHGlobal(idPtr)
    		Return DeviceID
    	End Function
    	Public Function GetDeviceID(ByVal DevInst As Integer) As String
    		Dim ReqLen As Integer
    		Dim DeviceID As String = "???"
    		If CM_Get_Device_ID_Size(ReqLen, DevInst, 0) = 0 Then
    			Dim idPtr As IntPtr = Marshal.AllocHGlobal(ReqLen + 1)
    			If CM_Get_Device_ID(DevInst, idPtr, ReqLen + 1, 0) = 0 Then
    				Try
    					DeviceID = Marshal.PtrToStringAnsi(idPtr, 1024)
    					DeviceID = Left(DeviceID, InStr(DeviceID, Chr(0)) - 1)
    				Catch ex As Exception
    				End Try
    			End If
    			Marshal.FreeHGlobal(idPtr)
    		End If
    		Return DeviceID
    	End Function

    其中下面片段可以透過USB的VID以及PID判斷要卸除哪一個USB的裝置

                    Dim BusDeviceID As String = GetDeviceID(pDevInst)
                    Console.WriteLine(vbTab & vbTab & pDevInst & ": " & BusDeviceID)
                    If BusDeviceID.StartsWith("USB\") Then
                        Console.WriteLine("Requesting USB drive removal...")
                        If CM_Request_Device_Eject(pDevInst, IntPtr.Zero, IntPtr.Zero, 0, 0) = 0 Then
                            Console.WriteLine("*** It's now safe to remove your USB drive")
                        Else
                            Console.WriteLine("*** Request failed!")
                        End If
                    End If


    Dim BusDeviceID As String = GetDeviceID(pDevInst)

    程式執行到上面那一行可以取得USB裝置的VID以及PID

    而我直接把程式片段移到ListBox事件中

    但最後回傳的卻是"???",是那個環節出問題了嗎?

    	Private Sub ListBox1_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDoubleClick
    		Dim GUID_DEVINTERFACE_VOLUME As Guid = New Guid(&H53F5630D, &HB6BF, &H11D0, &H94, &HF2, &H0, &HA0, &HC9, &H1E, &HFB, &H8B)
    		Dim hDevInfo As Integer = SetupDiGetClassDevs(GUID_DEVINTERFACE_VOLUME, IntPtr.Zero, 0, DIGCF_PRESENT + DIGCF_DEVICEINTERFACE)
    		Dim MemberIndex As Integer = 0
    		Dim did As New SP_DEVINFO_DATA
    		did.cbSize = Marshal.SizeOf(did)
    		Dim didPtr As IntPtr = Marshal.AllocHGlobal(did.cbSize)
    		Marshal.StructureToPtr(did, didPtr, True)
    		Marshal.PtrToStructure(didPtr, did)
    		Console.WriteLine("Mounted volume: " & GetVolumeName(hDevInfo, did))
    		Dim pDevInst As Integer
    		CM_Get_Parent(pDevInst, did.DevInst, 0)
    		CM_Get_Parent(pDevInst, pDevInst, 0)
    		Dim BusDeviceID As String = GetDeviceID(pDevInst)
    		If ListBox1.SelectedIndex = 4 Then
    			EjectUsbDrive("USB\")
    		End If
    	End Sub



    2012年4月25日 上午 10:02