1

I am developing a tool which ejects USB drives that doesn't comply with some internal policies. I checked many ways to do the ejection

https://www.codeproject.com/Articles/13530/Eject-USB-disks-using-C

Safely remove a USB drive using the Win32 API?

but all of them were not working for all the USB I tested. After a lot of research and tests, I found this code from StackOverflow which seemed to work fine (last reply) Eject USB device via C#

But recently I got a USB stick which is not ejected.

Surprisingly I debugged the execution and I realized that if I put a breakpoint in the line of DeviceIOControl and I just wait for few second and simply resume the execution, the ejection is done perfectly. If I remove the breakpoint and plug the same USB, the ejection fails. in both cases, the return code of the DeviceIOControl is always TRUE. So, in the end, I test to simply add a Thread.Sleep(3000); after the DeviceIOControl command and the USB got ejected.

Can anyone explaining what could be happening?

I also detected that there are several similar solutions with different parameters passed to the DeviceIOControl function. Anybody could explain to me which one should I use and why?

Many thanks.

My code:

       [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern IntPtr CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        IntPtr SecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        IntPtr hTemplateFile
    );

    [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    private static extern bool DeviceIoControl(
        IntPtr hDevice,
        uint dwIoControlCode,
        IntPtr lpInBuffer,
        uint nInBufferSize,
        IntPtr lpOutBuffer,
        uint nOutBufferSize,
        out uint lpBytesReturned,
        IntPtr lpOverlapped
    );

    [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
    private static extern bool DeviceIoControl(
        IntPtr hDevice,
        uint dwIoControlCode,
        byte[] lpInBuffer,
        uint nInBufferSize,
        IntPtr lpOutBuffer,
        uint nOutBufferSize,
        out uint lpBytesReturned,
        IntPtr lpOverlapped
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr hObject);

    private IntPtr handle = IntPtr.Zero;

    const uint GENERIC_READ = 0x80000000;
    const uint GENERIC_WRITE = 0x40000000;
    const int FILE_SHARE_READ = 0x1;
    const int FILE_SHARE_WRITE = 0x2;
    const int FSCTL_LOCK_VOLUME = 0x00090018;
    const int FSCTL_DISMOUNT_VOLUME = 0x00090020;
    const int IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808;
    const int IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804;


    public void EjectDrive(string  driveLetter)
    {
        string path = @"\\.\" + driveLetter + @":";
        IntPtr handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero);

        if ((long)handle == -1)
        {
         //   MessageBox.Show("Unable to open drive " + driveLetter);
            return;
        }

        uint dummy = 0;

        bool returnvalue = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, out dummy, IntPtr.Zero);
        Thread.Sleep(3000);
        CloseHandle(handle);

       // MessageBox.Show("OK to remove drive.");
    }
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
YaKs
  • 143
  • 12
  • Did you find the reason? – skm Jun 13 '17 at 09:50
  • unfortunately not yet – YaKs Jun 13 '17 at 21:32
  • I still dealing with this... look at this other post. seems like there are some functions to call before the ejection. I am using a different code now which works in 90% of the cases. https://stackoverflow.com/questions/48793364/c-sharp-eject-usb-code-for-lockvolume-dismountvolume-and-prepareremovalofvol – YaKs Feb 15 '18 at 09:45

0 Answers0