Detecting and 'Ejecting' Memory Cards

Huscroft

Member
Joined
Feb 2, 2007
Messages
5
Programming Experience
1-3
G'Day,
I'm writing a small application for my engagement and wedding that will (hopefully) detect when a memory card is inserted. When this happens, the program will create a new directory on the HDD and then rip all the data (in this case photos) off the memory card into this new directory. Ideally, once it is finished, it will "Eject" the memory card.

I can handle the directory creation and copying, but am at a loss with the detection and ejection of the memory card. Can anybody point me in the right direction?

I am aware that there are application out there that can do this, but I would like the satisfaction of doing this myself.

Cheers
Gareth
 
Try the DriveNotice class I just wrote, it manages and notifies about changes in the drive collection:
VB.NET:
Public Class DriveNotice
    Implements IDisposable
 
    Public Enum ChangeType
        added
        removed
    End Enum
 
    Public Class DriveChangeInfo
        Public Name As String
        Public DriveType As IO.DriveType
        Public ChangeType As ChangeType

        Public Sub New(ByVal name As String, ByVal drivetype As DriveType)
            Me.Name = name
            Me.DriveType = drivetype
        End Sub
    End Class
 
    Private drives As New Dictionary(Of String, DriveChangeInfo)
    Private WithEvents t As New System.Timers.Timer
    Public Event DriveChanged(ByVal info As DriveChangeInfo)
 
    Public Sub New(Optional ByVal interval As Integer = 5000)
        'add current drives
        For Each di As IO.DriveInfo In IO.DriveInfo.GetDrives
            Dim dci As New DriveChangeInfo(di.Name, di.DriveType)
            drives.Add(dci.Name, dci)
        Next
        'start timer
        t.Interval = interval
        t.Start()
    End Sub
 
    Private Sub t_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) _
    Handles t.Elapsed
        'get all current drives
        SyncLock drives
            Dim newdrives As New Dictionary(Of String, DriveChangeInfo)
            For Each di As IO.DriveInfo In IO.DriveInfo.GetDrives
                Dim dci As New DriveChangeInfo(di.Name, di.DriveType)
                newdrives.Add(dci.Name, dci)
                If drives.ContainsKey(dci.Name) = True Then
                    drives.Remove(dci.Name) 'remove existing old drive
                Else
                    dci.ChangeType = ChangeType.added
                    RaiseEvent DriveChanged(dci)
                End If
            Next
            'remaining old drives were removed
            For Each dci As DriveChangeInfo In drives.Values
                dci.ChangeType = ChangeType.removed
                RaiseEvent DriveChanged(dci)
            Next
            drives = newdrives
        End SyncLock
    End Sub
 
    Private disposedValue As Boolean = False        ' To detect redundant calls
 
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: free managed resources when explicitly called
                t.Close()
            End If
            ' TODO: free shared unmanaged resources
        End If
        Me.disposedValue = True
    End Sub
 
    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
End Class
Example usage:
VB.NET:
Private WithEvents DN As New DriveNotice(3000)
 
Private Sub DN_DriveChanged(ByVal info As DriveNotice.DriveChangeInfo) Handles DN.DriveChanged
    Dim sb As New StringBuilder
    sb.AppendLine("drive was " & info.ChangeType.ToString)
    sb.AppendLine("drive name: " & info.Name)
    sb.AppendLine("drive type: " & info.DriveType.ToString)
    If info.DriveType = DriveType.Removable Then
        sb.AppendLine("(could be a memory card)")
    End If
    MsgBox(sb.ToString)
End Sub
I've not seen hardware that "auto-ejects" memory cards yet, only manual such mechanisms.
 
G'Day,
Thanks for that, I'll give it a go. I should explain the ejecting a bit more...

To 'Correctly' eject removeable media (such as USB keys, memory cards etc), you normally right-click on the drive in My Computer and select "Eject". This ensures that allr eads and writes to/from the device are finialised so there is less chance of data being corrupted. There has to be a way of doing this through code, but I haven't been able to find it.


You could also stop the device from the taskbas but I don't want to stop the card reader.

Thanks
Gareth
 
Ok, I see, I knew about that feature, but didn't connect with "eject", "disconnect" is perhaps better, or "safely remove hardware" as the dialog says, didn't notice the 'eject' option on that context menu before. I don't know any code for it.
 
G'Day,
Well this wasn't quite what I was looking for. As the drives already exist from time you plug in the card reader, when you then insert a memory card, this class doesn't detect any changes in the system and thus won't be activated. In the end, I just built a function that checks each removable drives status every 500 milliseconds and if it detects the drive as being "Ready", it means a card has been inserted. It then return the drive letter and I can get on with copying files from it.

This class would work wonderfully if you either have memory sticks or the users plug their cameras in via the usb port instead of removing the memory card and plugging that into a card reader.

Thanks for the help anyway, it was much appreciated!
Gareth
 
Thanks for the info! I actually knew this also, but it was too late at night for thinking last night.. Another PC I use have fixed drives for card readers, that would probably detect "ready" same as with CD/DVD drives, with my own PC I have the card reader as a USB stick where the drive is added/removed when plugged.

For the fixed card reader drive this also means there is no need to "safely remove hardware", since the drive and hardware remains. As added note for removable hardware, I find the default configuration for these are "Optimized for quick removal" which means they can be removed without using the safe-dialog. I checked both with a USB-drive that is detected as drivetype Fixed and a USB-stick that is detected as drivetype Removable. If you have any such equipment you can see by opening Device Manager (Control Panel, Administrative, Computer Management), check under 'Disk drives' and review Policy tab of its properties.
 
Anyone have a snippet on "Safely Removing Hardware" programmability? I have a detection/notification class. I just want to be able to kick it off the system. If I can't eject the drive, is it possible to disable USBSTOR without a reboot? I would prefer the disable be temporary IE drives back after reboot. Thanks!
 
Thanks for the link. I found some C# source on "The Code Project" also. Instead of translating it, I turned it into a Class library and referenced it in my VB. I'm still sorting it out, but I think I can make it work. Thanks again!
 
Back
Top