Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0718: USB Medium abmelden (sicheres Entfernen)

 von 

Beschreibung 

Dieses Beispiel zeigt wie ein USB-Medium (USB-Sticks, USB-Festplatten und andere USB-Massenspeicher) sicher vom System abgemeldet und ausgeworfen werden kann, wie dies in Windows von der Funktion "Hardware sicher entfernen" bekannt ist.

Schwierigkeitsgrad:

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

CM_Get_DevNode_Status, CM_Get_Parent, CM_Locate_DevNodeA, CM_Request_Device_EjectA, CloseHandle, CreateFileA (CreateFile), DeviceIoControl, GetDriveTypeA (GetDriveType), GetLogicalDrives, IIDFromString, QueryDosDeviceA (QueryDosDevice), SetupDiDestroyDeviceInfoList, SetupDiEnumDeviceInterfaces, SetupDiGetClassDevsA (SetupDiGetClassDevs), SetupDiGetDeviceInterfaceDetailA (SetupDiGetDeviceInterfaceDetail)

Download:

Download des Beispielprojektes [6,31 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'----------- Anfang Projektdatei SaveUsbEject.vbp -----------
'------- Anfang Formular "frmMain" alias frmMain.frm  -------
' Steuerelement: Schaltfläche "cmdEject"
' Steuerelement: Kombinationsliste "cbDrive"
Option Explicit

' ----==== KERNEL32 Deklarationen ====----
Private Declare Function GetLogicalDrives Lib "kernel32" () As Long

Private Sub cmdEject_Click()

    Dim strDriveLetter As String
    
    ' sind Einträge in der ComboBox vorhanden
    If cbDrive.ListCount > 0 Then
    
        ' Laufwerksbuchstaben auslesen
        strDriveLetter = Chr$(65 + cbDrive.ItemData(cbDrive.ListIndex))
        
        ' Laufwerk auswerfen
        If EjectUsbDrive(strDriveLetter, True) Then
        
            MsgBox "Laufwerk '" & strDriveLetter & ":\' wurde " & _
                "erfolgreich enfernt.", vbOKOnly Or vbInformation
                
            ' alle auswerfbare Laufwerke ermitteln
            Call ListRemovableDrives
                
        Else
        
            MsgBox "Laufwerk '" & strDriveLetter & ":\' konnte nicht " & _
                "enfernt werden.", vbOKOnly Or vbExclamation
                
        End If
    End If
    
End Sub

Private Sub ListRemovableDrives()

    Dim lngDriveNum As Long
    Dim lngRet As Long
    Dim strDriveName As String
    
    ' Button deaktivieren
    cmdEject.Enabled = False
    
    ' alle Items in der ListBox löschen
    cbDrive.Clear
    
    ' alle verfügbare Laufwerke ermitteln
    lngRet = GetLogicalDrives
    
    ' alle Laufwerksnummern durchlaufen
    For lngDriveNum = 0 To 25
    
        ' ist das entsprechende Bit in lngRet <> 0
        If (lngRet And 2 ^ lngDriveNum) <> 0 Then
        
            ' Laufwerksbuchstabe
            strDriveName = Chr$(65 + lngDriveNum)
            
                ' Laufwerkstyp ermitteln (USB-Laufwerke)
                If Len(GetDevInstStr(strDriveName)) > 0 Then
                
                    ' Daten in der ComboBox ausgeben und speichern
                    cbDrive.AddItem strDriveName & ":\"
                    cbDrive.ItemData(cbDrive.NewIndex) = lngDriveNum
                    
                End If
        End If
        
        ' nächste Laufwerksnummer
    Next lngDriveNum
    
    ' sind Einträge in der ComboBox vorhanden
    If cbDrive.ListCount > 0 Then
    
        ' erster Eintrag in der ComboBox
        cbDrive.ListIndex = 0
        
        ' Button aktivieren
        cmdEject.Enabled = True
        
    End If

End Sub

Private Sub Form_Load()

    ' alle auswerfbare Laufwerke ermitteln
    Call ListRemovableDrives
    
End Sub
'-------- Ende Formular "frmMain" alias frmMain.frm  --------
'-------- Anfang Modul "modEject" alias modEject.bas --------
Option Explicit

' ----==== Const ====----
Private Const CR_SUCCESS As Long = &H0
Private Const DN_REMOVABLE As Long = &H4000
Private Const DRIVE_CDROM As Long = 5
Private Const DRIVE_FIXED As Long = 3
Private Const DRIVE_REMOVABLE As Long = 2
Private Const DIGCF_DEVICEINTERFACE As Long = &H10
Private Const DIGCF_PRESENT As Long = &H2
Private Const ERROR_INSUFFICIENT_BUFFER As Long = 122
Private Const ERROR_NO_MORE_ITEMS As Long = 259&
Private Const FILE_SHARE_READ As Long = &H1
Private Const FILE_SHARE_WRITE As Long = &H2
Private Const INVALID_HANDLE_VALUE As Long = -1
Private Const IOCTL_STORAGE_GET_DEVICE_NUMBER As Long = &H2D1080
Private Const MAX_PATH As Long = 260
Private Const OPEN_EXISTING As Long = 3

Private Const GUID_DEVINTERFACE_DISK As String = _
    "{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}"
    
Private Const GUID_DEVINTERFACE_FLOPPY As String = _
    "{53F56311-B6BF-11D0-94F2-00A0C91EFB8B}"
    
Private Const GUID_DEVINTERFACE_CDROM As String = _
    "{53F56308-B6BF-11D0-94F2-00A0C91EFB8B}"
    
' ----==== Type ====----
Private Type GUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type

Private Type SP_DEVICE_INTERFACE_DATA
    cbSize As Long
    InterfaceClassGuid As GUID
    flags As Long
    Reserved As Long
End Type

Private Type STORAGE_DEVICE_NUMBER
    DeviceType As Long
    DeviceNumber As Long
    PartitionNumber As Long
End Type

' ----==== KERNEL32 Deklarationen ====----
Private Declare Function CloseHandle Lib "kernel32" ( _
                         ByVal hObject As Long) As Long
                         
Private Declare Function CreateFile Lib "kernel32" _
                         Alias "CreateFileA" ( _
                         ByVal lpFileName As String, _
                         ByVal dwDesiredAccess As Long, _
                         ByVal dwShareMode As Long, _
                         ByRef lpSecurityAttributes As Any, _
                         ByVal dwCreationDisposition As Long, _
                         ByVal dwFlagsAndAttributes As Long, _
                         ByVal hTemplateFile As Long) As Long
                         
Private Declare Function DeviceIoControl Lib "kernel32" ( _
                         ByVal hDevice As Long, _
                         ByVal dwIoControlCode As Long, _
                         ByRef lpInBuffer As Any, _
                         ByVal nInBufferSize As Long, _
                         ByRef lpOutBuffer As Any, _
                         ByVal nOutBufferSize As Long, _
                         ByRef lpBytesReturned As Long, _
                         ByRef lpOverlapped As Any) As Long
                         
Private Declare Function GetDriveType Lib "kernel32" _
                         Alias "GetDriveTypeA" ( _
                         ByVal nDrive As String) As Long
                         
Private Declare Function QueryDosDevice Lib "kernel32.dll" _
                         Alias "QueryDosDeviceA" ( _
                         ByVal lpDeviceName As String, _
                         ByVal lpTargetPath As String, _
                         ByVal ucchMax As Long) As Long
                         
' ----==== OLE32 Deklarationen ====----
Private Declare Function IIDFromString Lib "ole32" ( _
                         ByVal lpsz As Long, _
                         ByRef lpiid As GUID) As Long
                         
' ----==== SETUPAPI Deklarationen ====----
Private Declare Function CM_Get_DevNode_Status Lib "setupapi.dll" ( _
                         ByRef pulStatus As Long, _
                         ByRef pulProblemNumber As Long, _
                         ByVal dnDevInst As Long, _
                         ByVal ulFlags As Long) As Long
                         
Private Declare Function CM_Get_Parent Lib "setupapi.dll" ( _
                         ByRef pdnDevInst As Long, _
                         ByVal dnDevInst As Long, _
                         ByVal ulFlags As Long) As Long
                         
Private Declare Function CM_Locate_DevNodeA Lib "setupapi.dll" ( _
                         ByRef pdnDevInst As Long, _
                         ByVal pDeviceID As Long, _
                         ByVal ulFlags As Long) As Long
                         
Private Declare Function CM_Request_Device_EjectA Lib "setupapi.dll" ( _
                         ByVal dnDevInst As Long, _
                         ByRef pVetoType As Long, _
                         ByVal pszVetoName As Long, _
                         ByVal ulNameLength As Long, _
                         ByVal ulFlags As Long) As Long
                         
Private Declare Function SetupDiDestroyDeviceInfoList Lib "setupapi.dll" ( _
                         ByVal DeviceInfoSet As Long) As Long
                         
Private Declare Function SetupDiEnumDeviceInterfaces Lib "setupapi.dll" ( _
                         ByVal DeviceInfoSet As Long, _
                         ByRef DeviceInfoData As Any, _
                         ByRef InterfaceClassGuid As GUID, _
                         ByVal MemberIndex As Long, _
                         ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) As Long
                         
Private Declare Function SetupDiGetDeviceInterfaceDetail Lib "setupapi.dll" _
                         Alias "SetupDiGetDeviceInterfaceDetailA" ( _
                         ByVal DeviceInfoSet As Long, _
                         ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA, _
                         ByRef DeviceInterfaceDetailData As Any, _
                         ByVal DeviceInterfaceDetailDataSize As Long, _
                         ByRef RequiredSize As Long, _
                         ByRef DeviceInfoData As Any) As Long
                         
Private Declare Function SetupDiGetClassDevs Lib "setupapi.dll" _
                         Alias "SetupDiGetClassDevsA" ( _
                         ByRef ClassGuid As GUID, _
                         ByVal Enumerator As String, _
                         ByVal hwndParent As Long, _
                         ByVal flags As Long) As Long
                         
' ------------------------------------------------------
' Funktion     : EjectUsbDrive
' Beschreibung : USB-Laufwerk sicher entfernen/auswerfen
' Übergabewert : DriveLetter = Laufwerksbuchstabe
'                ShowStdMessage = Standardnachricht anzeigen oder nicht
' Rückgabewert : True/False
' ------------------------------------------------------
' USB Gerät abmelden. (Sicheres Entfernen)
' Als Hilfestellung diente der Anno 2003 in c't veröffentlichter C++ Code
' DevEject von Matthias Withopf.
' ------------------------------------------------------
Public Function EjectUsbDrive(ByVal DriveLetter As String, Optional _
    ShowStdMessage As Boolean = True) As Boolean
    
    Dim strDevInst As String
    Dim hDevInst As Long
    Dim lngStatus As Long
    Dim lngProblem As Long
    Dim lngVetoType As Long
    Dim strVetoName As String
    
    ' Storagename aus der Registry auslesen
    strDevInst = GetDevInstStr(DriveLetter)
    
    ' ist ein Storagename vorhanden
    If Len(strDevInst) <> 0 Then
    
        ' Handle auf den Node holen
        If CM_Locate_DevNodeA(hDevInst, StrPtr(StrConv(strDevInst, _
            vbFromUnicode)), 0&) = CR_SUCCESS Then
            
            ' wenn dieser Node nicht auswerfbar ist, dann solange bis zum
            ' Parentnode raufgehen bis dieser auswerfbar ist
            If CM_Get_DevNode_Status(lngStatus, lngProblem, hDevInst, 0&) = _
                CR_SUCCESS Then
                
                ' solange die Schleife durchlaufen bis (lngStatus And
                ' DN_REMOVABLE) = DN_REMOVABLE
                Do While Not (lngStatus And DN_REMOVABLE) = DN_REMOVABLE
                
                    ' wenn kein Parentnode mehr vorhanden, dann Schleife
                    ' verlassen
                    If Not CM_Get_Parent(hDevInst, hDevInst, 0&) = _
                        CR_SUCCESS Then Exit Do
                        
                    ' wenn CM_Get_DevNode_Status nicht = CR_SUCCESS ist,
                    ' dann Schleife verlassen
                    If Not CM_Get_DevNode_Status(lngStatus, lngProblem, _
                        hDevInst, 0&) = CR_SUCCESS Then Exit Do
                        
                Loop
                
                ' ist dieser Node auswerbar
                If (lngStatus And DN_REMOVABLE) = DN_REMOVABLE Then
                
                    ' wenn nicht die Standardnachricht angezeigt werden soll
                    If Not ShowStdMessage Then
                    
                        ' strVetoName mit vbNullChar auffüllen
                        strVetoName = String$(MAX_PATH, vbNullChar)
                        
                    End If
                    
                    ' wenn das auswerfen erfolgreich war
                    If CM_Request_Device_EjectA(hDevInst, lngVetoType, _
                        StrPtr(strVetoName), Len(strVetoName), 0&) = _
                        CR_SUCCESS Then
                        
                        ' wenn nicht
                        ' nicht die Standardnachricht anzeigt werden soll
                        If Not ShowStdMessage Then
                        
                            MsgBox "Das Gerät 'USB-Massenspeichert' [" & _
                                DriveLetter & ":\] kann jetzt entfernt " & _
                                "werden.", vbOKOnly Or vbInformation
                                
                        End If
                        
                        ' entfernen war erfolgreich
                        EjectUsbDrive = True
                        
                    Else
                    
                        ' wenn nicht
                        ' nicht die Standardnachricht anzeigt werden soll
                        If Not ShowStdMessage Then
                        
                            ' ist lngVetoType <> 0
                            If lngVetoType <> 0 Then
                            
                                ' strVetoName konvertieren
                                strVetoName = StrConv(strVetoName, vbUnicode)
                                
                                ' strVetoName bis zum ersten vbNullChar
                                strVetoName = Left$(strVetoName, InStr(1, _
                                    strVetoName, vbNullChar) - 1)
                                    
                                MsgBox "Das Gerät '" & strVetoName & "' " & _
                                    "[" & DriveLetter & ":\] kann zur " & _
                                    "Zeit nicht deaktiviert werden. " & _
                                    "Wiederholen Sie den Vorgang " & _
                                    "später.", vbOKOnly Or vbExclamation
                                    
                            End If
                        End If
                        
                        ' entfernen war nicht erfolgreich
                        EjectUsbDrive = False
                        
                    End If
                End If
            End If
        End If
    End If
    
End Function

' ------------------------------------------------------
' Funktion     : GetDevInstStr
' Beschreibung : Gerätenamen zu einem Laufwerk ermitteln
' Übergabewert : DriveLetter = Laufwerksbuchstabe
' Rückgabewert : Gerätename
' ------------------------------------------------------
' Der Original C++ Code zu dieser Funktion ist auf der Seite
' http://www.codeproject.com/KB/system/RemoveDriveByLetter.aspx
' zu finden. Einge Teile zu dieser Funktion stammen auch von
' http://www.vbarchiv.net/workshop/workshop78s2.html
' ------------------------------------------------------
Public Function GetDevInstStr(ByVal DriveLetter As String) As String

    Dim hVolume As Long
    Dim hDevInfo As Long
    Dim bolIsFloppy As Boolean
    Dim bytBuff() As Byte
    Dim lngRet As Long
    Dim lngBuffLen As Long
    Dim lngDevNumber As Long
    Dim lngIndex As Long
    Dim strRet As String
    Dim strBuff As String * MAX_PATH
    Dim strDosDevName As String
    Dim tGUID As GUID
    Dim tSDN As STORAGE_DEVICE_NUMBER
    Dim tSPDID As SP_DEVICE_INTERFACE_DATA
    
    ' Handle auf das Laufwerk holen
    hVolume = CreateFile("\\.\" & DriveLetter & ":", 0&, FILE_SHARE_READ Or _
        FILE_SHARE_WRITE, ByVal 0&, OPEN_EXISTING, 0&, ByVal 0&)
        
    ' ist ein gültiges Handle vorhanden
    If hVolume <> INVALID_HANDLE_VALUE Then
    
        ' Laufwerksnummer ermitteln
        If DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, ByVal _
            0&, 0&, tSDN, Len(tSDN), lngRet, ByVal 0&) Then
            
            ' Laufwerksnummer speichern
            lngDevNumber = tSDN.DeviceNumber
            
        End If
        
        ' Handle schließen
        Call CloseHandle(hVolume)
        
    End If
    
    ' DOS-Gerätenamen vom Laufwerk ermitteln
    If QueryDosDevice(DriveLetter & ":", strBuff, MAX_PATH) Then
    
        ' DOS-Gerätename
        strDosDevName = Left$(strBuff, InStr(1, strBuff, vbNullChar) - 1)
        
        ' ist das Laufwerk ein Diskettenlauferk
        If InStr(1, strDosDevName, "\Floppy") Then
        
            ' Laufwerk ist ein Diskettenlaufwerk
            bolIsFloppy = True
            
        End If
    End If
    
    ' Laufwerkstyp ermitteln
    Select Case GetDriveType(DriveLetter & ":\")
    
        ' auswerfbare Laufwerke
    Case DRIVE_REMOVABLE
    
        ' Diskettenlaufwerke
        If bolIsFloppy Then
        
            ' String zu GUID konvertieren
            Call IIDFromString(StrPtr(GUID_DEVINTERFACE_FLOPPY), tGUID)
                
        Else
        
            ' andere auswerfbare Laufwerke
            ' String zu GUID konvertieren
            Call IIDFromString(StrPtr(GUID_DEVINTERFACE_DISK), tGUID)
                
        End If
        
        ' HD-Laufwerke
    Case DRIVE_FIXED
    
        ' String zu GUID konvertieren
        Call IIDFromString(StrPtr(GUID_DEVINTERFACE_DISK), tGUID)
        
        ' CDROM-Laufwerke
    Case DRIVE_CDROM
    
        ' String zu GUID konvertieren
        Call IIDFromString(StrPtr(GUID_DEVINTERFACE_CDROM), tGUID)
        
    End Select
    
    ' Handle auf die Geräteklasse holen
    hDevInfo = SetupDiGetClassDevs(tGUID, vbNullString, 0&, DIGCF_PRESENT Or _
        DIGCF_DEVICEINTERFACE)
        
    ' ist ein gültiges Handle vorhanden
    If hDevInfo <> INVALID_HANDLE_VALUE Then
    
        tSPDID.cbSize = Len(tSPDID)
        
        ' alle Geräte in dieser Geräteklasse durchlaufen
        Do
        
            ' Geräte in dieser Geräteklasse auflisten
            If SetupDiEnumDeviceInterfaces(hDevInfo, ByVal 0&, tGUID, _
                lngIndex, tSPDID) = 0 Then
                
                ' wenn keine Geräte mehr in dieser Geräteklasse vorhanden sind
                If Err.LastDllError = ERROR_NO_MORE_ITEMS Then
                
                    ' Schleife verlassen
                    Exit Do
                    
                Else
                
                    ' Funktion verlassen
                    Exit Function
                    
                End If
            End If
            
            ' hier ermitteln wir die erforderliche Buffergröße zur
            ' Aufnahme des Gerätenamens
            If SetupDiGetDeviceInterfaceDetail(hDevInfo, tSPDID, ByVal 0&, _
                0&, lngBuffLen, ByVal 0&) = 0 Then
                
                ' wenn der Buffer zu klein ist
                If Err.LastDllError = ERROR_INSUFFICIENT_BUFFER Then
                
                    'Type SP_DEVICE_INTERFACE_DETAIL_DATA
                    '    cbSize As Long
                    '    DevicePath(0) As Byte
                    'End Type
                
                    ' anstelle von SP_DEVICE_INTERFACE_DETAIL_DATA
                    ' verwenden wir hier ein BytaArray
                    
                    ' Buffer dimensionieren
                    ReDim bytBuff(lngBuffLen - 1)
                    
                    ' Len(SP_DEVICE_INTERFACE_DETAIL_DATA)
                    bytBuff(0) = 5
                    
                    ' Gerätenamen ermitteln
                    If SetupDiGetDeviceInterfaceDetail(hDevInfo, tSPDID, _
                        bytBuff(0), lngBuffLen, lngBuffLen, ByVal 0&) <> 0 _
                        Then
                        
                        ' Handle auf das Gerät holen
                        hVolume = CreateFile(Mid$(StrConv(bytBuff, _
                            vbUnicode), 5, lngBuffLen - 5), 0&, _
                            FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0&, _
                            OPEN_EXISTING, 0&, ByVal 0&)
                            
                        ' ist ein gültiges Handle vorhanden
                        If hVolume <> INVALID_HANDLE_VALUE Then
                        
                            ' Gerätenummer ermitteln
                            If DeviceIoControl(hVolume, _
                                IOCTL_STORAGE_GET_DEVICE_NUMBER, ByVal 0&, _
                                0&, tSDN, Len(tSDN), lngRet, ByVal 0&) Then
                                
                                ' ist die Laufwerksnummer gleich der
                                ' Gerätenummer
                                If lngDevNumber = tSDN.DeviceNumber Then
                                
                                    ' Handle auf das Gerät schließen
                                    Call CloseHandle(hVolume)
                                    
                                    ' Handle auf die Geräteklasse schließen
                                    Call SetupDiDestroyDeviceInfoList( _
                                        hDevInfo)
                                        
                                    ' Gerätename
                                    strRet = Mid$(StrConv(bytBuff, _
                                        vbUnicode), 5, lngBuffLen - 5)
                                        
                                    ' # durch \ ersetzen
                                    strRet = Replace(strRet, "#", "\")
                                    
                                    ' die ersten 4 Zeichen und die Geräte-GUID
                                    ' wegschneiden
                                    strRet = Mid$(strRet, 5, InStr(1, _
                                        strRet, "{") - 6)
                                        
                                    ' für EjectUsbDrive benötigen wir
                                    ' nur auswerfbare USB-Laufwerke
                                    If UCase$(Left$(strRet, 7)) = _
                                        "USBSTOR" Then
                                        
                                        ' Gerätenamen zurückgeben
                                        GetDevInstStr = strRet
                                        
                                    End If
                                End If
                            End If
                            
                            ' Handle auf das Gerät schließen
                            Call CloseHandle(hVolume)
                            
                        End If
                    End If
                End If
            End If
            
            ' nächste Geräteindexnummer
            lngIndex = lngIndex + 1
            
            ' nächstes Geräte in dieser Geräteklasse
        Loop
        
        ' Handle auf die Geräteklasse schließen
        Call SetupDiDestroyDeviceInfoList(hDevInfo)
        
    End If
    
End Function
'--------- Ende Modul "modEject" alias modEject.bas ---------
'------------ Ende Projektdatei SaveUsbEject.vbp ------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 4 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Frank Schüler am 21.06.2011 um 22:17

Hi

Ah, ein interner Card-Reader. Japp, da hilft nur ein Reboot. ;-)

Mfg Frank

Kommentar von piper am 21.06.2011 um 21:59

Hallo Frank

Hmmm - von wegen rein/rausstöpseln: Dazu benötigte ich Hammer, Axt, Trennscheibe, Sprengstoff oder zumindestens einen Schraubenzieher... das Ding ist nämlich hart eingebaut. Im übrigen ist Dein Code täglich im Einsatz; funktioniert mit normalen USB-Sticks bestens. Eine wertvolle Automationshilfe.

Hinweis: Der korrekte Dismount eines Card-Reader-Drives kann mit dem Context-Menu <Eject> erfolgen. Also, next Release: If Is CardReaderDrive then Eject... :-)

Thanks und Gruss
Alfred

Kommentar von Frank Schüler am 21.06.2011 um 20:28

Hi piper

Ups, sehe erst jetzt das Du da eine Message hinterlassen hast. Lieber spät als nie eine Antwort. ;-) Bei Multi-Card-Reader wird immer der komplette Reader ausgeworfen. Einzelne Laufwerke eines Multi-Card-Readers lassen sich nicht auswerfen. Das gleiche Verhalten zeigt auch W2K und XP. k.A wie es unter VISTA und W7 ausschaut. Vermute aber das dort ebenfalls der komplette Reader ausgeworfen wird. Card-Reader abziehen und wieder anstöpseln und schon sind alle Laufwerke des Card-Readers wieder da.

Kommentar von piper am 25.12.2010 um 19:58

Jahrelang gesucht - et voilà! Perfekte Lösung. Lediglich mit dem Multi-Card-Reader kommt sie nicht zurecht. Doch da zeigt auch XPProf-nativ ein ziemlich nicht-determiniertes Verhalten (Irrtümlicher Rootdevice-Unload oder sowas --> Cardreader verschwunden. --> Reboot --> vielleicht kommt er dann wieder...) :-(

Dem Autor vielen Dank für den Code; tolle Leistung!