Usage example: Try Eject( "D:" ). Drive letter passed can be like "D" or "D:" or File fullpath. Only the first letter matters.
This function's Result is Thrown as an Error object, so cannot be called as a normal function.
The function could be simply called as
Code: Select all
Drive := "H:"
Try Eject(Drive)
Catch Error as Result
and then Result properties could be shown in a dialog.
- Result.Message
- Warning: Eject failed
- Error: Eject failed
- Success: Eject succeeded
- Result.What
- An Error string returned either by System or by Eject()
- Result.Extra ;
- Model of Drive / Volume label, when drive letter is valid.
Code: Select all
#Requires AutoHotkey v2.0-
#Warn
#SingleInstance
MyEject("H:")
MyEject(Drive)
{
Local Result, Msg, Icon
Try Eject(Drive)
Catch Error as Result
Msg := StrSplit( Result.Message, ":",, 2 )
Icon := Msg[1] = "Success" ? "Iconi" : Msg[1]="Error" ? "Iconx" : "Icon!"
SetTimer( (*) => MsgBox(Result.What , Drive . "`n" . Msg[2], Icon . " T4"), -1)
Return( Msg[1] = "Success" )
}
Example screen shots for above script:
Code: Select all
Eject(Drive) ; By SKAN for ah2 on CT91/D48E @ autohotkey.com/r?t=94113
{
If ( ! DirExist( Drive := SubStr(Drive, 1, 1) . ":" ) )
Throw( Error("Warning: Eject failed", "Invalid drive letter.", Drive . " ?!") )
Local hVolume, DriveLabel := "<Label> " . DriveGetLabel(Drive)
If ( hVolume := OpenVolume(Drive) ) = -1
Throw( Error("Warning: Eject failed", "Mapped/substitute drive.", DriveLabel) )
Local DEVICE_NUMBER := IOCTL_STORAGE_GET_DEVICE_NUMBER(hVolume)
DllCall("Kernel32.dll\CloseHandle", "ptr",hVolume)
Local queryStr, queryEnum, DiskDrive, UnsupportedMedia
queryStr := Format("{1:}'{2:}{3:}'", "Select * from Win32_DiskDrive where DeviceID=", "\\\\.\\PHYSICALDRIVE", DEVICE_NUMBER)
queryEnum := ComObjGet("winmgmts:").ExecQuery(queryStr)._NewEnum()
queryEnum(&DiskDrive)
If ( UnsupportedMedia := CheckMediaType(DiskDrive.MediaType) )
Throw( Error("Warning: Eject failed", UnsupportedMedia, DiskDrive.Model) )
Local hSetupApi := DllCall("Kernel32.dll\LoadLibrary", "str","SetupApi.dll", "ptr"), nDeviceID := 0, nVetoType := 0
DllCall("SetupApi.dll\CM_Locate_DevNode", "ptrp",&nDeviceID, "str",DiskDrive.PNPDeviceID, "Int",0)
DllCall("SetupApi.dll\CM_Get_Parent", "ptrp",&nDeviceID, "uint",nDeviceID, "int",0)
If DllCall("SetupApi.dll\CM_Request_Device_Eject", "uint",nDeviceID, "ptrp",&nVetoType, "str",nVetoType, "int",1, "int",0)
{
DllCall("Kernel32.dll\FreeLibrary", "ptr",hSetupApi)
Throw( Error("Error: Eject failed", PNP_VETO_TYPE(nVetoType), DiskDrive.Model) )
}
While( DirExist(Drive) ) ; wait for drive letter to disappear ..
Sleep(100)
DllCall("Kernel32.dll\FreeLibrary", "ptr",hSetupApi) ; .. and then release Lib
Throw( Error("Success: Eject succeeded", "Safely removed hardware", DiskDrive.Model) )
OpenVolume(Drive) ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
Return DllCall("Kernel32.dll\CreateFile", "str", "\\.\" . Drive
, "int",0, "int", 0, "ptr",0, "int",0x3 ; OPEN_EXISTING := 0x3
, "int",0, "ptr",0, "ptr")
}
IOCTL_STORAGE_GET_DEVICE_NUMBER(hDevice) ; - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
Local STORAGE_DEVICE_NUMBER := Buffer(12, 0)
DllCall("Kernel32.dll\DeviceIoControl", "ptr",hDevice
, "int",0x2D1080 ; IOCTL_STORAGE_GET_DEVICE_NUMBER
, "int",0, "int",0, "ptr",STORAGE_DEVICE_NUMBER
, "int",12, "ptrp",0, "ptr",0)
Return( NumGet(STORAGE_DEVICE_NUMBER, 4, "uint") )
}
CheckMediaType(MT) ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
Switch( MT )
{
Case "Removable Media", "External hard disk media": Return
Case "Fixed hard disk media": Return(MT)
Default: Return("Media type Unknown")
}
}
PNP_VETO_TYPE(nVetoType) ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{ ; https://docs.microsoft.com/en-us/windows/win32/api/cfg/ne-cfg-pnp_veto_type
Return(
["The specified operation was rejected for an unknown reason." ; PNP_VetoTypeUnknown
, "The device does not support the specified PnP operation." ; PNP_VetoLegacyDevice
, "The specified operation cannot be completed because of a pending close operation." ; PNP_VetoPendingClose
, "A Microsoft Win32 application vetoed the specified operation." ; PNP_VetoWindowsApp
, "A Win32 service vetoed the specified operation." ; PNP_VetoWindowsService
, "The requested operation was rejected because of outstanding open handles." ; PNP_VetoOutstandingOpen
, "The device supports the specified operation, but the device rejected the operation." ; PNP_VetoDevice
, "The driver supports the specified operation, but the driver rejected the operation." ; PNP_VetoDriver
, "The device does not support the specified operation." ; PNP_VetoIllegalDeviceRequest
, "There is insufficient power to perform the requested operation." ; PNP_VetoInsufficientPower
, "The device cannot be disabled." ; PNP_VetoNonDisableable
, "The driver does not support the specified PnP operation." ; PNP_VetoLegacyDriver
, "The caller has insufficient privileges to complete the operation." ; PNP_VetoInsufficientRights
][nVetoType] )
}
}
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -