Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Eject any drive


  • Please log in to reply
39 replies to this topic
Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
Because the Eject-Command doesn't work for each device (like USB-Drives) I wrote this little lines.
I have tested it with CD- and USB-drives and worked.
I do not know it's limitations (e.g. OS), if you find some please post them...

You have simply to adjust the Driveletter.
Driveletter = I:
DrivePath = \\.\%Driveletter%

hVolume := DllCall("CreateFile"
		, str, DrivePath
		, UInt, 0x80000000 | 0x40000000   ;GENERIC_READ | GENERIC_WRITE
		, UInt, 0x0		;Tries to get exclusiv rights to the drive +++(see below)
		, UInt, Null
		, UInt, 0x3         ;OPEN_EXISTING
		, UInt, 0x0
		, UInt, NULL)

if A_LastError = 32			;In this case no handle was retreived to release
{
	msgbox Drive is in use by another application. Please try again later
	return
}

if hVolume != -1
{
	   DllCall("DeviceIoControl"
      , UInt, hVolume
      , UInt, 0x2D4808   ;IOCTL_STORAGE_EJECT_MEDIA
      , UInt, NULL
      , UInt, 0
      , UInt, NULL
      , UInt, 0
      , UInt, &dwBytesReturned   ;Not used
      , UInt,  NULL)

   DllCall("CloseHandle", UInt, hVolume)
}
return
+++:
To throw the device out while another application reads it (like if it is open in Explorer) specify
, UInt, 0x1 ;(= FILE_SHARE_READ)

To throw the device out even while another process is writing to specify:
, UInt, 0x1 | 0x2 ;FILE_SHARE_READ | FILE_SHARE_WRITE



Edit 06.06.2006: I have added a little sample to eject a known device (for example if drive-letter changes) using it's device-ID (GUID)
Driveletter_as_value = 65		;Begins to search at drive-letter "A". Increase this value according to your count of "fix" discs

;This loop checks the Volume-ID of all drives until the searched one is found
Loop
{
	Transform, Driveletter, Chr, %Driveletter_as_value%		;Getting a drive-letter
	DllCall("GetVolumeNameForVolumeMountPoint"
	   , Str, Driveletter . ":\"
	   , Str, GUID
	   , UInt, 50)

	if (GUID = "\\?\Volume{53some83-val3-1ue9-your-drive172hasf}")	;Volume-ID of your device
		break
	else if Driveletter_as_value = 90		;90 = "Z" as last drive-letter --> drive was not found
	{
		msgbox Device not found!
		return
	}
	Driveletter_as_value ++
}

DrivePath = \\.\%Driveletter%:

hVolume := DllCall("CreateFile"
		, str, DrivePath
		, UInt, 0x80000000 | 0x40000000   ;GENERIC_READ | GENERIC_WRITE
		, UInt, 0x0		;Tries to get exclusiv rights to the drive +++(see above)
		, UInt, Null
		, UInt, 0x3         ;OPEN_EXISTING
		, UInt, 0x0
		, UInt, NULL)

if A_LastError = 32			;In this case no handle was retreived to release
{
	msgbox Drive is in use by another application. Please try again later
	return
}

if hVolume != -1
{
   DllCall("DeviceIoControl"
      , UInt, hVolume
      , UInt, 0x2D4808   ;IOCTL_STORAGE_EJECT_MEDIA
      , UInt, NULL
      , UInt, 0
      , UInt, NULL
      , UInt, 0
      , UInt, &dwBytesReturned   ;Not used
      , UInt,  NULL)

   DllCall("CloseHandle", UInt, hVolume)
}
return

Thalon

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
Pfff, buggy... I tested it with C: and it didn't worked!

(Honestly, I didn't tried... I hope it doesn't work with fixed disks!...)
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
Of course you found it!
It doesn't work for fixed disks (tested at D:\) :oops: :wink:

The command just ejects ejectable devices ;)

Thalon

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005

The command just ejects ejectable devices ;)

I would have been sorry if it could eject a fixed hard disk out of its bed...
Out of curiosity, I wonder if it can "eject" a Flash card, like the tray icon stating: "You can safely take out this peripheral" (rough translation from French".
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
I am using it in work to eject a CompactFlash and the Drive is not available afterwards (also the normal warning-ballon after disconnecting it the "hard way" doesn't appear this way).

I found this function (as C#-Example) for save-ejection, but I am not shure how to check if it is correct.

The IOCTL_STORAGE_EJECT_MEDIA control code causes media to be ejected from a SCSI device.

Thalon

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Thanks for sharing this. If you don't mind, perhaps it should be posted on the Drive command page in the help file.

By the way, don't you have to close the file (hVolume) afterward? Maybe you intentionally omitted that part so that the handle could eject more than once without having to call CreateFile(). I believe all files (even strange ones like these) close automatically when the script exits; but if anyone needs to close the file before then, I think this would do it:
DllCall("CloseHandle", uint, hVolume)

Thanks.

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
It isn't well tested at the moment (I used it today about 30 times in a short script which exits directly after ejecting the CF).

It works as standalone-script, but of course I have to free handle afterwards in a persistent script! (I have added it in first post. Thx Chris!)

The CreateFile-Function returns only the handle to the device in this case. The name is really misleading, but what shall we do? :lol:

Thalon

badmojo
  • Members
  • 204 posts
  • Last active: Jul 23 2014 01:39 AM
  • Joined: 11 Nov 2005
Thalon, you may want to try the use the RUNDLL command posted here.

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
Mmm.. no.
With this command a window opens and I have to eject it still by myself.
This solution can be found already somewhere here in forum.

Because the Drive-Letter never changes I want to directly eject it after some operations (which I have to do between 10 and 50 times a day!).

Thalon

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
I am using the first script for more than 2 month every day at work and I did not found any problems.

Because of a script in german forum I have added (edited) a second way of using this script: The (second) script is looking for the device (usings it's device-ID) instead of the drive-letter. This is usefull if you use more than one Plug-And-Play-Device where Drive-Letters could change...

Of course it works for CD-Drives as well as for USB-Devices (and I think all other ejectable media).

Feedback is welcome!

Thalon

toralf as guest
  • Guests
  • Last active:
  • Joined: --
Wouldn't that be a nice extension of the AHK command Drive?
I guess currently only CD/DVD Drives can be ejected with Drive.

Maybe also DriveGet could be extended.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
The above method is in the user manual: it's listed near the bottom of the Drive page. That should help people find it.

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
But not the second part, with
DllCall("GetVolumeNameForVolumeMountPoint" 

      , Str, Driveletter . ":\" 

      , Str, GUID 

      , UInt, 50)
Do you expect too much R&D and only little benefit?
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
It's a nice feeling to see his code in the official help-file :)

I think the second part is a bit (too?) special and was written in about 15 minutes (including research).
What means R&D?

Thalon

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012
I tried your first script with my USB drive and it works great. Like PhiLho suggested it would be nice if Windows could told to give the 'Safe to remove hardware' notification.

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit