NiVZ Posted November 5, 2008 Share Posted November 5, 2008 (edited) Hello, Wrote this little function to copy a file and show a progress bar as it copies. Any suggestions for improvement welcome. I've seen a few people ask for this so hope it helps. ** Edit: 06/11/2008 - If file can't be opened it now shows filename ** ** Edit: 06/11/2008 - Progressbar Subtext does not wrap so changed to show source and destination on seperate lines expandcollapse popup; Need to use a large file >2MB or add a Sleep(1000) to the For Loop $FileCopy = _CopyWithProgress("C:\Test.txt", "C:\TEMP\Test2.txt", 2048) ; Check return code to see if file copied correctly If $FileCopy = 0 Then MsgBox(0,"Copy Complete", "File Copy Successful.") Else MsgBox(16,"Copy Complete", "File Copy Failed.") EndIf Func _CopyWithProgress($inSource, $inDest, $ChunkSize = 2048) ; Function to copy a file showing a realtime progress bar ; ; By Paul Niven (NiVZ) ; ; 05/11/2008 ; ; Parameters: ; ; $inSource - Full path to source file ; $inDest - Full path to destination file (structure will be created if it does not exist ; $ChunkSize - (Optional) Size of chunks to copy - setting this higher makes large files copy faster ; Default chunk size is 2048 ; ; Returns 0 if copy is successful and 1 if it fails ; Open source file for BINARY reading $SourceFile = FileOpen($inSource, 16) ; Check that file open was successful If $SourceFile = -1 Then MsgBox(16, "Error", "Unable to open source file: " & $inSource) Exit EndIf ; Open destination file for BINARY writing , overwriting existing file and creating directory structure if it doesn't exist $DestFile = FileOpen($inDest, 26) ; Check that file open was successful If $SourceFile = -1 Then MsgBox(16, "Error", "Unable to open destination file: " & $inDest) Exit EndIf ; Get the size of the file we are going to copy $SourceSize = FileGetSize($inSource) ; Calculate how many chunks we need to copy $Chunks = $SourceSize / $ChunkSize ; Show the progress bar ProgressOn("File Copy", "Copying...", "Source: " & $inSource & @LF & "Dest: " & $inDest) ; Loop from 0 to number of chunks For $i = 0 to $Chunks ; Read the next chunk $Data = FileRead($SourceFile, $ChunkSize) ; Write the next chunk FileWrite($DestFile, $Data) ; Update the progress bar ProgressSet( (($i + 1) / $Chunks) * 100 ) Next ; Hide the progress bar ProgressOff() ; Close the source file FileClose($SourceFile) ; Close the destination file FileClose($DestFile) ; Check the file copy was successful $DestSize = FileGetSize($inDest) If $SourceSize = $DestSize Then Return 0 Else Return 1 EndIf EndFunc Edited November 6, 2008 by NiVZ Link to comment Share on other sites More sharing options...
279009500 Posted November 6, 2008 Share Posted November 6, 2008 It's Good! Link to comment Share on other sites More sharing options...
NiVZ Posted November 6, 2008 Author Share Posted November 6, 2008 Found another better way to do this on the german AutoIt forum, so I've modified my script again to use their method. It uses Kernel32.dll and a DllCallback so it's the Windows filesystem thats performing the copy. This also makes it copy faster.Credit to the guys on the german AutoIt site (hope they don't mind me modifying their code): http://www.autoit.de/index.php?page=Thread&postID=58875NiVZexpandcollapse popup; Need to use a large file >2MB $FileCopy = _CopyWithProgress("C:\test.txt", "C:\TEMP\Test.txt") ; Check return code to see if file copied correctly If $FileCopy = 0 Then MsgBox(0,"Copy Complete", "File Copy Successful.") Else MsgBox(16,"Copy Complete", "File Copy Failed.") EndIf Func _CopyWithProgress($inSource, $inDest) ; Function to copy a file showing a realtime progress bar ; ; By Paul Niven (NiVZ) ; ; 05/11/2008 ; ; Parameters: ; ; $inSource - Full path to source file ; $inDest - Full path to destination file (structure will be created if it does not exist ; ; Returns 0 if copy is successful and 1 if it fails ; ; ; Updates: ; ; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying ; - Now uses Kernal32 and DllCallBackRegister to provide faster copying ; Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3 ; See: http://www.autoit.de/index.php?page=Thread&postID=58875 ; Create dll hooks for Progress Update If Not IsDeclared("callback") Then Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') If Not IsDeclared("ptr") Then Local $ptr = DllCallbackGetPtr($callback) ; Check that file open was successful If Not FileExists($inSource) Then MsgBox(16, "Error", "Unable to open source file: " & $inSource) Exit EndIf ; Get Destination Directory - without filename $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1)) ; Check destination directory exists and create it if it doesn't try to create it If Not FileExists($DestDir) Then $DirCreate = DirCreate($DestDir) If $DirCreate = 0 Then MsgBox(16, "Error", "Could not create destination directory: " & $DestDir) EndIf ; Show the progress bar ProgressOn("File Copy", "Copying...", "Source: " & $inSource & @LF & "Dest: " & $inDest) $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0) ; Hide the progress bar ProgressOff() If $ret[0] <> 0 Then ; Success Return 0 Else ; Fail Return 1 EndIf EndFunc Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData) ProgressSet(Round($BytesTransferred / $FileSize * 100, 0)) EndFunc Link to comment Share on other sites More sharing options...
HeXetic Posted November 6, 2008 Share Posted November 6, 2008 Very nice but is there any way to copy the entire contents of the folder or maybe the folder itself? Link to comment Share on other sites More sharing options...
ProgAndy Posted November 6, 2008 Share Posted November 6, 2008 (edited) This is exactly, what the function in the German forum is designed for http://www.autoit.de/index.php?page=Thread&postID=58875Waht you want, is Example 1 ("Beispiel 1") or this one http://www.autoitscript.com/forum/index.php?showtopic=11888 Edited November 6, 2008 by ProgAndy *GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes Link to comment Share on other sites More sharing options...
shovetech Posted August 27, 2009 Share Posted August 27, 2009 I wrote this script for the same reasons as above, I needed a progress bar while copying a single file, but reading/writing using a custom function wasn't yielding good performance. I found a way to use the copy command and retrieve information about how much data was being copied by using ProcessGetStats: expandcollapse popupAutoItSetOption("MustDeclareVars", 1) ; Displays progress bar when copying a single file If ($CmdLine[0] < 2) Then MsgBox(0, "Error", "You must specify both source and destination files") Exit EndIf Global $helpmsg $helpmsg = "CopyFileProgress.exe [options] source destination" & @CRLF _ & " options:" & @CRLF _ & " /y = suppress prompt to overwrite destination file" & @CRLF _ & " /title:<title> = set title of copy dialog box" & @CRLF _ & " source = source file" & @CRLF _ & " destination = destination file" & @CRLF Dim $forceoverwrite = 0 Dim $title = "Copying files..." Dim $source = "" Dim $destination = "" Dim $cmdopts = $CmdLine ; Loop through command args for switches If ($cmdopts[0] > 2) Then For $a = 1 to ($cmdopts[0] - 2) Select Case StringLower($cmdopts[$a]) = "/y" $forceoverwrite = 1 case StringLower(StringLeft($cmdopts[$a], 7)) = "/title:" $title = StringSplit($cmdopts[$a], ":") $title = $title[2] case $cmdopts[$a] = "/?" MsgBox(0, "Help", $helpmsg) Exit Case Else MsgBox(0, "Help", $helpmsg) Exit EndSelect Next EndIf $source = $cmdopts[($cmdopts[0] -1)] $destination = $cmdopts[($cmdopts[0])] ; Check that source file exist If Not (FileExists($source)) Then MsgBox(0, "Error", $source & " file does not exist.") Exit EndIf ; If destination exist, ask if ok to overwrite If (FileExists($destination)) Then If ($forceoverwrite = 0) Then If (MsgBox(260, "Overwrite", $destination & " already exists. Overwrite?") = 7) Then Exit EndIf EndIf If Not (FileDelete($destination)) Then MsgBox(0, "Error", "Could not copy to " & $destination) Exit EndIf EndIf ; Get source file size Dim $sourcesize = FileGetSize($source) Dim $sourceprefix = 0 Dim $sourcesuffix = "" getByteSuffix($sourcesize, $sourceprefix, $sourcesuffix) ; Copy file, querying process for IO bytes written Dim $starttime = TimerInit() Dim $destinationsize = 0 Dim $progress = 0 Dim $spin = "|" ; Display progress bar and run copy command ProgressOn($title, "Please wait...", "Preparing...", -1, -1, 16) Dim $pid = Run(@ComSpec & " /c copy /y " & chr(34) & $source & chr(34) & " " & Chr(34) & $destination & Chr(34), @ScriptDir, @SW_HIDE) If ($pid = 0) Then MsgBox(0, "Error", "Error copying file") Exit EndIf While (ProcessExists($pid)) Local $procstats = ProcessGetStats($pid, 1) If (IsArray($procstats) And UBound($procstats) > 4) Then $destinationsize = $procstats[4] If ($destinationsize = 0) Then ProgressSet(0, "", "Calculating size ...") Else $progress = Int(($destinationsize / $sourcesize) * 100) For $x = 1 to 10 progressUpdate($progress, $destinationsize) Sleep(100) Next EndIf EndIf WEnd ; After copy finished, display destination file size $destinationsize = FileGetSize($destination) $progress = Int(($destinationsize / $sourcesize) * 100) progressUpdate($progress, $destinationsize) Sleep(500) ProgressOff() ; Compare source file size and destination file size If ($sourcesize <> $destinationsize) Then MsgBox(0, "Error", "Source and destination file sizes are different. Could not copy.") Exit EndIf Exit Func progressUpdate($progress, $destsize) If ($progress > 100) Then $progress = 100 EndIf Local $byteprefix = 0 Local $bytesuffix = "" If (StringLen($spin) > 50) Then $spin = StringRight($spin, 1) Switch StringRight($spin, 1) Case "|" $spin = StringReplace($spin, "|", "/", 1, 2) Case "/" $spin = StringReplace($spin, "/", "-", 1, 2) Case "-" $spin = StringReplace($spin, "-", "\", 1, 2) Case "\" $spin = StringReplace($spin, "\", ".", 1, 2) & ".|" EndSwitch getByteSuffix($destsize, $byteprefix, $bytesuffix) ProgressSet($progress, "Source: " & $source & @LF & "Destination: " & $destination & @LF & $spin, Round($byteprefix, 2) & " " & $bytesuffix & " / " & Round($sourceprefix, 2) & " " & $sourcesuffix) EndFunc Func getByteSuffix ($bytes, ByRef $byteprefix, ByRef $bytesuffix) $byteprefix = $bytes $bytesuffix = "bytes" If ($byteprefix > 1024) Then $byteprefix = ($byteprefix / 1024) $bytesuffix = "KB" If ($byteprefix > 1024) Then $byteprefix = ($byteprefix / 1024) $bytesuffix = "MB" If ($byteprefix > 1024) Then $byteprefix = ($byteprefix / 1024) $bytesuffix = "GB" If ($byteprefix > 1024) Then $byteprefix = ($byteprefix / 1024) $bytesuffix = "TB" If ($byteprefix > 1024) Then $byteprefix = ($byteprefix / 1024) $bytesuffix = "PB" EndIf EndIf EndIf EndIf EndIf EndFunc Hope this helps, Doug Link to comment Share on other sites More sharing options...
Angrysteel Posted September 16, 2009 Share Posted September 16, 2009 (edited) oops Edited September 16, 2009 by Angrysteel Link to comment Share on other sites More sharing options...
surreal Posted October 5, 2009 Share Posted October 5, 2009 i understand thta it was stated before that this scipt will work for copy the entire contents of the folder or maybe the folder itself. however i cannot get it to work, and i cannot read german, lol. thanks for your help. expandcollapse popup$temp1 = "C:\test\temp1\*.*" $temp2 = "C:\test\temp2" ; Need to use a large file >2MB $FileCopy = _CopyWithProgress($temp1, $temp2) ; Check return code to see if file copied correctly If $FileCopy = 0 Then MsgBox(0,"Copy Complete", "File Copy Successful.") Else MsgBox(16,"Copy Complete", "File Copy Failed.") EndIf Func _CopyWithProgress($inSource, $inDest) ; Function to copy a file showing a realtime progress bar ; ; By Paul Niven (NiVZ) ; ; 05/11/2008 ; ; Parameters: ; ; $inSource - Full path to source file ; $inDest - Full path to destination file (structure will be created if it does not exist ; ; Returns 0 if copy is successful and 1 if it fails ; ; ; Updates: ; ; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying ; - Now uses Kernal32 and DllCallBackRegister to provide faster copying ; Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3 ; See: http://www.autoit.de/index.php?page=Thread&postID=58875 ; Create dll hooks for Progress Update If Not IsDeclared("callback") Then Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') If Not IsDeclared("ptr") Then Local $ptr = DllCallbackGetPtr($callback) ; Check that file open was successful If Not FileExists($inSource) Then MsgBox(16, "Error", "Unable to open source file: " & $inSource) Exit EndIf ; Get Destination Directory - without filename $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1)) ; Check destination directory exists and create it if it doesn't try to create it If Not FileExists($DestDir) Then $DirCreate = DirCreate($DestDir) If $DirCreate = 0 Then MsgBox(16, "Error", "Could not create destination directory: " & $DestDir) EndIf ; Show the progress bar ProgressOn("File Copy", "Copying...", "Source: " & $inSource & @LF & "Dest: " & $inDest) $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0) ; Hide the progress bar ProgressOff() If $ret[0] <> 0 Then ; Success Return 0 Else ; Fail Return 1 EndIf EndFunc Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData) ProgressSet(Round($BytesTransferred / $FileSize * 100, 0)) EndFunc i get an error: File Copy Failed Link to comment Share on other sites More sharing options...
dantay9 Posted October 5, 2009 Share Posted October 5, 2009 Yahoo BabelFish should at least give you an idea about what is being discussed there. You can translate whole web pages on BabelFish. Link to comment Share on other sites More sharing options...
surreal Posted October 5, 2009 Share Posted October 5, 2009 Yahoo BabelFish should at least give you an idea about what is being discussed there. You can translate whole web pages on BabelFish.good idea but does not work to well with forums, not for me. i do notice that they are talking about _MultiFileCopy not _CopyWithProgress. i just need a single copy but the entire folder. i like the idea of file details and speed performance. Link to comment Share on other sites More sharing options...
Angrysteel Posted October 6, 2009 Share Posted October 6, 2009 i understand thta it was stated before that this scipt will work for copy the entire contents of the folder or maybe the folder itself. however i cannot get it to work, and i cannot read german, lol. thanks for your help. expandcollapse popup$temp1 = "C:\test\temp1\*.*" $temp2 = "C:\test\temp2" ; Need to use a large file >2MB $FileCopy = _CopyWithProgress($temp1, $temp2) ; Check return code to see if file copied correctly If $FileCopy = 0 Then MsgBox(0,"Copy Complete", "File Copy Successful.") Else MsgBox(16,"Copy Complete", "File Copy Failed.") EndIf Func _CopyWithProgress($inSource, $inDest) ; Function to copy a file showing a realtime progress bar ; ; By Paul Niven (NiVZ) ; ; 05/11/2008 ; ; Parameters: ; ; $inSource - Full path to source file ; $inDest - Full path to destination file (structure will be created if it does not exist ; ; Returns 0 if copy is successful and 1 if it fails ; ; ; Updates: ; ; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying ; - Now uses Kernal32 and DllCallBackRegister to provide faster copying ; Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3 ; See: http://www.autoit.de/index.php?page=Thread&postID=58875 ; Create dll hooks for Progress Update If Not IsDeclared("callback") Then Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') If Not IsDeclared("ptr") Then Local $ptr = DllCallbackGetPtr($callback) ; Check that file open was successful If Not FileExists($inSource) Then MsgBox(16, "Error", "Unable to open source file: " & $inSource) Exit EndIf ; Get Destination Directory - without filename $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1)) ; Check destination directory exists and create it if it doesn't try to create it If Not FileExists($DestDir) Then $DirCreate = DirCreate($DestDir) If $DirCreate = 0 Then MsgBox(16, "Error", "Could not create destination directory: " & $DestDir) EndIf ; Show the progress bar ProgressOn("File Copy", "Copying...", "Source: " & $inSource & @LF & "Dest: " & $inDest) $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0) ; Hide the progress bar ProgressOff() If $ret[0] <> 0 Then ; Success Return 0 Else ; Fail Return 1 EndIf EndFunc Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData) ProgressSet(Round($BytesTransferred / $FileSize * 100, 0)) EndFunc i get an error: File Copy Failed Yeah me too, Cannot figure it out yet. Link to comment Share on other sites More sharing options...
shovetech Posted December 18, 2009 Share Posted December 18, 2009 I've updated my above posted script here: http://www.autoitscript.com/forum/index.php?showtopic=15384&st=0&p=755467&#entry755467 Link to comment Share on other sites More sharing options...
digitalteck Posted February 1, 2013 Share Posted February 1, 2013 When I run the script I get unable to open file. Here is the script with my file path.I tried using a txt JPG and MP3 file thinking it was a file format issue.Am I missing something ?#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.8.1 Author: myName Script Function: Template AutoIt script.#ce ----------------------------------------------------------------------------; Script Start - Add your code below here$Test1 = "C:\Users\John\Desktop\Test1\1.mp3"$Test2 = "C:\Users\John\Desktop\Test2"; Need to use a large file >2MB$FileCopy = _CopyWithProgress($Test1, $Test2); Check return code to see if file copied correctlyIf $FileCopy = 0 Then MsgBox(0,"Copy Complete", "File Copy Successful.")Else MsgBox(16,"Copy Complete", "File Copy Failed.")EndIfFunc _CopyWithProgress($inSource, $inDest); Function to copy a file showing a realtime progress bar;; By Paul Niven (NiVZ);; 05/11/2008;; Parameters:;; $inSource - Full path to source file; $inDest - Full path to destination file (structure will be created if it does not exist;; Returns 0 if copy is successful and 1 if it fails;;; Updates:;; 06/11/2008 - Now shows SOURCE and DEST on seperate lines while copying; - Now uses Kernal32 and DllCallBackRegister to provide faster copying; Kernal32 and DllCallBackRegister taken from _MultiFileCopy.au3; See: http://www.autoit.de/index.php?page=Thread&postID=58875; Create dll hooks for Progress Update If Not IsDeclared("callback") Then Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') If Not IsDeclared("ptr") Then Local $ptr = DllCallbackGetPtr($callback); Check that file open was successful If Not FileExists($inSource) Then MsgBox(16, "Error", "Unable to open source file: " & $inSource) Exit EndIf; Get Destination Directory - without filename $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1)); Check destination directory exists and create it if it doesn't try to create it If Not FileExists($DestDir) Then $DirCreate = DirCreate($DestDir) If $DirCreate = 0 Then MsgBox(16, "Error", "Could not create destination directory: " & $DestDir) EndIf; Show the progress bar ProgressOn("File Copy", "Copying...", "Source: " & $inSource & @LF & "Dest: " & $inDest) $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0); Hide the progress bar ProgressOff() If $ret[0] <> 0 Then ; Success Return 0 Else ; Fail Return 1 EndIfEndFuncFunc __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData) ProgressSet(Round($BytesTransferred / $FileSize * 100, 0))EndFunc Link to comment Share on other sites More sharing options...
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