USB Überwachung, externer Cardreader

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Amelie.

    USB Überwachung, externer Cardreader

    Moin moin

    Ich habe hier eine Class, die soweit auch funktioniert. Ein kleines / großes Problem habe ich jedoch mit einem externen USB-CardReader.
    Stecke ich den kompletten Reader ein oder ziehe ihn ab, reagiert die Class wie sie soll. Die Events feuern.

    Ziehe ich aber nur die SD-Karte aus dem Reader, reagiert die Class nicht, ebenso beim einstecken. Die Events feuern nicht. :(
    Wie kann ich das lösen?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class USBListener
    2. Inherits NativeWindow
    3. Private Const WM_DEVICECHANGE As Integer = &H219
    4. Private Const DBT_DEVICEARRIVAL As Integer = &H8000
    5. Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
    6. Public Event USBEvent As EventHandler(Of USBEventArgs)
    7. Public Event TimerElapsed As EventHandler
    8. Private WithEvents timer As Timer
    9. Public Sub New()
    10. timer = New Timer()
    11. timer.Interval = 3000 ' 3 Sekunden
    12. timer.Enabled = False
    13. End Sub
    14. Public Sub StartMonitoring()
    15. Dim params As New CreateParams()
    16. Me.CreateHandle(params)
    17. End Sub
    18. Protected Overrides Sub WndProc(ByRef msg As Message)
    19. MyBase.WndProc(msg)
    20. Dim wParam = msg.WParam.ToInt32()
    21. If msg.Msg = WM_DEVICECHANGE Then
    22. If wParam = DBT_DEVICEARRIVAL Then
    23. RaiseEvent USBEvent(Me, New USBEventArgs(True))
    24. StartTimer()
    25. ElseIf wParam = DBT_DEVICEREMOVECOMPLETE Then
    26. RaiseEvent USBEvent(Me, New USBEventArgs(False))
    27. StartTimer()
    28. End If
    29. End If
    30. End Sub
    31. Private Sub StartTimer()
    32. timer.Stop()
    33. timer.Start()
    34. End Sub
    35. Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles timer.Tick
    36. timer.Stop()
    37. RaiseEvent TimerElapsed(Me, EventArgs.Empty)
    38. End Sub
    39. End Class
    40. Public Class USBEventArgs
    41. Inherits EventArgs
    42. Private _isInserted As Boolean
    43. Public ReadOnly Property IsInserted As Boolean
    44. Get
    45. Return _isInserted
    46. End Get
    47. End Property
    48. Public Sub New(isInserted As Boolean)
    49. _isInserted = isInserted
    50. End Sub
    51. End Class

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Probiere das einmal (ist von hier):

    VB.NET-Quellcode

    1. 'https://www.codeguru.com/dotnet/detecting-usb-devices-using-c/
    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. Private Const DBT_DEVTYP_VOLUME As Integer = &H2
    6. Protected Overrides Sub WndProc(ByRef msg As Message)
    7. MyBase.WndProc(msg)
    8. Dim wParam = msg.WParam.ToInt32()
    9. Dim devType = Marshal.ReadInt32(msg.LParam, 4)
    10. If msg.Msg = WM_DEVICECHANGE Then
    11. If wParam = DBT_DEVICEARRIVAL AndAlso devType = DBT_DEVTYP_VOLUME Then
    12. RaiseEvent USBEvent(Me, New USBEventArgs(True))
    13. StartTimer()
    14. ElseIf wParam = DBT_DEVICEREMOVECOMPLETE Then
    15. RaiseEvent USBEvent(Me, New USBEventArgs(False))
    16. StartTimer()
    17. End If
    18. End If
    19. End Sub
    @VB1963

    Moin moin und Danke.
    Jedoch klappt das nicht. Sobald ich starte, ( in der Entwicklungsumgebung ) popt das MainForm kurz auf und dann kommt die Fehlermeldung.
    Starte ich die exe-Datei, schreib mein logger das gleiche.

    12.12.2023 | 07:49:19 Ein Fehler ist aufgetreten! Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

    VB.NET-Quellcode

    1. Public Class frmMain
    2. Private WithEvents eventlogger As New Eventloger()
    3. Private WithEvents usbMonitor As New USBListener()
    4. Private WithEvents drivehelper As New DriveHelper()
    5. Private WithEvents progressbar As New Progbar()
    6. Public allDrives() As DriveInfo = DriveInfo.GetDrives()
    7. Private isCleaning As Boolean = False
    8. Public Sub New()
    9. AddHandler Application.ThreadException, AddressOf ExceptionHandlerForErrors
    10. AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf ExceptionHandlerForErrors
    11. AddHandler progressbar.PanelToggle, AddressOf UpdateProgbar
    12. progressbar.InitializePanels(Me)
    13. usbMonitor.StartMonitoring()
    14. InitializeComponent()
    15. ClearLabels()
    16. ListDrives()
    17. End Sub

    XML-Quellcode

    1. System.AccessViolationException wurde nicht behandelt.
    2. Message: Ein Ausnahmefehler des Typs "System.AccessViolationException" ist in mscorlib.dll aufgetreten.
    3. Zusätzliche Informationen: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

    [/spoiler]
    Bilder
    • error1.jpg

      754,44 kB, 1.737×957, 30 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @VB1963: Hast Du das selbst übersetzt?
    Zeile#9 und #10 müssen wohl getauscht werden, sonst wird bei jeglicher Nachricht versucht, mit einem Offset lParam auszuwerten, was zu genanntem Fehler führt - da manche lParam-Werte einfach Nullzeiger sein dürften. Oder auf Stellen zeigen, die kein Auslesen mit Offset erlauben.

    Daher mein Vorschlag (ungetestet):

    VB.NET-Quellcode

    1. Private Const WM_DEVICECHANGE As Integer = &H219
    2. Private Const DBT_DEVICEARRIVAL As Integer = &H8000
    3. Private Const DBT_DEVICEREMOVECOMPLETE As Integer = &H8004
    4. Private Const DBT_DEVTYP_VOLUME As Integer = &H2
    5. Protected 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. Dim devType = Marshal.ReadInt32(msg.LParam, 4)
    10. If wParam = DBT_DEVICEARRIVAL AndAlso devType = DBT_DEVTYP_VOLUME Then
    11. RaiseEvent USBEvent(Me, New USBEventArgs(True))
    12. StartTimer()
    13. ElseIf wParam = DBT_DEVICEREMOVECOMPLETE Then
    14. RaiseEvent USBEvent(Me, New USBEventArgs(False))
    15. StartTimer()
    16. End If
    17. End If
    18. End Sub

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Habe nun mal ein TestZip angehangen. Erstellt in VS 2015.

    Wie schon gesagt, handelt es sich um einen externen USB-CardReader. Das abziehen / einstecken des ganzen Reader funktioniert.
    Nur das abziehen der SD-Card wird nicht registriert. Im Windows Explorer schon!
    Dateien
    • TestUSBEvent.zip

      (19,62 kB, 183 mal heruntergeladen, zuletzt: )
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    VaporiZed schrieb:

    Hast Du das selbst übersetzt?
    Ja - leider ist mir beim zeilenweise Reinkopieren in ihrem Code dieser bedauerliche Fehler unterlaufen - hab's auch nicht getestet...
    @Amelie
    das war eine ungewollte C&P-Bremse...

    VB.NET-Quellcode

    1. Protected Overrides Sub WndProc(ByRef msg As Message)
    2. MyBase.WndProc(msg)
    3. Dim wParam = msg.WParam.ToInt32()
    4. If msg.Msg = WM_DEVICECHANGE Then
    5. If wParam = DBT_DEVICEARRIVAL AndAlso Marshal.ReadInt32(msg.LParam, 4) = DBT_DEVTYP_VOLUME Then
    6. RaiseEvent USBEvent(Me, New USBEventArgs(True))
    7. StartTimer()
    8. ElseIf wParam = DBT_DEVICEREMOVECOMPLETE Then
    9. RaiseEvent USBEvent(Me, New USBEventArgs(False))
    10. StartTimer()
    11. End If
    12. End If
    13. End Sub
    Das sollte jetzt ohne Fehler laufen...

    Ich habe gerade festgestellt, dass das nur mit USB funktioniert!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VB1963“ ()

    @VB1963
    Ja aber das brachte mich nicht weiter und ich verstand noch nicht viel.

    Das war das letzte was ich damals versuchte, was aber auch nicht funktionierte: :(
    Es wird zwar erkannt, wenn ich ganze USB-Geräte entferne / anschließe, aber das entfernen von "nur der SDCard" eben nicht.

    VB.NET-Quellcode

    1. Imports System.Management
    2. Public Class SDMonitor
    3. Private WithEvents watcher As ManagementEventWatcher
    4. Private query As WqlEventQuery
    5. Public Event SDInserted As EventHandler
    6. Public Event SDRemoved As EventHandler
    7. Public Sub StartMonitoring()
    8. query = New WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogicalDisk' AND TargetInstance.DriveType=2")
    9. watcher = New ManagementEventWatcher(query)
    10. watcher.Start()
    11. End Sub
    12. Public Sub StopMonitoring()
    13. If watcher IsNot Nothing Then
    14. watcher.Stop()
    15. watcher.Dispose()
    16. End If
    17. End Sub
    18. Private Sub watcher_EventArrived(sender As Object, e As EventArrivedEventArgs) Handles watcher.EventArrived
    19. Dim eventType As String = e.NewEvent.ClassPath.ClassName
    20. Dim instance As ManagementBaseObject = CType(e.NewEvent("TargetInstance"), ManagementBaseObject)
    21. If eventType.Equals("__InstanceCreationEvent") Then
    22. RaiseEvent SDInserted(Me, EventArgs.Empty)
    23. ElseIf eventType.Equals("__InstanceDeletionEvent") Then
    24. RaiseEvent SDRemoved(Me, EventArgs.Empty)
    25. End If
    26. End Sub
    27. End Class
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @VB1963

    Moin moin
    Nach erstem schnellem Test funktioniert das!
    Danke :thumbsup:

    Sehe da im Code einiges Interessante, was ich ggf für mein Projekt verwenden kann.
    Werde den Code mal intensive studieren. Habe da bestimmt viele Fragen zu. :)

    Nochmals Danke für die Überarbeitung.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh: