Jump to content

Safely Eject a USB Drive


wraithdu
 Share

Recommended Posts

That's interesting, because I have one or two drives that regularly give trouble. Sometimes it appears to maybe be a memory issue, after sustained and heavy use (video stuff, etc).

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Link to comment
Share on other sites

  • 1 year later...

If someone thinks the example isn't working, then it is. The issue is down to the Forum removing backslashes (again). Simply replace the following with ....

; "X:" -> for GetDriveType
    Local $szRootPath = $drive & ":\"
    ; "X:" -> for QueryDosDevice
    Local $szDevicePath = $drive & ":"
    ; ".X:" -> to open the volume
    Local $szVolumeAccessPath = "\\.\" & $drive & ":"

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Sorry wraithdu, but I couldn't help but update the code though to use the new features of AutoIt. Great work by the way!

 

#include <Array.au3>
#include <WinAPI.au3>
#include <WinAPIFiles.au3>
#include <WinAPISys.au3>

Global Const $DIGCF_DEVICEINTERFACE = 0x10
Global Const $DIGCF_PRESENT = 0x2
Global Const $CR_SUCCESS = 0
Global Const $CR_ACCESS_DENIED = 0x33
Global Const $CM_REMOVE_UI_OK = 0
Global Const $CM_REMOVE_UI_NOT_OK = 0x1
Global Const $CM_REMOVE_NO_RESTART = 0x2
Global Const $CM_SETUP_DEVNODE_READY = 0
Global Const $CM_SETUP_DEVNODE_RESET = 0x4
Global Const $DN_REMOVABLE = 0x4000
Global Const $PNP_VetoTypeUnknown = 0 ; Name is unspecified
Global Enum $DRIVE_EJECT_DEVICENUMBER, _ ; int
        $DRIVE_EJECT_DEVICETYPE, _ ; int
        $DRIVE_EJECT_DEVICEDOSNAME, _ ; string
        $DRIVE_EJECT_DEVICEPATH, _ ; string
        $DRIVE_EJECT_DEVICEID, _ ; string
        $DRIVE_EJECT_DEVICEINSTANCE, _ ; int
        $DRIVE_EJECT_DEVICEINSTANCEPARENT, _ ; int
        $DRIVE_EJECT_DEVICEPARENTID, _ ; string
        $DRIVE_EJECT_ISREMOVEABLE, _ ; bool
        $DRIVE_EJECT_MAX

Global Const $tagSTORAGE_DEVICE_NUMBER = 'dword DeviceType;ulong DeviceNumber;ulong PartitionNumber'
Global Enum $DRIVENUMBER_TYPE, $DRIVENUMBER_NUMBER, $DRIVENUMBER_PARTITION
Global Const $LETTER_LENGTH = StringLen('A')
Global Const $MAX_PATH = 260

; Structures
Global Const $STORAGE_DEVICE_NUMBER = 'ulong DeviceType;ulong DeviceNumber;ulong PartitionNumber'
Global Const $SP_DEV_BUF = 'byte[2052]'
Global Const $SP_DEVICE_INTERFACE_DETAIL_DATA = 'dword cbSize;wchar DevicePath[1024]' ; Created at SP_DEV_BUF ptr
Global Const $SP_DEVICE_INTERFACE_DATA = 'dword cbSize;byte InterfaceClassGuid[16];dword Flags;ulong_ptr Reserved' ; GUID struct = 16 bytes
Global Const $SP_DEVINFO_DATA = 'dword cbSize;byte ClassGuid[16];dword DevInst;ulong_ptr Reserved'

; GUIDs
Global Const $tagGUID_DEVINTERFACE_DISK = DllStructCreate($tagGUID)
DllStructSetData($tagGUID_DEVINTERFACE_DISK, 'Data1', 0x53f56307)
DllStructSetData($tagGUID_DEVINTERFACE_DISK, 'Data2', 0xb6bf)
DllStructSetData($tagGUID_DEVINTERFACE_DISK, 'Data3', 0x11d0)
DllStructSetData($tagGUID_DEVINTERFACE_DISK, 'Data4', Binary('0x94f200a0c91efb8b'))
Global Const $tagGUID_DEVINTERFACE_CDROM = DllStructCreate($tagGUID)
DllStructSetData($tagGUID_DEVINTERFACE_CDROM, 'Data1', 0x53f56308)
DllStructSetData($tagGUID_DEVINTERFACE_CDROM, 'Data2', 0xb6bf)
DllStructSetData($tagGUID_DEVINTERFACE_CDROM, 'Data3', 0x11d0)
DllStructSetData($tagGUID_DEVINTERFACE_CDROM, 'Data4', Binary('0x94f200a0c91efb8b'))
Global Const $tagGUID_DEVINTERFACE_FLOPPY = DllStructCreate($tagGUID)
DllStructSetData($tagGUID_DEVINTERFACE_FLOPPY, 'Data1', 0x53f56311)
DllStructSetData($tagGUID_DEVINTERFACE_FLOPPY, 'Data2', 0xb6bf)
DllStructSetData($tagGUID_DEVINTERFACE_FLOPPY, 'Data3', 0x11d0)
DllStructSetData($tagGUID_DEVINTERFACE_FLOPPY, 'Data4', Binary('0x94f200a0c91efb8b'))

; http://www.codeproject.com/Articles/13839/How-to-Prepare-a-USB-Drive-for-Safe-Removal
; http://www.autoitscript.com/forum/topic/83470-safely-eject-a-usb-drive/
Example()

Func Example()
    Local $hDriveEject = _Drive('E')
    ConsoleWrite('Ejected E: = ' & _Drive_Eject($hDriveEject) & @CRLF)
    ConsoleWrite('Restarted E: = ' & _Drive_Restart($hDriveEject) & @CRLF)
    _ArrayDisplay($hDriveEject)
    $hDriveEject = 0
EndFunc   ;==>Example

Func _Drive($sDrive)
    $sDrive = _GetDrive($sDrive) & ':'
    If Not FileExists($sDrive) Then Return Null

    Local $aQueryDrive[$DRIVE_EJECT_MAX]

    Local $aReturn = _WinAPI_GetDriveNumberEx($sDrive)
    $aQueryDrive[$DRIVE_EJECT_DEVICENUMBER] = (@error ? 0 : $aReturn[$DRIVENUMBER_NUMBER]) ; Device number.
    $aQueryDrive[$DRIVE_EJECT_DEVICETYPE] = _WinAPI_GetDriveType($sDrive)
    $aQueryDrive[$DRIVE_EJECT_DEVICEDOSNAME] = _WinAPI_QueryDosDevice($sDrive)

    Local $tGUID = 0
    Switch $aQueryDrive[$DRIVE_EJECT_DEVICETYPE]
        Case $DRIVE_REMOVABLE
            If StringInStr($aQueryDrive[$DRIVE_EJECT_DEVICEDOSNAME], '\Floppy') > 0 Then
                $tGUID = DllStructGetPtr($tagGUID_DEVINTERFACE_FLOPPY)
            Else
                $tGUID = DllStructGetPtr($tagGUID_DEVINTERFACE_DISK)
            EndIf

        Case $DRIVE_FIXED
            $tGUID = DllStructGetPtr($tagGUID_DEVINTERFACE_DISK)

        Case $DRIVE_CDROM
            $tGUID = DllStructGetPtr($tagGUID_DEVINTERFACE_CDROM)

        Case Default
            Return Null

    EndSwitch

    Local $hDevInfo = DllCall('setupapi.dll', 'ptr', 'SetupDiGetClassDevsW', _
            'ptr', $tGUID, _
            'ptr', Null, _
            'hwnd', Null, _
            'dword', BitOR($DIGCF_PRESENT, $DIGCF_DEVICEINTERFACE))
    If @error Or $hDevInfo[0] = $INVALID_HANDLE_VALUE Then Return Null
    $hDevInfo = $hDevInfo[0]

    Local $tBuffer = DllStructCreate($SP_DEV_BUF)
    Local $tpSP_DEVICE_INTERFACE_DETAIL_DATA = DllStructCreate($SP_DEVICE_INTERFACE_DETAIL_DATA, DllStructGetPtr($tBuffer))
    Local Const $SP_DEVICE_INTERFACE_DETAIL_DATA_SIZE = (@AutoItX64 ? 8 : 6) ; Fix for 64-bit systems.
    Local $tSP_DEVICE_INTERFACE_DETAIL_DATA = DllStructCreate($SP_DEVICE_INTERFACE_DATA)
    Local $tDevInfo = DllStructCreate($SP_DEVINFO_DATA)

    DllStructSetData($tSP_DEVICE_INTERFACE_DETAIL_DATA, 'cbSize', DllStructGetSize($tSP_DEVICE_INTERFACE_DETAIL_DATA))

    Local $iIndex = 0, $iSize = 0
    While 1
        $aReturn = DllCall('setupapi.dll', 'int', 'SetupDiEnumDeviceInterfaces', _
                'ptr', $hDevInfo, _
                'ptr', 0, _
                'ptr', $tGUID, _
                'dword', $iIndex, _
                'struct*', $tSP_DEVICE_INTERFACE_DETAIL_DATA)
        If @error Or Not $aReturn[0] Then
            ExitLoop
        EndIf

        $aReturn = DllCall('setupapi.dll', 'int', 'SetupDiGetDeviceInterfaceDetailW', _
                'ptr', $hDevInfo, _
                'struct*', $tSP_DEVICE_INTERFACE_DETAIL_DATA, _
                'ptr', 0, _
                'dword', 0, _
                'dword*', 0, _
                'ptr', 0)
        $iSize = (@error ? 0 : $aReturn[5])

        If $iSize > 0 And $iSize <= DllStructGetSize($tBuffer) Then
            DllStructSetData($tpSP_DEVICE_INTERFACE_DETAIL_DATA, 'cbSize', $SP_DEVICE_INTERFACE_DETAIL_DATA_SIZE)
            _WinAPI_ZeroMemory(DllStructGetPtr($tDevInfo), DllStructGetSize($tDevInfo))
            DllStructSetData($tDevInfo, 'cbSize', DllStructGetSize($tDevInfo))

            $aReturn = DllCall('setupapi.dll', 'int', 'SetupDiGetDeviceInterfaceDetailW', _
                    'ptr', $hDevInfo, _
                    'struct*', $tSP_DEVICE_INTERFACE_DETAIL_DATA, _
                    'struct*', $tpSP_DEVICE_INTERFACE_DETAIL_DATA, _
                    'dword', $iSize, _
                    'dword*', 0, _
                    'struct*', $tDevInfo)
            If Not @error And $aReturn[0] Then
                $aQueryDrive[$DRIVE_EJECT_DEVICEPATH] = DllStructGetData($tpSP_DEVICE_INTERFACE_DETAIL_DATA, 'DevicePath')
                $aReturn = _WinAPI_GetDriveNumberEx($aQueryDrive[$DRIVE_EJECT_DEVICEPATH])
                If Not @error Then
                    If $aQueryDrive[$DRIVE_EJECT_DEVICENUMBER] = $aReturn[$DRIVENUMBER_NUMBER] Then
                        $aQueryDrive[$DRIVE_EJECT_DEVICEID] = DllStructGetData($tDevInfo, 'DevInst')
                        ExitLoop
                    EndIf
                EndIf
            EndIf
        EndIf
        $iIndex += 1
    WEnd
    DllCall('setupapi.dll', 'int', 'SetupDiDestroyDeviceInfoList', _
            'ptr', $hDevInfo)

    If $aQueryDrive[$DRIVE_EJECT_DEVICEID] > 0 Then
        $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Get_Device_IDW', _
                'ptr', $aQueryDrive[$DRIVE_EJECT_DEVICEID], _
                'wstr', '', _
                'ulong', DllStructGetSize($tBuffer), _ ; Was once 1024.
                'ulong', 0)
        $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCE] = (@error Or $aReturn[0] <> $CR_SUCCESS ? Null : $aReturn[2])

        $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Get_Parent', _
                'dword*', 0, _
                'dword', $aQueryDrive[$DRIVE_EJECT_DEVICEID], _
                'ulong', 0)
        $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT] = (@error Or $aReturn[0] <> $CR_SUCCESS ? Null : $aReturn[1])

        If $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT] Then
            $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Get_Device_IDW', _
                    'ptr', $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT], _
                    'wstr', '', _
                    'ulong', DllStructGetSize($tBuffer), _ ; Was once 1024.
                    'ulong', 0)
            $aQueryDrive[$DRIVE_EJECT_DEVICEPARENTID] = (@error Or $aReturn[0] <> $CR_SUCCESS ? Null : $aReturn[2])

            $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Get_DevNode_Status', _
                    'ulong*', 0, _
                    'ulong*', 0, _
                    'ptr', $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT], _
                    'ulong', 0)
            $aQueryDrive[$DRIVE_EJECT_ISREMOVEABLE] = (Not @error And $aReturn[0] = $CR_SUCCESS And BitAND($aReturn[1], $DN_REMOVABLE))
        EndIf
    EndIf

    Return $aQueryDrive
EndFunc   ;==>_Drive

Func _Drive_Eject(ByRef $aQueryDrive)
    Local $fReturn = False
    If UBound($aQueryDrive) = $DRIVE_EJECT_MAX And $aQueryDrive[$DRIVE_EJECT_ISREMOVEABLE] Then
        Local $aReturn = 0
        For $i = 1 To 3
            $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Query_And_Remove_SubTreeW', _ ; Only used if SurpriseRemovalOK is true in DEVICE_CAPABILITIES
                    'dword', $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT], _
                    'dword*', Null, _
                    'wstr', Null, _
                    'ulong', $MAX_PATH, _
                    'ulong', $CM_REMOVE_UI_OK) ; $CM_REMOVE_NO_RESTART
            If $aReturn[0] = $CR_ACCESS_DENIED Then
                $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Request_Device_EjectW', _
                        'dword', $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT], _
                        'dword*', Null, _
                        'wstr', Null, _
                        'ulong', $MAX_PATH, _
                        'ulong', 0)
            EndIf
            $fReturn = (UBound($aReturn) >= 3 And $aReturn[0] = $CR_SUCCESS And $aReturn[2] = $PNP_VetoTypeUnknown)
            If $fReturn Then
                ExitLoop
            EndIf
            Sleep(500)
        Next
    EndIf
    Return $fReturn
EndFunc   ;==>_Drive_Eject

Func _Drive_IsUSBHDD(ByRef $aQueryDrive)
    ; If the drive is a fixed drive and the path contains 'usbtor', and parent device ID contains 'USB', and IsRemovable.
    Return UBound($aQueryDrive) = $DRIVE_EJECT_MAX ? (($aQueryDrive[$DRIVE_EJECT_DEVICETYPE] = $DRIVE_FIXED) And StringInStr($aQueryDrive[$DRIVE_EJECT_DEVICEPATH], 'usbstor') And StringInStr($aQueryDrive[$DRIVE_EJECT_DEVICEPARENTID], 'usb') And $aQueryDrive[$DRIVE_EJECT_ISREMOVEABLE]) : Null
EndFunc   ;==>_Drive_IsUSBHDD

Func _Drive_Restart(ByRef $aQueryDrive)
    Local $fReturn = False
    If UBound($aQueryDrive) = $DRIVE_EJECT_MAX Then
        Local $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Setup_DevNode', _
                'dword', $aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT], _
                'ulong', 0)
        If @error Or Not $aReturn[0] Then Return SetError(@error, @extended, $fReturn)
        $fReturn = True
    EndIf
    Return $fReturn
EndFunc   ;==>_Drive_Restart

Func _GetDrive($sFilePath)
    Local $sDrive = StringUpper(StringLeft($sFilePath, $LETTER_LENGTH))
    Return _IsDriveLetter($sDrive) ? $sDrive : Null
EndFunc   ;==>_GetDrive

Func _IsDriveLetter($sDrive)
    ; Return StringRegExp($sDrive, '^[A-Za-z]$') = 1
    Return StringIsAlpha($sDrive) And StringLen($sDrive) = $LETTER_LENGTH
EndFunc   ;==>_IsDriveLetter

Func _IsDriveLetterFull($sDrive)
    ; Return StringRegExp($sDrive, '^[A-Za-z]:$') = 1
    Return _IsDriveLetter(_GetDrive($sDrive)) And StringLen($sDrive) = ($LETTER_LENGTH + $LETTER_LENGTH) And StringRight($sDrive, $LETTER_LENGTH) == ':'
EndFunc   ;==>_IsDriveLetterFull

Func _WinAPI_GetDriveNumberEx($sFilePath)
    If _IsDriveLetter($sFilePath) Or _IsDriveLetterFull($sFilePath) Then
        $sFilePath = '\\.\' & _GetDrive($sFilePath) & ':'
    EndIf
    Local Const $hFile = _WinAPI_CreateFileEx($sFilePath, $OPEN_EXISTING, 0, $FILE_SHARE_READWRITE)
    If @error Then Return SetError(@error, @extended, 0)

    Local $tSTORAGE_DEVICE_NUMBER = DllStructCreate($tagSTORAGE_DEVICE_NUMBER)
    Local $vResult = [$DRIVENUMBER_TYPE, $DRIVENUMBER_NUMBER, $DRIVENUMBER_PARTITION]
    _WinAPI_DeviceIoControl($hFile, $IOCTL_STORAGE_GET_DEVICE_NUMBER, Null, 0, DllStructGetPtr($tSTORAGE_DEVICE_NUMBER), DllStructGetSize($tSTORAGE_DEVICE_NUMBER))
    If @error Then
        $vResult = 0
    Else
        $vResult[$DRIVENUMBER_TYPE] = DllStructGetData($tSTORAGE_DEVICE_NUMBER, 'DeviceType')
        $vResult[$DRIVENUMBER_NUMBER] = DllStructGetData($tSTORAGE_DEVICE_NUMBER, 'DeviceNumber')
        $vResult[$DRIVENUMBER_PARTITION] = DllStructGetData($tSTORAGE_DEVICE_NUMBER, 'PartitionNumber')
    EndIf
    _WinAPI_CloseHandle($hFile)
    Return $vResult
EndFunc   ;==>_WinAPI_GetDriveNumberEx
Edited by guinness

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

  • 10 months later...

Hi there,
  i want to eject the USB Drive my script is running from, i guess is will requirey to detect and close the handle of @ScriptFullPath.

however, for the beginning i will focus on the eject, wich deos not work on my win7 ent.:

 

#include <ejectUSB.lib.au3>
#NoTrayIcon
#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
;;;EXAMPLE
Global $drive = InputBox("Eject Drive", "Enter drive (letter only):", "", " M1", 200, 130)
If @error Then Exit
$drive = StringUpper(StringLeft($drive, 1))
If Not FileExists($drive & ":") Then
MsgBox(0 + 16, "Error", "Drive not found.")
Exit
EndIf

Global $driveInfo[9] = ["Device Number", "Drive Type", "DOS Device Name", "Device Path", "Device ID", "Device Instance", "Device Instance Parent", _
"Parent Device ID", "IsRemovable"]
Global $driveArray = _QueryDrive($drive)
For $i = 0 To UBound($driveArray) - 1
ConsoleWrite("-" & $driveInfo[$i] & ": " & $driveArray[$i] & @CRLF)
Next
ConsoleWrite("-Is USBHDD: " & _IsUSBHDD($driveArray) & @CRLF)

If (6 = MsgBox(4 + 32, "Eject?", "Eject this drive?")) Then ConsoleWrite("Ejecting drive <" & $drive & ":> - " & _QueryDrive($drive, True) & @CRLF)
If (6 = MsgBox(4 + 32, "Restart?", "Restart this drive?")) Then ConsoleWrite("Restarting drive <" & $drive & ":> - " & _RestartDrive($driveArray) & @CRLF)

>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "P:\OC\autoit\conti\ejectUSB.au3" /UserParams    
+>13:09:33 Starting AutoIt3Wrapper v.14.801.2025.0 SciTE v.3.4.4.0   Keyboard:00000407  OS:WIN_7/Service Pack 1  CPU:X64 OS:X64    Environment(Language:0409)
+>         SciTEDir => C:\Program Files (x86)\AutoIt3\SciTE   UserDir => C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper
>Running AU3Check (3.3.12.0)  params:-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6  from:C:\Program Files (x86)\AutoIt3  input:P:\OC\autoit\conti\ejectUSB.au3
+>13:09:33 AU3Check ended.rc:0
>Running:(3.3.12.0):C:\Program Files (x86)\AutoIt3\autoit3.exe "P:\OC\autoit\conti\ejectUSB.au3"    
--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
-Device Number: 1
-Drive Type: 2
-DOS Device Name: \Device\HarddiskVolume5
-Device Path: \\?\usbstor#disk&ven_jetflash&prod_transcend_16gb&rev_8.01#7q9wxdi5&1#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
-Device ID: 2172
-Device Instance:
-Device Instance Parent:
-Parent Device ID:
-IsRemovable:
-Is USBHDD: False
"P:\OC\autoit\conti\ejectUSB.lib.au3" (281) : ==> Variable used without being declared.:
$res = DllCall("setupapi.dll", "dword", "CM_Query_And_Remove_SubTreeW", "dword", $DevInstParent, "dword*", 0, "wstr", "", "ulong", 260, "ulong", $CM_REMOVE_UI_OK)
$res = DllCall("setupapi.dll", "dword", "CM_Query_And_Remove_SubTreeW", "dword", ^ ERROR
->13:09:36 AutoIt3.exe ended.rc:1
+>13:09:36 AutoIt3Wrapper Finished.
>Exit code: 1    Time: 4.048

 

any idea?

 

 

Link to comment
Share on other sites

  • 5 months later...

@guinness,

Your rewritten script no longer works with the current 3.3.14.2 or beta 3.3.15.0 AutoIt versions.

The latest version I can get it to work with is release 3.3.10.2 (I don't have all the betas since then, but the ones I do have don't work either). 

I've tested on Win 7 Pro x86 and x64 versions on different physical machines..

If you run the script with both using your built in example, you will see that when you hit the _ArrayDisplay($hDriveEject) that some info is missing running with later versions of AutoIt.

Further debugging shows that 3.3.10.2 yields the following values in my testing: 

$aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCE] = USBSTOR\DISK&VEN_KINGSTON&PROD_DATATRAVELER_3.0&REV_PMAP\00147854488EBE51E75C40C2&0
$aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT] = 2472

and any AutoIt version after that that yields no values for those:

$aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCE] =
$aQueryDrive[$DRIVE_EJECT_DEVICEINSTANCEPARENT] =

 

Looks like something failing with the DLL call

If $aQueryDrive[$DRIVE_EJECT_DEVICEID] > 0 Then
        $aReturn = DllCall('setupapi.dll', 'dword', 'CM_Get_Device_IDW', _
                'ptr', $aQueryDrive[$DRIVE_EJECT_DEVICEID], _
                'wstr', '', _
                'ulong', DllStructGetSize($tBuffer), _ ; Was once 1024.
                'ulong', 0)

but I can't figure it out.

Perhaps you can cast your expert eye over it, and confirm whether it is indeed a problem. I seem to recall it stopped working with the 3.3.11.0 beta, but couldn't find anything in the change logs that set would lead me to the solution.

Thanks

 

 

Link to comment
Share on other sites

  • 4 weeks later...

OK, found the problem: with versions of AutoIt after 3.3.10.2 you have to do an explicit DllOpen() for setupapi.dll before any of the subsequent DllCall() statements

Found the solution in a post by Biatu https://www.autoitscript.com/forum/topic/77731-device-management-api/?do=findComment&comment=1186109 in another thread.

 

Link to comment
Share on other sites

  • 3 months later...

Hi,

I save the "$aQueryDrive" Array to a file when _Drive_Eject succeeds
And then exit the script

With a new command script I want to restart the drive
So I load the identical array from the saved file with the function  _Drive_Restart($array)
but the drive wont restart

so I'm guessing that there are extra values that need to be saved and loaded when using this function

as When using both functions in 1 run everything runs as expected

Edit:

It seems that some of these DDK functions are possibly outdated and aren't recommended for use by newer ddk
functions For example: CM_Setup_DevNode


 

Edited by Deye
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...