Erkennen, wann ein Laufwerk hinzugefügt bzw. entfernt wurde (USB-Stick)

    • VB.NET

    Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von lupo76.

      Erkennen, wann ein Laufwerk hinzugefügt bzw. entfernt wurde (USB-Stick)

      Hallo,

      wie kann man erkennen ob ein USB-Stick eingesteckt bzw. entfernt wurde ohne einen Timer verwenden zu müssen.

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class Form1
      3. Private allDrives As New List(Of DriveInfo)
      4. Private Const WM_DEVICECHANGE As Integer = &H219
      5. Private Const DBT_DEVICEARRIVAL As Integer = &H8000
      6. Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
      7. Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
      8. MyBase.WndProc(msg)
      9. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = DBT_DEVICEARRIVAL Then
      10. 'alle laufwerke durchlaufen und in der liste suchen
      11. For Each s As String In Directory.GetLogicalDrives
      12. find_driveinfo_arg = s
      13. Dim d As DriveInfo = allDrives.Find(AddressOf find_driveinfo)
      14. If d Is Nothing Then
      15. 'laufwerk wurde in der liste nicht gefunden und ist somit neu
      16. MessageBox.Show("Neuer Datenträger erkannt = " & s)
      17. 'laufwerk jetzt zur liste hinzufügen
      18. allDrives.Add(New DriveInfo(s))
      19. End If
      20. Next
      21. End If
      22. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = DBT_DEVICEREMOVECOMPLETE Then
      23. 'alle laufwerke aus der liste prüfen
      24. Dim temp As List(Of DriveInfo) = GetAllDrives()
      25. For Each d As DriveInfo In allDrives
      26. find_driveinfo_arg = d.Name
      27. Dim lost As DriveInfo = temp.Find(AddressOf find_driveinfo)
      28. If lost Is Nothing Then
      29. 'laufwerk wurde in der liste nicht mehr gefunden
      30. MessageBox.Show("Datenträger wurde entfernt = " & d.Name)
      31. 'laufwerk aus der liste entfernen
      32. allDrives.Remove(d)
      33. 'schleife verlassen
      34. Exit For
      35. End If
      36. Next
      37. End If
      38. End Sub
      39. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      40. allDrives = GetAllDrives()
      41. End Sub
      42. Private Function GetAllDrives() As List(Of DriveInfo)
      43. Dim ret As New List(Of DriveInfo)
      44. 'und wieder befüllen
      45. For Each d As String In Directory.GetLogicalDrives
      46. ret.Add(New DriveInfo(d))
      47. Next
      48. Return ret
      49. End Function
      50. 'suchfunktion zum finden der laufwerke in der collection
      51. Private find_driveinfo_arg As String
      52. Private Function find_driveinfo(ByVal d As DriveInfo)
      53. If d.Name = find_driveinfo_arg Then
      54. Return True
      55. Else
      56. Return False
      57. End If
      58. End Function
      59. End Class

      Kommentare erwünscht

      EDIT:
      Laufwerksbuchstabe wird nun ausgegeben (beim Hinzufügen und Entfernen des Laufwerks)

      Gruss

      mikeb69

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „mikeb69“ ()

      Bei AndAlso wird der 2te Teil nur ausgeführt, wenn der 1te Teil bereits wahr ist. Das ganze ist quasi eine Optimierung im Quelltext, weil man sich u.U. den 2ten Teil spart. AndAlso hat also das gleiche Verhalten wie das "normale" && in C/C++.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Mad Andy“ ()

      Ich dachte das ist damit man die Variable nicht ständig wiederholen muss:

      VB.NET-Quellcode

      1. If Var = 1 Or Var = 2 Then
      2. If Var = 1 OrElse 2 Then
      Gruß, Agent Smith 8-)

      activeFlags = (lazy OR weary)

      Lemgo-Verschwörung | Mathematics | VB-Paradise in blau
      Hier ist das ganze noch ausführlicher, also auch mit Laufwerksbuchstaben:
      Hinzufügen und Entfernen von USB-Wechselmedien erkennen
      Gruß, Agent Smith 8-)

      activeFlags = (lazy OR weary)

      Lemgo-Verschwörung | Mathematics | VB-Paradise in blau
      hallo denny
      hallo agent,

      ich hab den code ein wenig umgebaut, sodass man die driveinfo des laufwerks erhält.
      aus der driveinfo kann man dann den laufwerkstyp, laufwerksbuchstabe usw. auslesen

      gruss

      mikeb69
      Auch wenn das Thema schon recht alt ist, habe ich das zwecks Ausbau nochmal neu aufgegriffen:
      Dank der Hilfe von Mikeb69 ist es mir gelungen, sein Beispiel so in eine Klasse zu verpacken, dass man nur noch das Handle übergeben muß, um an die WindowsMesage zu kommen.
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class ClsDrivewatcher
      3. Inherits System.Windows.Forms.NativeWindow
      4. 'Konstanten für Windowsmessages
      5. Private Const WM_DEVICECHANGE As Integer = &H219
      6. Private Const DBT_DEVICEARRIVAL As Integer = &H8000
      7. Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
      8. 'Events
      9. Public Event WinProc(ByVal sender As ClsDrivewatcher, ByRef m As Message)
      10. Public Event Drive_Neu(ByVal DI As DriveInfo)
      11. Public Event Drive_entfernt(ByVal DN As String)
      12. Private allDrives As New List(Of DriveInfo)
      13. Public Sub New(ByVal Handle As IntPtr)
      14. 'übergibt dem NativeWindow das Handle
      15. MyBase.AssignHandle(Handle)
      16. 'Listet alle Laufwerke in allDrives
      17. allDrives = GetAllDrives()
      18. End Sub
      19. 'Ausgabemöglichkeit für Laufwerkliste
      20. Public Function Getdrives() As List(Of DriveInfo)
      21. Return allDrives
      22. End Function
      23. 'WinProc-Methode des übergebenen Handles
      24. Protected Overrides Sub WndProc(ByRef msg As Message)
      25. 'gibt die OriginalMessage an übergebenes Handles weiter
      26. MyBase.WndProc(msg)
      27. 'Event für externe Auswertung der Message
      28. RaiseEvent WinProc(Me, msg)
      29. 'Wenn ein Laufwerk gewechselt und ein neues Laufwerk erkannt wurde
      30. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEARRIVAL, IntPtr) Then
      31. 'alle laufwerke durchlaufen und in der liste suchen
      32. For Each s As String In Directory.GetLogicalDrives
      33. find_driveinfo_arg = s
      34. Dim d As DriveInfo = allDrives.Find(AddressOf find_driveinfo)
      35. If d Is Nothing Then
      36. d = New DriveInfo(s)
      37. 'laufwerk wurde in der liste nicht gefunden und ist somit neu
      38. 'MessageBox.Show("Neuer Datenträger erkannt = " & d.Name)
      39. 'laufwerk jetzt zur liste hinzufügen
      40. allDrives.Add(d)
      41. 'Event auslösen
      42. RaiseEvent Drive_Neu(d)
      43. End If
      44. Next
      45. End If
      46. 'Wenn ein Laufwerk gewechselt und ein Laufwerk entfernt wurde
      47. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEREMOVECOMPLETE, IntPtr) Then
      48. 'alle laufwerke aus der liste prüfen
      49. Dim temp As List(Of DriveInfo) = GetAllDrives()
      50. For Each d As DriveInfo In allDrives
      51. find_driveinfo_arg = d.Name
      52. Dim lost As DriveInfo = temp.Find(AddressOf find_driveinfo)
      53. If lost Is Nothing Then
      54. 'laufwerk wurde in der liste nicht mehr gefunden
      55. 'MessageBox.Show("Datenträger wurde entfernt = " & d.Name)
      56. 'Event auslösen
      57. RaiseEvent Drive_entfernt(d.Name)
      58. 'laufwerk aus der liste entfernen
      59. allDrives.Remove(d)
      60. 'schleife verlassen
      61. Exit For
      62. End If
      63. Next
      64. End If
      65. End Sub
      66. 'Funktion zum Auflisten der Laufwerke
      67. Private Function GetAllDrives() As List(Of DriveInfo)
      68. Dim ret As New List(Of DriveInfo)
      69. 'und wieder befüllen
      70. For Each d As String In Directory.GetLogicalDrives
      71. ret.Add(New DriveInfo(d))
      72. Next
      73. Return ret
      74. End Function
      75. 'suchfunktion zum finden der laufwerke in der collection
      76. Private find_driveinfo_arg As String
      77. Private Function find_driveinfo(ByVal d As DriveInfo) As Boolean
      78. If d.Name = find_driveinfo_arg Then
      79. Return True
      80. Else
      81. Return False
      82. End If
      83. End Function
      84. End Class
      Die Klasse kann nun einfach wie im folgenden Beispiel instanziert werden und bietet Events für die Rückmeldung Laufwerk hinzugefügt/entfernt.
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class Testform
      3. 'Instanzierung mit Fensterhandle
      4. Dim Drivewatcher As New ClsDrivewatcher(Me.Handle)
      5. Private Sub Testform_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      6. 'Events adden
      7. AddHandler Drivewatcher.Drive_Neu, AddressOf LW_erkannt
      8. AddHandler Drivewatcher.Drive_entfernt, AddressOf LW_entfernt
      9. End Sub
      10. 'Event Laufwerk neu
      11. Private Sub LW_erkannt(ByVal DI As DriveInfo)
      12. Debug.WriteLine(String.Format("Laufwerk {0}:\ wurde hinzugefügt, Label = {1} ", DI.Name, DI.VolumeLabel))
      13. Debug.WriteLine(String.Format("Type: {0};frei: {1} von {2}", DI.DriveType, DI.TotalFreeSpace, DI.TotalSize))
      14. End Sub
      15. 'Event Laufwerk entfernt
      16. Private Sub LW_entfernt(ByVal Name As String)
      17. Debug.WriteLine(String.Format("Laufwerk {0}:\ wurde entfernt ", Name))
      18. End Sub
      19. End Class
      Damit wird dann der Form-Code nicht mehr so zugemüllt.
      :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
      Dieser Code hat mich interessiert, aber leider funktioniert er bei mir nicht. Ich bei den Abfragen einen Haltepunkt gesetzt, der USB-Stick angesteckt und angesteckt. Aber keiner der Haltepunkt hat angeschlagen. Ich verwende den haargleichen Code von @mikeb69
      Grüße,
      Lukas

      Fragen über Themen im Forum per Konversation werden gelöscht und die Absender blockiert...
      Bei mir funktioniert der Code, nachdem ich 3 kleine Änderungen vorgenommen habe (ich habe grundsätzlich "STRICT ON":

      Neue Zeile 13:

      VB.NET-Quellcode

      1. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEARRIVAL, IntPtr) Then


      Neue Zeile 26:

      VB.NET-Quellcode

      1. If msg.Msg = WM_DEVICECHANGE AndAlso msg.WParam = CType(DBT_DEVICEREMOVECOMPLETE, IntPtr) Then


      Neue Zeile 59:

      VB.NET-Quellcode

      1. Private Function find_driveinfo(ByVal d As DriveInfo) As Boolean


      Beim Einstecken eines USB-Sticks erfolgt sofort eine Meldung mit Laufwerksangabe. Beim Abmelden des Sticks (Gerät entfernen) erfolgt korrekt die Meldung:"Datenträger wurde entfernt = F:\"
      Das Leben ist nicht so kompliziert. Eine süsse Erinnerung tut's.
      Indiana Jocutus - Jäger des Variablen-Schatzes
      Moin,

      ich weiß das das Thema schon alt ist ;) aber es ist genau das was ich benötige .
      Das Script funktioniert für USB super!

      Hat jemand einen Tipp wie ich es erweitern kann bzw was ich ändern müsste damit auch eine SC-Card (Anschluß über einen USB Card-Reader) erkannt wird ?


      VG
      Lupo
      @lupo76 Willkommen im Forum. :thumbup:
      Der Code erkennt zunächst mal eine ganze Menge, die Kunst besteht darin, das, was man nicht sehen will, gar nicht erst zuzulassen.
      Teste mit diesem Code (Form, RichTextBox):

      VB.NET-Quellcode

      1. Public Class Form1
      2. Private Const WM_DEVICECHANGE As Integer = &H219
      3. Private Const DBT_DEVICEARRIVAL As Integer = &H8000
      4. Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
      5. Protected Overloads Overrides Sub WndProc(ByRef msg As Message)
      6. MyBase.WndProc(msg)
      7. Dim wParam = msg.WParam.ToInt32()
      8. If msg.Msg = WM_DEVICECHANGE Then
      9. If wParam = DBT_DEVICEARRIVAL Then
      10. Me.RichTextBox1.AppendText("Neues Gerät" & Environment.NewLine)
      11. ElseIf wParam = DBT_DEVICEREMOVECOMPLETE Then
      12. Me.RichTextBox1.AppendText("Gerät abgezogen" & Environment.NewLine)
      13. End If
      14. End If
      15. End Sub
      16. End Class
      =======================
      @mikeb69 Dein Code ist Strict Off ;)
      Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
      Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
      Ein guter .NET-Snippetkonverter (der ist verfügbar).
      Programmierfragen über PN / Konversation werden ignoriert!
      Wow, danke für die schnelle Antwort!
      Leider löst es mein Problem nicht.
      Da der Card-Reader am PC bleibt scheint des kein Event (oder ein anderes?) mehr zu geben was sagt SD-Card eingesteckt bzw entfernt.

      Wenn ich die SD-Card inkl. Card-Reader einstecke und entferne funktionieren die Scripte.