symadis Posted October 19, 2007 Posted October 19, 2007 Hello,I have to update data on a huge quantity of usb keys.The goal is > when a usb key is detected, the script must erase the data on this key, and copy *.* from a specified directory to the key, eject the key and wait for the next key.I made a script, witch is a merge of ptrex's 'USB drive Monitor Example' and the arcker's 'AutoEjectIt'.Here is the script: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> #include <Misc.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 $chemin="c:\usbee\" $strComputer = "." $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2") $colEvents = $objWMIService.ExecNotificationQuery _ ("Select * From __InstanceOperationEvent Within 5 Where " _ & "TargetInstance isa 'Win32_LogicalDisk' and " _ & "TargetInstance.DriveType = 2" ) HotKeySet("{ESC}", "Terminer") ;~ ========================================================== ;~ ACTION ;~ ========================================================== While 1 $objEvent = $colEvents.NextEvent If $objEvent.TargetInstance.DriveType = 2 Then ;~ detecte les cles usb (2 = usb) Select Case $objEvent.Path_.Class()="__InstanceCreationEvent" ;~ detecte la creation d'un disque Consolewrite("Disque " & $objEvent.TargetInstance.DeviceId & "ajouté." & @CR) FileDelete($objEvent.TargetInstance.DeviceId &"\*.*") ;~ efface le contenu de la clé FileCopy($chemin &"*.*", $objEvent.TargetInstance.DeviceId &"\") ;~ copie les nouveaux fichiers $OpenVolume = $objEvent.TargetInstance.DeviceId ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf) ; <=== use of the autoejectit Case $objEvent.Path_.Class()="__InstanceDeletionEvent" Consolewrite("Disque " & $objEvent.TargetInstance.DeviceId & "supprimé."& @CR) EndSelect EndIf WEnd ;~ ========================================================== Func Terminer() Exit 0 EndFunc 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- The problem is i don't know where to put the HotKey to quit the program when i launch the program, it works, but when i press 'ESC' it only quit when a usb change has been detected. I would like to quit exactly when i want. i don't specialy need a hotkey, even a gui with a button is better but i don't know gui creation for the moment.- Does a script already exist for copying data on usb keys with shorter code?Thank you for your help and suggests,Loris
symadis Posted October 21, 2007 Author Posted October 21, 2007 Any ideas for the place of the hotkey?
PsaltyDS Posted October 21, 2007 Posted October 21, 2007 Any ideas for the place of the hotkey?Add this to the top of the script: Opt("TrayIconDebug", 1)And when you hit ESC and nothing happens, check what line of the script it's hung up on. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Sundance Posted October 23, 2007 Posted October 23, 2007 What happens if you insert a sleep(1000) statement into the while loop? Don't think that the while loop is some kind of blocking function but it's worth the try...
PsaltyDS Posted October 23, 2007 Posted October 23, 2007 What happens if you insert a sleep(1000) statement into the while loop? Don't think that the while loop is some kind of blocking function but it's worth the try...A While/WEnd loop is not blocking, but can slam your CPU usage. A shorter sleep, i.e. Sleep(20) or Sleep(100), is usually better to free up the CPU while still making the script responsive to events. A full second is slow enough to be perceptible lag to the user. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Sundance Posted October 23, 2007 Posted October 23, 2007 I know that 1 sec is to much to go productive with a program. It was only for testing purpose. In our domain we use some AutoItscripts with GUI's. I think the users would allready killed me if i used a sleep(1000)
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