Automatische Laufwerkserkennung

    • Offizieller Beitrag

    Wenn man ein Programm schreibt, in dem man die zur Verfügung stehenden Laufwerke dem Benutzer zur Auswahl anbieten will, dann steht man vor dem Problem (während der Laufzeit des Scripts) eine Änderung der zur Verfügung stehenden Laufwerke mitzubekommen. Das könnte man einerseits so lösen, dass man eine Prüfroutine alle paar Sekunden aufruft oder (was ein besserer Weg ist) Windows anweisen, eine Funktion in unserem Script aufzurufen, wenn sich an der Laufwerksauswahl etwas ändert. Das Ganze kann man mit Hilfe von GUIRegisterMsg und $WM_DEVICECHANGE erreichen.
    Hier mal ein Beispiel:

    Spoiler anzeigen
    [autoit]


    #include <ComboConstants.au3>
    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $WM_DEVICECHANGE = 0x0219 ; Notifies an application of a change to the hardware configuration of a device or the computer.
    Global Const $DBT_DEVICEARRIVAL = 0x8000 ; A device or piece of media has been inserted and is now available.
    Global Const $DBT_DEVICEREMOVECOMPLETE = 0x8004 ; A device or piece of media has been removed.

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate('Automatische Laufwerkserkennung', 380, 200)
    GUICtrlCreateLabel('Laufwerke mit Datenträger:', 20, 30, 180, 20)
    $idDrivesReady = GUICtrlCreateCombo('', 20, 50, 120, 20, $CBS_DROPDOWNLIST)
    GUICtrlCreateLabel('Laufwerke ohne Datenträger:', 220, 30, 180, 20)
    $idDrivesNotReady = GUICtrlCreateCombo('', 220, 50, 120, 20, $CBS_DROPDOWNLIST)
    _ReadDrives()
    GUISetState()
    GUIRegisterMsg($WM_DEVICECHANGE, 'MY_WM_DEVICECHANGE')

    [/autoit] [autoit][/autoit] [autoit]

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    [/autoit] [autoit][/autoit] [autoit]

    Func MY_WM_DEVICECHANGE($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $lParam
    Switch $wParam
    Case $DBT_DEVICEARRIVAL
    ConsoleWrite('A device or piece of media has been inserted and is now available.' & @CR)
    _ReadDrives()
    Case $DBT_DEVICEREMOVECOMPLETE
    ConsoleWrite('A device or piece of media has been removed.' & @CR)
    _ReadDrives()
    EndSwitch
    Return $GUI_RUNDEFMSG
    EndFunc ;==>MY_WM_DEVICECHANGE

    [/autoit] [autoit][/autoit] [autoit]

    Func _ReadDrives()
    Local $aDrives, $sDrivesReady, $sDrivesNotReady, $sTmp
    GUICtrlSetData($idDrivesReady, '')
    GUICtrlSetData($idDrivesNotReady, '')
    $aDrives = DriveGetDrive('ALL')
    For $i = 1 To $aDrives[0]
    If DriveStatus($aDrives[$i]) = 'READY' Then
    $sDrivesReady &= '|' & StringUpper($aDrives[$i])
    $sTmp = DriveGetLabel($aDrives[$i])
    If $sTmp <> '' Then $sDrivesReady &= ' (' & $sTmp & ') '
    Else
    $sDrivesNotReady &= '|' & StringUpper($aDrives[$i])
    EndIf
    Next
    GUICtrlSetData($idDrivesReady, StringTrimLeft($sDrivesReady, 1), StringRegExpReplace($sDrivesReady, '\|(.+?)\|.*', '$1'))
    GUICtrlSetData($idDrivesNotReady, StringTrimLeft($sDrivesNotReady, 1), StringRegExpReplace($sDrivesNotReady, '\|(.+?)\|.*', '$1'))
    EndFunc ;==>_ReadDrives

    [/autoit]
  • Hi,

    Zitat

    Windows anweisen, eine Funktion in unserem Script aufzurufen,

    SO gehört sich das :thumbup:

  • Hallo Oscar, hallo Forum,

    ich habe ein Problem mit der aut. Laufwerkserkennung:
    USB-Cardreader anschließen - WM_DEVICECHANGE-Event wird "abgefeuert" und von der GUI verarbeitet, alles OK
    ABER: dann SD-Karte in den Reader einstecken / entfernen - WM_DEVICECHANGE-Event wird NICHT "abgefeuert" (oder NICHT von der GUI verarbeitet?)
    Das Ganze unter Windows 7. Hat jemand eine Idee wie ich dieses Problem lösen kann?

    VG Jens

    • Offizieller Beitrag

    Das Problem ist ja, dass bereits den einzelnen Slots des Cardreaders ein Laufwerksbuchstabe zugewiesen wird.
    Für Windows sind das 1, 2, 3 oder 4 Laufwerke (je nach Cardreader). Das einstecken der SD-Karte wird dann gar nicht mehr als Laufwerkswechsel erkannt.
    Wie man jetzt (ohne ständig den Laufwerkstyp abzufragen) trotzdem eine Nachricht von Windows bekommen kann, entzieht sich meiner Kenntnis.

  • ggf über den DriveStatus().
    Man könnte/sollte sämtlichche DriveXxxx()-Funktionen auf nützlichkeiten untersuchen. Was ich weiß ist, dass Events ausgelöst werden wenn sich auf einem Laufwerk Daten ändern, AspirinJunkie hatte da mal etwas... Geschrieben abfragen

    • Offizieller Beitrag

    In der WinAPI-UDF gibt es ja mittlerweile auch "_WinAPI_ShellChangeNotifyRegister", womit auf Veränderungen reagiert werden kann, aber das funktioniert nur mit Laufwerken, die den Status "READY" haben.
    Versucht man dort den Laufwerksbuchstaben eines Cardreaders ohne eingesteckte Karte zu registrieren, schlägt die Funktion fehl.

    Man könnte natürlich in regelmäßigen Abständen den DriveStatus aller Laufwerke überprüfen, aber das ist ja eben nicht erwünscht. :huh:

  • Wow, ihr seid ja echt fix :thumbup:
    @Andy :das mit dem DriveStatus hatte ich vorher schon versucht - in einer Schleife - das will ich aber nicht. Das von AspirinJunkie schaue ich mir gleich mal genauer an...
    @Oscar :auf die _WinAPI_ShellChangeNotifyRegister-Methode bin ich beim Googeln auch gestoßen. Ich hab's nur nicht zum Laufen bekommen. Dank deines Hinweises: 'nur Status "READY"' weiß ich jetzt auch warum.

    Hat sich erledigt: Mit _WinAPI_ShellChangeNotifyRegister bekomme ich jetzt alle Events und muss nur noch nach dem richtigen filtern. Danke Oscar

    VG Jens

    Einmal editiert, zuletzt von heje8162 (18. September 2015 um 09:38)