I am struggling trying to create an application capable to eject any USB mass storage device. After many tries, I am finally using some code found in codeproject https://www.codeproject.com/Articles/375916/How-to-Prepare-a-USB-Drive-for-Safe-Removal BUT with some USB devices I get an error "This device is currently in use. Close any programs or windows that might be using the device, and then try again.". I dont really understand why it happens for some devices and not for others...
The error window is shown and basically removalDrive() method returns false, USB not ejected.
public static bool RemoveDrive( string driveCharWithColon )
{
// open the storage volume
IntPtr hVolume = CreateFile( @"\\.\" + driveCharWithColon, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero );
if ( hVolume.ToInt32( ) == -1 ) return false;
// get the volume's device number
long DeviceNumber = GetDeviceNumber( hVolume );
if ( DeviceNumber == -1 ) return false;
// get the drive type which is required to match the device numbers correctely
string rootPath = driveCharWithColon + "\\";
DriveType driveType = GetDriveType( rootPath );
// get the dos device name (like \device\floppy0) to decide if it's a floppy or not - who knows a better way?
StringBuilder pathInformation = new StringBuilder( 250 );
uint res = QueryDosDevice( driveCharWithColon, pathInformation, 250 );
if ( res == 0 ) return false;
// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
long DevInst = GetDrivesDevInstByDeviceNumber( DeviceNumber, driveType, pathInformation.ToString( ) );
if ( DevInst == 0 ) return false;
// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
int DevInstParent = 0;
CM_Get_Parent( ref DevInstParent, ( int ) DevInst, 0 );
for ( int tries=1; tries <= 3; tries++ ) // sometimes we need some tries...
{
int r = CM_Request_Device_Eject_NoUi( DevInstParent, IntPtr.Zero, null, 0, 0 );
if ( r == 0 ) return true;
Thread.Sleep( 500 );
}
return false;
}
Reading more answers I found this one Eject Memory card from Card Reader C#
Where it is mentioned that before invoking the method CM_Request_Device_Eject_NoUi, I have to call "LockVolume, DismountVolume, and PrepareRemovalOfVolume" using the hVolume returned from CreateFile.
Unfortunately these functions are only provided by Microsoft in C++. how-to-ejecting-removable-media-in-windows
I wanted to try this solution but I dont really know how to implement those methods using c#.
Any could give me any idea about what might be happening? I tried with simply closing the file handler
CloseHandle(hVolume);
before calling the method CM_Request_Device_Eject_NoUi but it created other SEHException exception (External component has thrown an exception).