arcker Posted June 29, 2007 Posted June 29, 2007 (edited) This script lets you to dismount an usb key of a CD-Rom safelyFor example, it's useful if you don't want you users to use an usb keyi've just translated it from http://support.microsoft.com/kb/165721Note that preventremoval doesn't work, so if you have opened files, they will be lost if you launch this script.For now, it's impossible to "remount" an usb key that has been removed. You have to disconnect and reconnect it.If you manage to remount the key without eject and reconnect physically your usb key, please let me now expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Description ...: Eject an USB Key or a CD-ROM safely ; Parameters ....: $$cDriveLetter - Drive to eject (ex : E: ) ; Return values .: Success - True ; Failure - False ; Author ........: Yoan Roblet (Arcker) ; Remarks .......: ; Requirements...: AutoIt3Lib ; Related .......: http://support.microsoft.com/kb/165721 ; =============================================================================================================================== #include <A3LWinApi.au3> ;Prototypes ;BOOL EjectVolume(TCHAR cDriveLetter); ;HANDLE OpenVolume(TCHAR cDriveLetter); ;BOOL LockVolume(HANDLE hVolume); ;BOOL DismountVolume(HANDLE hVolume); ;BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent); ;BOOL AutoEjectVolume(HANDLE hVolume); ;BOOL CloseVolume(HANDLE hVolume); ;StringFormat Output $szVolumeFormat = "\\\\.\\%s" $szRootFormat = "%s\\" $szErrorFormat = "Error %d: %s\n" ;------------------------------------------ ;Arbitrary variables Global Const $INVALID_HANDLE_VALUE = 0 ;------------------------------------------ ;DeviceIoControl Contants Global Const $FSCTL_LOCK_VOLUME = int(0x090018) Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020) Global Const $IOCTL_STORAGE_EJECT_MEDIA = int(0x002D4808) Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804) ;------------------------------------------ ;Retry Constants Global Const $LOCK_TIMEOUT = 10000 ; 10 Seconds Global Const $LOCK_RETRIES = 20 $OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:") ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf) Func ReportError($szMsg) ConsoleWrite(StringFormat($szErrorFormat, _API_GetLastErrorMessage (), $szMsg) & @CRLF) Exit EndFunc ;==>ReportError Func OpenVolume($cDriveLetter) ;HANDLE hVolume ;UINT uDriveType ;TCHAR szVolumeName[8] ;TCHAR szRootName[5] ;DWORD dwAccessFlags $szRootName = StringFormat($szRootFormat, $cDriveLetter) $uDriveType = DriveGetType($szRootName); ConsoleWrite($szRootName & @tab & $uDriveType & @crlf) Switch $uDriveType Case "Removable" $dwAccessFlags = 6 Case "CDROM" $dwAccessFlags = 2 Case Else ConsoleWrite("Cannot eject. Drive type is incorrect." & @CRLF) Return $INVALID_HANDLE_VALUE EndSwitch $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter) ;$szVolumeName = $szVolumeFormat & $cDriveLetter ConsoleWrite($szVolumeName & @crlf ) $hVolume = _API_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6) #cs hVolume = CreateFile( szVolumeName, dwAccessFlags, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); #ce If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile"); Return $hVolume; EndFunc ;==>OpenVolume Func CloseVolume($hVolume) Return _API_CloseHandle ($hVolume); EndFunc ;==>CloseVolume Func LockVolume($hVolume) Local $dwBytesReturned Local $dwSleepAmount Local $nTryCount local $iRead $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES; ; Do this in a loop until a timeout period has expired For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then Return True Else Sleep($dwSleepAmount); EndIf Next Return False; EndFunc ;==>LockVolume Func DismountVolume($hVolume) ConsoleWrite("Dismount " & $hVolume & @crlf) Local $dwBytesReturned, $iRead local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead) msgbox(0,"",$aResult) Return $aResult ;Return $dwBytesReturned EndFunc ;==>DismountVolume Func PreventRemovalOfVolume($hVolume, $fPreventRemoval) Local $dwBytesReturned Local $aResult Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval") DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval) $lpBytesReturned = DllStructCreate("int Read") $pRead = DllStructGetPtr($lpBytesReturned, "Read") $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _ "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped) if $aResult = 0 then msgbox(0,"",_API_GetLastErrorMessage()) Return $aResult <> 0 ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL), ;NULL, 0, ; & dwBytesReturned, ;NULL); EndFunc ;==>PreventRemovalOfVolume Func AutoEjectVolume($hVolume) Local $aResult, $iRead; $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead) Return $aResult EndFunc ;==>AutoEjectVolume Func EjectVolume($cDriveLetter) Local $hVolume; Local $fRemoveSafely = False; Local $fAutoEject = False; ; Open the volume. $hVolume = OpenVolume($cDriveLetter); If $hVolume == $INVALID_HANDLE_VALUE Then Return False ; Lock and dismount the volume. If LockVolume($hVolume) And DismountVolume($hVolume) Then $fRemoveSafely = True; ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf) ; Set prevent removal to false and eject the volume. If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then $fAutoEject = True; EndIf Else ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf) EndIf ; Close the volume so other processes can use the drive. If CloseVolume($hVolume) = False Then Return False; EndIf If $fAutoEject Then ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter)) Else If $fRemoveSafely Then ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter)) EndIf EndIf Return True; EndFunc ;==>EjectVolume Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead) Local $aResult Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped $tRead = DllStructCreate("int Data") $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _ "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped) $iRead = DllStructGetData($tRead, "Data") ConsoleWrite("Device Control " & $iRead & @CRLF) Return $aResult<>0 EndFunc ;==>_Device_Control Edited June 29, 2007 by arcker -- Arck System _ Soon -- Ideas make everything "La critique est facile, l'art est difficile" Projects :[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
spudw2k Posted August 22, 2008 Posted August 22, 2008 Updated api include and _API_ funcs. expandcollapse popup#include <WinApi.au3> ;Prototypes ;BOOL EjectVolume(TCHAR cDriveLetter); ;HANDLE OpenVolume(TCHAR cDriveLetter); ;BOOL LockVolume(HANDLE hVolume); ;BOOL DismountVolume(HANDLE hVolume); ;BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent); ;BOOL AutoEjectVolume(HANDLE hVolume); ;BOOL CloseVolume(HANDLE hVolume); ;StringFormat Output $szVolumeFormat = "\\\\.\\%s" $szRootFormat = "%s\\" $szErrorFormat = "Error %d: %s\n" ;------------------------------------------ ;Arbitrary variables Global Const $INVALID_HANDLE_VALUE = 0 ;------------------------------------------ ;DeviceIoControl Contants Global Const $FSCTL_LOCK_VOLUME = int(0x090018) Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020) Global Const $IOCTL_STORAGE_EJECT_MEDIA = int(0x002D4808) Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804) ;------------------------------------------ ;Retry Constants Global Const $LOCK_TIMEOUT = 10000 ; 10 Seconds Global Const $LOCK_RETRIES = 20 $OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:") ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf) Func ReportError($szMsg) ConsoleWrite(StringFormat($szErrorFormat, _WinAPI_GetLastErrorMessage (), $szMsg) & @CRLF) Exit EndFunc ;==>ReportError Func OpenVolume($cDriveLetter) ;HANDLE hVolume ;UINT uDriveType ;TCHAR szVolumeName[8] ;TCHAR szRootName[5] ;DWORD dwAccessFlags $szRootName = StringFormat($szRootFormat, $cDriveLetter) $uDriveType = DriveGetType($szRootName); ConsoleWrite($szRootName & @tab & $uDriveType & @crlf) Switch $uDriveType Case "Removable" $dwAccessFlags = 6 Case "CDROM" $dwAccessFlags = 2 Case Else ConsoleWrite("Cannot eject. Drive type is incorrect." & @CRLF) Return $INVALID_HANDLE_VALUE EndSwitch $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter) ;$szVolumeName = $szVolumeFormat & $cDriveLetter ConsoleWrite($szVolumeName & @crlf ) $hVolume = _WinAPI_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6) #cs hVolume = CreateFile( szVolumeName, dwAccessFlags, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); #ce If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile"); Return $hVolume; EndFunc ;==>OpenVolume Func CloseVolume($hVolume) Return _WinAPI_CloseHandle ($hVolume); EndFunc ;==>CloseVolume Func LockVolume($hVolume) Local $dwBytesReturned Local $dwSleepAmount Local $nTryCount local $iRead $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES; ; Do this in a loop until a timeout period has expired For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then Return True Else Sleep($dwSleepAmount); EndIf Next Return False; EndFunc ;==>LockVolume Func DismountVolume($hVolume) ConsoleWrite("Dismount " & $hVolume & @crlf) Local $dwBytesReturned, $iRead local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead) msgbox(0,"",$aResult) Return $aResult ;Return $dwBytesReturned EndFunc ;==>DismountVolume Func PreventRemovalOfVolume($hVolume, $fPreventRemoval) Local $dwBytesReturned Local $aResult Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval") DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval) $lpBytesReturned = DllStructCreate("int Read") $pRead = DllStructGetPtr($lpBytesReturned, "Read") $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _ "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped) if $aResult = 0 then msgbox(0,"",_WinAPI_GetLastErrorMessage()) Return $aResult <> 0 ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL), ;NULL, 0, ; & dwBytesReturned, ;NULL); EndFunc ;==>PreventRemovalOfVolume Func AutoEjectVolume($hVolume) Local $aResult, $iRead; $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead) Return $aResult EndFunc ;==>AutoEjectVolume Func EjectVolume($cDriveLetter) Local $hVolume; Local $fRemoveSafely = False; Local $fAutoEject = False; ; Open the volume. $hVolume = OpenVolume($cDriveLetter); If $hVolume == $INVALID_HANDLE_VALUE Then Return False ; Lock and dismount the volume. If LockVolume($hVolume) And DismountVolume($hVolume) Then $fRemoveSafely = True; ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf) ; Set prevent removal to false and eject the volume. If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then $fAutoEject = True; EndIf Else ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf) EndIf ; Close the volume so other processes can use the drive. If CloseVolume($hVolume) = False Then Return False; EndIf If $fAutoEject Then ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter)) Else If $fRemoveSafely Then ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter)) EndIf EndIf Return True; EndFunc ;==>EjectVolume Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead) Local $aResult Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped $tRead = DllStructCreate("int Data") $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _ "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped) $iRead = DllStructGetData($tRead, "Data") ConsoleWrite("Device Control " & $iRead & @CRLF) Return $aResult<>0 EndFunc ;==>_Device_Control Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF
Marcuzzo18 Posted October 6, 2008 Posted October 6, 2008 My Drive has the Letter E, so when the InputBox prompts for the drive letter I enter "E:" (without quotes) it Pops a MsgBox that says "True" and then I get the following error message _WinAPI_CloseHandle: The handle is invalid this is the output written to the console >Running:(3.2.12.1):H:\Autoit\autoit3.exe "H:\Scripts\AuotEjectIt.au3" E:\ Removable \\.\E: Device Control 0 Dismount 0xFFFFFFFF Device Control 0 Volume Locked and Dismounted, trying to eject Device Control 0 +>14:43:56 AutoIT3.exe ended.rc:0 >Exit code: 0 Time: 36.611 Am I missing something here? [font="Century Gothic"]quisnam est quantum stultus , balatro vel balatro quisnam insistovolubilis in solum rideo risi risum----------------------------------------------------------------------------------------------------------------------------Portable Command Line Tool[/font]
spudw2k Posted October 6, 2008 Posted October 6, 2008 Am I missing something here?Hmm not too sure. I notice in your console output your device (Dismount 0xFFFFFFFF). I think something is failing there. My output has never returned 0xFFFFFFFF. Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF
Cdma1X Posted October 11, 2008 Posted October 11, 2008 after Eject/dismount how to replug/remount the usb?
arcker Posted October 11, 2008 Author Posted October 11, 2008 reconnect it. once unmounted windows doesn't recognise it once you unplugged, replugged it. This is the purpose => Security. -- Arck System _ Soon -- Ideas make everything "La critique est facile, l'art est difficile" Projects :[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]
Cdma1X Posted October 11, 2008 Posted October 11, 2008 (edited) reconnect it. once unmounted windows doesn't recognise it once you unplugged, replugged it. This is the purpose => Security.is it really impossible? or only autoit can not do it? Edited October 11, 2008 by Cdma1X
corey822 Posted October 11, 2008 Posted October 11, 2008 Works like a beaut abosoloutly great!!! works perfect for me no error's cheers C.W C.Wnew rules:1.dont use plz in a post or title use please instead2.always use help file as it is now muchly over rated3. dont think where not watching u4.please wait 24 hours after last post ot bump XD i use to make that mistake
Innovative Posted October 12, 2008 Posted October 12, 2008 Cool ! Would be useful for me in future ;D
slayerz Posted October 14, 2008 Posted October 14, 2008 Thanks...I'll try it after this. I've been using the example posted by arcker last year, and its working well. AUTOIT[sup] I'm lovin' it![/sup]
Marcuzzo18 Posted October 22, 2008 Posted October 22, 2008 Hi there, sorry for the late response... one small detail I had forgotten to mention. I had initially tried the script here at work, NO ADMIN Rights I tried the script again on my home pc and it worked would be cool to get this to work without admin rights eitherway... nice work Cheers... [font="Century Gothic"]quisnam est quantum stultus , balatro vel balatro quisnam insistovolubilis in solum rideo risi risum----------------------------------------------------------------------------------------------------------------------------Portable Command Line Tool[/font]
spudw2k Posted October 22, 2008 Posted October 22, 2008 (edited) would be cool to get this to work without admin rightsThis is not a limitation of the code, but how the Operating System works. It's outside the scripts control unfortunately. Edited October 22, 2008 by spudw2k Spoiler Things I've Made: Always On Top Tool ◊ AU History ◊ Deck of Cards ◊ HideIt ◊ ICU ◊ Icon Freezer ◊ Ipod Ejector ◊ Junos Configuration Explorer ◊ Link Downloader ◊ MD5 Folder Enumerator ◊ PassGen ◊ Ping Tool ◊ Quick NIC ◊ Read OCR ◊ RemoteIT ◊ SchTasksGui ◊ SpyCam ◊ System Scan Report Tool ◊ System UpTime ◊ Transparency Machine ◊ VMWare ESX Builder Misc Code Snippets: ADODB Example ◊ CheckHover ◊ Detect SafeMode ◊ DynEnumArray ◊ GetNetStatData ◊ HashArray ◊ IsBetweenDates ◊ Local Admins ◊ Make Choice ◊ Recursive File List ◊ Remove Sizebox Style ◊ Retrieve PNPDeviceID ◊ Retrieve SysListView32 Contents ◊ Set IE Homepage ◊ Tickle Expired Password ◊ Transpose Array Projects: Drive Space Usage GUI ◊ LEDkIT ◊ Plasma_kIt ◊ Scan Engine Builder ◊ SpeeDBurner ◊ SubnetCalc Cool Stuff: AutoItObject UDF ◊ Extract Icon From Proc ◊ GuiCtrlFontRotate ◊ Hex Edit Funcs ◊ Run binary ◊ Service_UDF
Michel Claveau Posted October 22, 2008 Posted October 22, 2008 Hi! My external USB disk is:$uDriveType = "Fixed" If I addCase "Fixed" $dwAccessFlags = 6 The script run OK. @-salutations
cagiva Posted June 14, 2009 Posted June 14, 2009 imnsho CDTray("F:", "open") Sleep(5000) CDTray("F:", "closed")
Solarlight27 Posted March 2, 2012 Posted March 2, 2012 Works great, I wish there was a way to just put the text in automatically.... Updated api include and _API_ funcs. expandcollapse popup#include <WinApi.au3> ;Prototypes ;BOOL EjectVolume(TCHAR cDriveLetter); ;HANDLE OpenVolume(TCHAR cDriveLetter); ;BOOL LockVolume(HANDLE hVolume); ;BOOL DismountVolume(HANDLE hVolume); ;BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent); ;BOOL AutoEjectVolume(HANDLE hVolume); ;BOOL CloseVolume(HANDLE hVolume); ;StringFormat Output $szVolumeFormat = ".%s" $szRootFormat = "%s" $szErrorFormat = "Error %d: %sn" ;------------------------------------------ ;Arbitrary variables Global Const $INVALID_HANDLE_VALUE = 0 ;------------------------------------------ ;DeviceIoControl Contants Global Const $FSCTL_LOCK_VOLUME = int(0x090018) Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020) Global Const $IOCTL_STORAGE_EJECT_MEDIA = int(0x002D4808) Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804) ;------------------------------------------ ;Retry Constants Global Const $LOCK_TIMEOUT = 10000 ; 10 Seconds Global Const $LOCK_RETRIES = 20 $OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:") ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf) Func ReportError($szMsg) ConsoleWrite(StringFormat($szErrorFormat, _WinAPI_GetLastErrorMessage (), $szMsg) & @CRLF) Exit EndFunc ;==>ReportError Func OpenVolume($cDriveLetter) ;HANDLE hVolume ;UINT uDriveType ;TCHAR szVolumeName[8] ;TCHAR szRootName[5] ;DWORD dwAccessFlags $szRootName = StringFormat($szRootFormat, $cDriveLetter) $uDriveType = DriveGetType($szRootName); ConsoleWrite($szRootName & @tab & $uDriveType & @crlf) Switch $uDriveType Case "Removable" $dwAccessFlags = 6 Case "CDROM" $dwAccessFlags = 2 Case Else ConsoleWrite("Cannot eject. Drive type is incorrect." & @CRLF) Return $INVALID_HANDLE_VALUE EndSwitch $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter) ;$szVolumeName = $szVolumeFormat & $cDriveLetter ConsoleWrite($szVolumeName & @crlf ) $hVolume = _WinAPI_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6) #cs hVolume = CreateFile( szVolumeName, dwAccessFlags, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); #ce If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile"); Return $hVolume; EndFunc ;==>OpenVolume Func CloseVolume($hVolume) Return _WinAPI_CloseHandle ($hVolume); EndFunc ;==>CloseVolume Func LockVolume($hVolume) Local $dwBytesReturned Local $dwSleepAmount Local $nTryCount local $iRead $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES; ; Do this in a loop until a timeout period has expired For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then Return True Else Sleep($dwSleepAmount); EndIf Next Return False; EndFunc ;==>LockVolume Func DismountVolume($hVolume) ConsoleWrite("Dismount " & $hVolume & @crlf) Local $dwBytesReturned, $iRead local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead) msgbox(0,"",$aResult) Return $aResult ;Return $dwBytesReturned EndFunc ;==>DismountVolume Func PreventRemovalOfVolume($hVolume, $fPreventRemoval) Local $dwBytesReturned Local $aResult Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval") DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval) $lpBytesReturned = DllStructCreate("int Read") $pRead = DllStructGetPtr($lpBytesReturned, "Read") $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _ "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped) if $aResult = 0 then msgbox(0,"",_WinAPI_GetLastErrorMessage()) Return $aResult <> 0 ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL), ;NULL, 0, ; & dwBytesReturned, ;NULL); EndFunc ;==>PreventRemovalOfVolume Func AutoEjectVolume($hVolume) Local $aResult, $iRead; $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead) Return $aResult EndFunc ;==>AutoEjectVolume Func EjectVolume($cDriveLetter) Local $hVolume; Local $fRemoveSafely = False; Local $fAutoEject = False; ; Open the volume. $hVolume = OpenVolume($cDriveLetter); If $hVolume == $INVALID_HANDLE_VALUE Then Return False ; Lock and dismount the volume. If LockVolume($hVolume) And DismountVolume($hVolume) Then $fRemoveSafely = True; ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf) ; Set prevent removal to false and eject the volume. If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then $fAutoEject = True; EndIf Else ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf) EndIf ; Close the volume so other processes can use the drive. If CloseVolume($hVolume) = False Then Return False; EndIf If $fAutoEject Then ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.n", $cDriveLetter)) Else If $fRemoveSafely Then ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.n", $cDriveLetter)) EndIf EndIf Return True; EndFunc ;==>EjectVolume Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead) Local $aResult Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped $tRead = DllStructCreate("int Data") $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _ "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped) $iRead = DllStructGetData($tRead, "Data") ConsoleWrite("Device Control " & $iRead & @CRLF) Return $aResult<>0 EndFunc ;==>_Device_Control
nico18n Posted August 22, 2018 Posted August 22, 2018 good morning. I am using Windows 7 and it does not work. This is the result when I ask to remove a USB pendrive:h: Removable.h:Device Control 0Dismount 0Device Control 0
water Posted August 22, 2018 Posted August 22, 2018 The OP has been away for over 3 years, the last entry in this thread is more than 6 years old. I fear you won't get much support. My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
nico18n Posted August 22, 2018 Posted August 22, 2018 Hello, unfortunately I think you're absolutely right. I was so taken by the argument that I had not noticed.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now