60
votes

I want to build a program that detects if a usb (or two or more) are plugged in (and copy all contents to any folder on a hard disk)

Any ideas? I have this,

using System.Runtime.InteropServices;

But it is not the easy way (that I believe). I want something easy.

I have another idea (if (folder exist) then copy) something -- but there may be a problem with that, and I want a good solution.

There may also be a tool called SerialPort; can I use it? If so, how do I use it?

3
Break it down into individual pieces. The code that detects the USB drive is one piece, the code that copies data from is another. Do the pieces you can at the moment.Lasse V. Karlsen
yeah! i can "copy" file now.. with a batch file the program can "create" it file if not existangel
I made a NuGet packet that works on Windows, MacOS and Linux: github.com/Jinjinov/Usb.EventsJinjinov

3 Answers

67
votes

It is easy to check for removable devices. However, there's no guarantee that it is a USB device:

var drives = DriveInfo.GetDrives()
    .Where(drive => drive.IsReady && drive.DriveType == DriveType.Removable);

This will return a list of all removable devices that are currently accessible. More information:

13
votes

Here is a code that works for me, which is a part from the website above combined with my early trials: http://www.codeproject.com/KB/system/DriveDetector.aspx

This basically makes your form listen to windows messages, filters for usb drives and (cd-dvds), grabs the lparam structure of the message and extracts the drive letter.

protected override void WndProc(ref Message m)
    {

        if (m.Msg == WM_DEVICECHANGE)
        {
            DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
            if ((m.WParam.ToInt32() == DBT_DEVICEARRIVAL) &&  (vol.dbcv_devicetype == DBT_DEVTYPVOLUME) )
            {
                MessageBox.Show(DriveMaskToLetter(vol.dbcv_unitmask).ToString());
            }
            if ((m.WParam.ToInt32() == DBT_DEVICEREMOVALCOMPLETE) && (vol.dbcv_devicetype == DBT_DEVTYPVOLUME))
            {
                MessageBox.Show("usb out");
            }
        }
        base.WndProc(ref m);
    }

    [StructLayout(LayoutKind.Sequential)] //Same layout in mem
    public struct DEV_BROADCAST_VOLUME
    {
        public int dbcv_size;
        public int dbcv_devicetype;
        public int dbcv_reserved;
        public int dbcv_unitmask;
    }

    private static char DriveMaskToLetter(int mask)
    {
        char letter;
        string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //1 = A, 2 = B, 3 = C
        int cnt = 0;
        int pom = mask / 2;
        while (pom != 0)    // while there is any bit set in the mask shift it right        
        {        
            pom = pom / 2;
            cnt++;
        }
        if (cnt < drives.Length)
            letter = drives[cnt];
        else
            letter = '?';
        return letter;
    }

Do not forget to add this:

using System.Runtime.InteropServices;

and the following constants:

    const int WM_DEVICECHANGE = 0x0219; //see msdn site
    const int DBT_DEVICEARRIVAL = 0x8000;
    const int DBT_DEVICEREMOVALCOMPLETE = 0x8004;
    const int DBT_DEVTYPVOLUME = 0x00000002;  
2
votes

Microsoft API Code Pack. ShellObjectWatcher class.