mrider Posted September 2, 2005 Share Posted September 2, 2005 Here's my problem - I'm copying a modestly large file across a WAN link, and I'd like to provide the user with a progress bar. I've tried the following methods: FileCopy( $fileName, ".", 1 ) and RunWait( @COMSPEC & ' /C copy "' & $fileName & '" .', "", @SW_HIDE ) and with both methods, the file reports it's full size immediately. So I can't figure out how to tell how much of the file has actually copied across the network. If the file were to report the amount that's actually copied, then I could do a bit of simple math to create a progress bar. I know I could use Windows copy which would natively create a progress bar, but then the user would know where the file is coming from. This isn't necessarily a problem per se (it's not top secret or anything like that), it is an implementation detail that I'd rather not confuse my users with. We're all on Win2K pro if that makes a difference... Any suggestions? How's my riding? Dial 1-800-Wait-There Trying to use a computer with McAfee installed is like trying to read a book at a rock concert. Link to comment Share on other sites More sharing options...
Valuater Posted September 2, 2005 Share Posted September 2, 2005 maybe take a look at thishttp://www.autoitscript.com/forum/index.ph...opic=11888&hl=#hope it helps8) Link to comment Share on other sites More sharing options...
Gigglestick Posted September 2, 2005 Share Posted September 2, 2005 I haven't tried this, but I think you could do it something like this: 1. Use FileFindFirstFile and FileFindNextFile (or _RunDOS("dir /a/s/b ' & $fullpath) and capture the output, looking for "Total Files Listed:" and then taking the number of files for your maximum in the progress bar. 2. Then you can run your CMD with Run instead of RunWait and loop, watching StdoutRead and counting the files, updating the progress bar for each file that is output to StdOut. If you're interested, I'll find a way to do all this with COM objects. I ran across some similar code in MSDN a week or so back anyway. My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
Gigglestick Posted September 2, 2005 Share Posted September 2, 2005 (edited) maybe take a look at thishttp://www.autoitscript.com/forum/index.ph...opic=11888&hl=#hope it helps8)<{POST_SNAPBACK}>Nevermind my comment. Go with this!EDIT: Actually, I personally don't care for the Windows Explorer copy method. I'd rather have my own progress dialog. mrider might like your solution, though. Thanks. Edited September 2, 2005 by c0deWorm My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
mrider Posted September 2, 2005 Author Share Posted September 2, 2005 Wow. It sure looks like the copy with progress script will work. Thanks * 1,000,000!! How's my riding? Dial 1-800-Wait-There Trying to use a computer with McAfee installed is like trying to read a book at a rock concert. Link to comment Share on other sites More sharing options...
mrider Posted September 2, 2005 Author Share Posted September 2, 2005 Oh - regarding post #3. Thanks for the suggestion, but there's only one file. That's the problem. If there were multiple files, I'd just poll the directory and run the progress as: int(( numFilesNeeded / numFilesFound ) * 100 ). I was trying to do something like: int(( finalFileSize / currentFileSize ) * 100 ) Unfortunately it reports it's final size immediately... How's my riding? Dial 1-800-Wait-There Trying to use a computer with McAfee installed is like trying to read a book at a rock concert. Link to comment Share on other sites More sharing options...
Gigglestick Posted September 2, 2005 Share Posted September 2, 2005 Unfortunately it reports it's final size immediately...<{POST_SNAPBACK}>If the file's too small for AutoIt to show a progress, then how is it possible that the Windows Explorer dialog shows at all?! I don't think the Explorer "Copying..." window even shows unless it knows it's going to show a progress for at least a second or more.How big is this file you're copying? My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
mrider Posted September 2, 2005 Author Share Posted September 2, 2005 The ultimate file is moderately large - say 5Mb. Considering the WAN speed, it'll probably take around a minute to download. For testing purposes, I'm copying a 400Mb file (that's right 400 megabytes) so that I have plenty of time to see a progress bar. It's a much faster link, but the copy time is about the same. Roughly a minute.When I use Windows Explorer, I get a progress bar showing progress on that one file. As I said, I could force a Windows Explorer window open, navigate to the directory, select the file, select copy, navigate to the destination directory, select paste - and I'd get a progress bar. IMHO that leaves too many things that the user could screw up though.When I use AutoIt's FileCopy I get no progress bar - even though it takes about a minute. Using both AutoIt's file copy and the DOS copy command, I can't ask for current size of the destination file - because both Windows Explorer and AutoIt's FileGetSize reports the final size immediately - even though there's still stuff to copy.It looks like the link provided won't work. When I run the scipt I get the following error message:Line 37Â (File "C:\Program Files\AutoIt3\Include\FileCopy.au3"):$SHFILEOPSTRUCT = DllStructCreate("int;uint;ptr;ptr;uint;int;ptr;ptr")$SHFILEOPSTRUCT = ^ ERRORError: Unknown function name.So back to square one... How's my riding? Dial 1-800-Wait-There Trying to use a computer with McAfee installed is like trying to read a book at a rock concert. Link to comment Share on other sites More sharing options...
mrider Posted September 2, 2005 Author Share Posted September 2, 2005 I hate to admit defeat, but it looks like I'm done. I tried the following, thinking that I could watch the progress as the bytes go by one at a time, but the script doesn't copy the file faithfully. while 1 $char = FileRead( $fileIN, 1 ); If @error = -1 Then ExitLoop; FileWrite( $fileOUT, $char ); If @error = -1 Then ExitLoop; WEnd Probably because it's a binary file, and AutoIt tries to read an actual character. Maybe I can convince the powers that be to put it on a web or ftp server available only internally. I bet InetGet reports correctly. How's my riding? Dial 1-800-Wait-There Trying to use a computer with McAfee installed is like trying to read a book at a rock concert. Link to comment Share on other sites More sharing options...
Sokko Posted September 2, 2005 Share Posted September 2, 2005 It looks like the link provided won't work. When I run the scipt I get the following error message:You'll need the latest beta version of AutoIt to make it work. A lot of user-defined functions use DllStruct functions, which are not available in the current production version. Link to comment Share on other sites More sharing options...
Gigglestick Posted September 2, 2005 Share Posted September 2, 2005 Have you considered Robocopy? Check out the Windows 2003 Resource Kit for the latest version "XP010". I think you can capture the percentage via StdoutRead and just make your progress bar show that percentage. Plus I personally think Robocopy is faster and more reliable than Explorer.... at the very least its progress per file is more helpful. My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
mrider Posted September 2, 2005 Author Share Posted September 2, 2005 Well, the latest beta worked with my code. And I get a nice progress bar. I'm downloading the RK tools now, and I'll take a look at Robocopy. I also tested InetGet, and it in fact correctly displays the file size as it goes.Thanks everyone - I really appreciate the help. I don't know what I'll use as a final solution, but I have three different things that at least do something. How's my riding? Dial 1-800-Wait-There Trying to use a computer with McAfee installed is like trying to read a book at a rock concert. Link to comment Share on other sites More sharing options...
Matt Houston Posted April 27, 2006 Share Posted April 27, 2006 ...I think you can capture the percentage via StdoutRead and just make your progress bar show that percentage. Plus I personally think Robocopy is faster and more reliable than Explorer.... at the very least its progress per file is more helpful.Hi Everyone,has somebody tried to use robocopy in order to produce a progressbar? I tried to use it in combination with StdoutRead which is working fine - but i don't have any idea how to parse the captured stuff.Is it possible to "StdoutRead line by line"?Greetings!MattHouston Link to comment Share on other sites More sharing options...
shovetech Posted December 18, 2009 Share Posted December 18, 2009 (edited) Like others, I too wanted a way to display a progress bar while copying a file. Unfortunately, since I'm using WinPE 2.0, I can't get a native explorer-type progress dialog, as the necessary DLL's aren't included. I wrote my own that only relies on the 'copy' command with any version of Windows (including WinPE). Attached is the version I wrote. It's meant to be compiled an run as a stand-alone executable. Any improvements and suggestions would be appreciated. Update: v1.1.6: Fixed a bug where copying to/from the root of a drive (ex. c:\, d:\, etc.) was handled incorrectly. v1.1.5: Fixed a bug where if /k switch is given and file transfer was too fast, peak speed would show 0 bytes/s. v1.1.4: Fixed a bug where empty directories were reporting failure, although copy operation was successful. v1.1.3: adds two progress bars for current progress, and total progress if /k switch is given, shows peak (highest) transfer rate during operation v1.1.0: supports copying directoriesCopyFileProgress_v1.1.6.au3 Edited October 10, 2010 by shovetech Link to comment Share on other sites More sharing options...
parsifal Posted September 26, 2010 Share Posted September 26, 2010 Mmm, if i try to copy in a root of hard disk five an error (Could not replace g:\). my test is : CopyFileProgress_v1.1.5.exe /k E:\Test g: Something wrong? Link to comment Share on other sites More sharing options...
parsifal Posted October 10, 2010 Share Posted October 10, 2010 Bug: sample: CopyFileProgress_v1.1.5.exe /k E:\test c:\pippo where test is test--> Folder -->Subfolder --> File copyng files (works fine) CopyFileProgress make in the root of E:\ the folder "pippo" with the structure of folder "test" without files. Link to comment Share on other sites More sharing options...
shovetech Posted October 10, 2010 Share Posted October 10, 2010 Mmm, if i try to copy in a root of hard disk five an error (Could not replace g:\).my test is : CopyFileProgress_v1.1.5.exe /k E:\Test g:Something wrong?Thank you for the feedback. I updated to v1.1.6 which fixes this issue. Also, make sure you end the drive letter with a backslash (ex. g:\) when specifying source/destination. Link to comment Share on other sites More sharing options...
jp10558 Posted April 29, 2011 Share Posted April 29, 2011 Thank you for the feedback. I updated to v1.1.6 which fixes this issue. Also, make sure you end the drive letter with a backslash (ex. g:\) when specifying source/destination.Is there a UDF version of this?Also, I'm seeing a bug with the total amount to copy / progress bar display when copying a folder with several nested folders in it from a mapped network drive to a local folder. My first test is already at 62 MB / 27 MB ... Link to comment Share on other sites More sharing options...
Chimaera Posted April 29, 2011 Share Posted April 29, 2011 Have you considered Robocopy? Check out the Windows 2003 Resource Kit for the latest version "XP010". I think you can capture the percentage via StdoutRead and just make your progress bar show that percentage. Plus I personally think Robocopy is faster and more reliable than Explorer.... at the very least its progress per file is more helpful.XP010 is the early version best and most useful version Ive found through much practice with robocopy is XP026 (XP027 is vista and above only) If Ive just helped you ... miracles do happen. Chimaera CopyRobo() * Hidden Admin Account Enabler * Software Location From Registry * Find Display Resolution * _ChangeServices() Link to comment Share on other sites More sharing options...
digitalteck Posted February 1, 2013 Share Posted February 1, 2013 I downloaded the file from below to try since I could not get the one on the other post to work.Here is my error I get Pic attached. Also I hope I put my Sourse and Dest link on the right line 52 and 53.; Copies a file/directory using the native Windows copy command, but; displays statistics while copying.; The only dependency is 'copy.exe', which is available on every Windows system.; Works especially good in a WinPE environment where no copy GUI is available.;; v1.1.6:; - Fixed bug: Copying to/from the root directory of a drive (c:\, d:\, etc.); was handled incorrectly.; v1.1.5:; - Fixed bug: Peak speed would display 0 bytes/s for small files; v1.1.4:; - Fixed bug: empty directories would report failure; v1.1.3:; - Add current file progress bar (above total progress bar); - Add check for file/dir size after copy operation is complete; - Add 'Peak speed' on display after copy operation is complete; v1.1.2:; - Add internal byte decimal place ($bytedecimalplace) global var; for displaying any byte measurement data; v1.1.1:; - Shorten path and file names on GUI display; v1.1.0:; - Adds copying directory support; - Re-write some code and better organized code; v1.0.0:; - Initial release;#include <GUIConstants.au3>#include <GUIConstantsEx.au3>#include <ProgressConstants.au3>#include <ButtonConstants.au3>#Include <GuiButton.au3>#Include <File.au3>Opt("GUICoordMode", 0)Opt("GUIOnEventMode", 1)Opt("MustDeclareVars", 1); Debug Mode; If debug=1, then Debug Mode is turned on. This produces a lot; of messages for debugging purposes.; NOTE: This setting should be 0 for production use.Global $debug = 0Global $invalidChars = "/ : * ? < > | " & chr(34)Global $forceoverwrite = 0Global $showcopytime = 0Global $noerror = 0Global $displayhelp = 0Global $title = "Copying files..."Global $source = "C:\Users\John\Desktop\Test"Global $destination = "C:\Users\John\Desktop\Test2"Global $cmdopts = $CmdLineGlobal $sourcetype = ""Global $progress = 0Global $fail = ""If ($cmdopts[0] = 0) Then displayHelp() ExitEndIf; Loop through command args for switchesFor $a = 1 to ($cmdopts[0]) Select Case StringLower($cmdopts[$a]) = "/y" $forceoverwrite = 1 Case StringLower($cmdopts[$a]) = "/noerror" $noerror = 1 case StringLower(StringLeft($cmdopts[$a], 7)) = "/title:" $title = StringSplit($cmdopts[$a], ":") If ($title[2] <> "") Then $title = $title[2] Else ; set to empty $title = "" EndIf case StringLower($cmdopts[$a]) = "/title" ; if no valid title is given, continue as normal case StringLower($cmdopts[$a]) = "/k" $showcopytime = 1 case $cmdopts[$a] = "/?" $displayhelp = 1 Case Else If ($a = ($cmdopts[0] - 1)) Then $source = $cmdopts[($cmdopts[0] -1)] ElseIf ($a = $cmdopts[0]) Then $destination = $cmdopts[($cmdopts[0])] Else $displayhelp = 1 EndIf EndSelectNext; If displayhelp = 1, display help messageIf ($displayhelp = 1) Then displayHelp() ExitEndIf; Must specify both source and destinationIf ($source = "" Or $destination = "") Then errorMsg ("You must specify both source and destination files") ExitEndIf; Check for illegal characters in sourceIf ( validPath(getDirectory($source)) = 0 Or _ validPath(getFilename($source)) = 0 ) Then errorMsg ("Source file name invalid. File name cannot contain: " & @LF & $invalidChars) ExitEndIf; Convert any relative paths into absolute paths$source = _PathFull($source)$destination = _PathFull($destination); Check that source file existIf (FileExists($source)) Then If (StringInStr(FileGetAttrib($source), "D", 0) = 0) Then ; if source is a file, (not directory) $sourcetype = "file" debugMsg ("Source is a file") ; if destination is directory, append source filename If (StringInStr(FileGetAttrib($destination), "D", 0)) Then If (StringRight($destination, 1) = "\") Then ; append only filename to destination, no \ required $destination = $destination & getFilename($source) Else ; append \ + source filename to destination $destination = $destination & "\" & getFilename($source) EndIf debugMsg ("New destination " & $destination) EndIf Else ; if source is a diretory $sourcetype = "dir" ; if destination is <drive>:\ append full source directory If (getDirectory($destination) & getFilename($destination) = "\") Then $destination = getDrive($destination) & getDirectory($source) & getFilename($source) EndIf debugMsg ("Source is a directory") EndIfElse ; if source does not exist errorMsg ($source & " does not exist.") ExitEndIf; Check for illegal characters in destinationIf ( validPath(getDirectory($destination)) = 0 Or _ validPath(getFilename($destination)) = 0 ) Then errorMsg ("Destination file name invalid. File name cannot contain: " & @LF & $invalidChars) ExitEndIf; Check if source and destination are the sameIf (StringUpper($source) = StringUpper($destination)) Then errorMsg ("Source and destination are the same!") ExitEndIf; If destination exist, ask if ok to overwriteIf (FileExists($destination)) Then If ($forceoverwrite = 0) Then ; if response is No.. If (MsgBox(4 + 32 + 256, "Overwrite", $destination & " already exists. Overwrite?") = 7) Then Exit EndIf EndIf ; remove destination ; if destination is a directory, use DirRemove ; if destination is a file, use FileDelete If (StringInStr(FileGetAttrib($destination), "D", 0)) Then ; remove destination directory debugMsg ("Removing directory " & $destination) If (DirRemove ($destination, 1) = 0) Then errorMsg ("Could not replace " & $destination) Exit EndIf Else ; remove destination file debugMsg ("Removing file " & $destination) If (FileDelete($destination) = 0) Then errorMsg ("Could not replace " & $destination) Exit EndIf EndIfEndIf; Global GUI controlsGlobal $guiwin, $cancelbtn, $progressbar, $currentprogressbar, $msg, $index, $lblbytesGlobal $lbltransfer, $lblspin, $lblfiles, $lblcurrentfile, $lbltime, $lbltotalprogressGlobal $spin = "|"Global $progresssubstring = ""Global $pid = 0Global $sourcesize = 0Global $destinationsize = 0Global $copyfiletime ; total time for copy operationGlobal $statusrefresh = 1300 ; calulate time remain, speed, etc. intervalGlobal $progresstimerGlobal $progressrefresh = 1000 ; display stats (time est/remain, speed) intervalGlobal $spintimerGlobal $spinrefresh = 170 ; display top bar (bytes and spin) intervalGlobal $bytedecimalplace = 2Global $peakspeed = 0$guiwin = GUICreate($title, 300, 200)$lblbytes = GUICtrlCreateLabel("Preparing...", 5, 5, 290)$lblcurrentfile = GUICtrlCreateLabel("Cur. Source: " & $source & @LF & "Cur. Destination: " & $destination , -1, 21, 290, 26)$currentprogressbar = GUICtrlCreateProgress(-1, 20, 290, 20, $PBS_SMOOTH)$lbltotalprogress = GUICtrlCreateLabel("Total progress", -1, 21, 290, 26)$progressbar = GUICtrlCreateProgress(-1, 20, 290, 20, $PBS_SMOOTH)$lblfiles = GUICtrlCreateLabel("Source: " & $source & @LF & "Destination: " & $destination , -1, 21, 290, 30)$lbltime = GUICtrlCreateLabel("", -1, 31, 290, 13)$lbltransfer = GUICtrlCreateLabel("", -1, 14, 290, 13)$cancelbtn = GUICtrlCreateButton("Cancel", 230, 15, 60)GUICtrlSetOnEvent($cancelbtn, "cancelop")GUISetOnEvent($GUI_EVENT_CLOSE, "cancelop")GUISetState(@SW_SHOW); if source is file, copy file; if source is directory, copy directory; Get size of sourceGUICtrlSetData($lblbytes, "Calculating size ...") If ($sourcetype = "file") Then $sourcesize = FileGetSize($source)ElseIf ($sourcetype = "dir") Then $sourcesize = DirGetSize($source) EndIfIf ($sourcesize = -1) Then errorMsg ("Could not retrieve size of " & $source) ExitEndIfdebugMsg ($source & " size: " & $sourcesize); Start the timer(s)$copyfiletime = TimerInit()$progresstimer = TimerInit(); Start copyingIf ($sourcetype = "file") Then If (copyFile($source, $destination) = 0) Then $fail = $fail & @LF & $destination EndIfElseIf ($sourcetype = "dir") Then ; if any file fails to copy, $fail is updated inside copyDir copyDir ($source, $destination)EndIf; Stop timer$copyfiletime = TimerDiff($copyfiletime); Get size of destinationGUICtrlSetData($lblbytes, "Checking size ...")If ($sourcetype = "file") Then $destinationsize = FileGetSize($destination)ElseIf ($sourcetype = "dir") Then $destinationsize = DirGetSize($destination)EndIfIf ($destinationsize = -1) Then errorMsg ("Could not retrieve size of " & $destination) ExitEndIfdebugMsg ($destination & " size: " & $destinationsize); If destinationsize <> sourcesize, warn userIf ($destinationsize <> $sourcesize) Then errorMsg ("Source and destination sizes are different.")EndIf; If fail is not empty, warn userIf ($fail <> "") Then errorMsg ("Failed to copy:" & @LF & $fail)EndIf; If /k switch was given, leave dialog openIf ($showcopytime = 1) Then ; rename and re-map the "Cancel" button to "Close" GUICtrlSetOnEvent($cancelbtn, "closeop") GUISetOnEvent($GUI_EVENT_CLOSE, "closeop") _GUICtrlButton_SetText ($cancelbtn, "Close") ; Update display status Local $destbyteprefix = 0 Local $destbytesuffix = "" Local $peakspeedprefix = 0 Local $peakspeedsuffix = "" getByteSuffix($destinationsize, $destbyteprefix, $destbytesuffix) getByteSuffix($peakspeed, $peakspeedprefix, $peakspeedsuffix) GUICtrlSetData($lblbytes, "Total transfered: " & Round($destbyteprefix, $bytedecimalplace) & " " & $destbytesuffix) GUICtrlSetData ($lblcurrentfile, "Current file:") GUICtrlSetData($lblfiles, "Source: " & shortText($source) & @LF & "Destination: " & shortText($destination)) GUICtrlSetData($lbltransfer, "Peak speed: " & Round($peakspeedprefix, $bytedecimalplace) & " " & $peakspeedsuffix & "/s") GUICtrlSetData($lbltime, "Total time: " & getTime($copyfiletime / 1000)) while (1) Sleep (1000) WEndEndIf; End programExitFunc killproc($pid) ; kills a process While (ProcessExists($pid)) ProcessClose($pid) WEndEndFuncFunc closeop() GUISetState(@SW_HIDE) ExitEndFuncFunc cancelop() ; if copy is in progress, kill proccess and remove destination If (MsgBox(4 + 32 + 256, "Copy File Progress", "Are you sure you want to cancel file copy?") = 6) Then GUICtrlSetState($cancelbtn, $GUI_DISABLE) WinSetTitle($guiwin, "", $title & " canceling...") GUICtrlSetData($lblbytes, "Canceling.....") GUICtrlSetData($lbltransfer, "") GUICtrlSetData($lbltime, "") If ($pid > 0) Then killproc($pid) If (FileExists($destination)) Then GUICtrlSetData($lblbytes, "Removing " & $destination & " .....") If ($sourcetype = "file") Then debugMsg ("Removing file " & $destination) FileDelete($destination) ElseIf ($sourcetype = "dir") Then debugMsg ("Removing directory " & $destination) DirRemove($destination, 1) EndIf EndIf Exit EndIfEndFuncFunc progressUpdate($insourcesize, $indestsize, $intransferspeed, $intimeremaining) ; Don't let progress bar above 100% If ($progress > 100) Then $progress = 100 EndIf Local $sourceprefix = 0 Local $sourcesuffix = "" getByteSuffix($insourcesize, $sourceprefix, $sourcesuffix) Local $byteprefix = 0 Local $bytesuffix = "" getByteSuffix($indestsize, $byteprefix, $bytesuffix) Local $speedprefix = 0 Local $speedsuffix = "" getByteSuffix($intransferspeed, $speedprefix, $speedsuffix) Local $speedstring = "" Local $timestring = "" ; set current speed If ($intransferspeed > 0) Then $speedstring = "Speed: " & Round($speedprefix, $bytedecimalplace) & " " & $speedsuffix & "/s" EndIf $progresssubstring = $speedstring ; set elapsed time and time remaining $timestring = "Elapsed: " & getTime(timerdiff($copyfiletime) / 1000) If (Int($intimeremaining) > 0) Then $timestring = $timestring & " - Remaining: " & getTime($intimeremaining) EndIf ; display spin at specified refresh time If (TimerDiff($spintimer) > $spinrefresh) Then $spintimer = TimerInit() ; Display spin 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 GUICtrlSetData($lblbytes, Round($byteprefix, $bytedecimalplace) & " " & $bytesuffix & " / " & Round($sourceprefix, $bytedecimalplace) & " " & $sourcesuffix & " " & $spin) EndIf ; only refresh at specified interval. this should minimize any flickering If (TimerDiff($progresstimer) > $progressrefresh) Then ; restart progress timer $progresstimer = TimerInit() GUICtrlSetData($progressbar, $progress) If ($intransferspeed > 0) Then GUICtrlSetData($lbltransfer, $progresssubstring) EndIf GUICtrlSetData($lbltime, $timestring) WinSetTitle($guiwin, "", $title & " " & $progress & " %") ElseIf ($progress = 100) Then ; Always update status at progress of 100% GUICtrlSetData($progressbar, $progress) WinSetTitle($guiwin, "", $title & " " & $progress & " %") EndIfEndFuncFunc getTime($secs) ; Take time in seconds and convert to hours, mins, seconds, etc... Local $seconds = $secs Local $mins = 0 Local $hours = 0 Local $days = 0 Local $weeks = 0 Local $months = 0 Local $timestring = Int($seconds) & " secs" If ($seconds > 60) Then $mins = Int($seconds / 60) $seconds = Int($seconds - ($mins * 60)) If ($seconds <= 0) Then $timestring = $mins & " mins" Else $timestring = $mins & " mins " & $seconds & " secs" EndIf If ($mins > 60) Then $hours = Int($mins / 60) $mins = Int($mins - ($hours * 60)) If ($mins <= 0) Then $timestring = $hours & " hours" Else $timestring = $hours & " hours " & $mins & " mins" EndIf If ($hours > 24) Then $days = Int($hours / 24) $hours = Int($hours - ($days * 24)) If ($hours <= 0) Then $timestring = $days & " days" Else $timestring = $days & " days " & $hours & " hours" EndIf If ($days > 7) Then $weeks = Int($days / 7) $days = Int($days - ($weeks * 7)) If ($days <= 0) Then $timestring = $weeks & " weeks" Else $timestring = $weeks & " weeks " & $days & " days" EndIf If ($weeks > 4) Then $months = Int($weeks / 4) $weeks = Int($weeks - ($months * 4)) If ($weeks <= 0) Then $timestring = $months & " months" Else $timestring = $months & " months " & $weeks & " weeks" EndIf EndIf EndIf EndIf EndIf EndIf Return $timestringEndFuncFunc getByteSuffix ($bytes, ByRef $byteprefix, ByRef $bytesuffix) Local $byte = 1 Local $kilobyte = ($byte * 1024) Local $megabyte = ($kilobyte * 1024) Local $gigabyte = ($megabyte * 1024) Local $terabyte = ($gigabyte * 1024) Local $petabyte = ($terabyte * 1024) Select Case $bytes > $petabyte $byteprefix = ($bytes / $petabyte) $bytesuffix = "PB" Case $bytes > $terabyte $byteprefix = ($bytes / $terabyte) $bytesuffix = "TB" Case $bytes > $gigabyte $byteprefix = ($bytes / $gigabyte) $bytesuffix = "GB" Case $bytes > $megabyte $byteprefix = ($bytes / $megabyte) $bytesuffix = "MB" Case $bytes > $kilobyte $byteprefix = ($bytes / $kilobyte) $bytesuffix = "KB" Case Else $byteprefix = $bytes $bytesuffix = "bytes" EndSelect EndFuncFunc validPath ($input) ; search through invalidChars against input Local $invalidCharArray = StringSplit($invalidChars, " ") For $x = 1 to $invalidCharArray[0] If (StringInStr($input, $invalidCharArray[$x])) Then Return 0 EndIf Next Return 1EndFuncFunc debugMsg ($inmsg) ; show debug message If ($debug = 1) Then MsgBox(0, "Debug", $inmsg) EndIfEndFuncFunc errorMsg($inmsg) ; displays error message If ($noerror = 0) Then MsgBox(16, "Error", $inmsg) EndIfEndFuncFunc copyFile($insource, $indest) debugMsg ("Executing copyFile " & $insource & " -> " & $indest) Local $sourcefilesize = FileGetSize($insource) Local $destfilesize = 0 Local $sourceprefix = 0 Local $sourcesuffix = "" Local $bytestransfered = 0 Local $transferspeed = 0 Local $transfersize = 0 Local $timeremaining = 0 Local $index = 1 Local $destsizeupdate = 0 Local $runcmd = "" Local $procstats Local $starttime ; set source size display getByteSuffix($sourcefilesize, $sourceprefix, $sourcesuffix) ; update current file display GUICtrlSetData ($lblcurrentfile, "Current file: " & getFilename(shortText($indest))) ; if destination's path doesn't exist, create it If (FileExists(getDirectory($indest)) = 0) Then debugMsg ("copyFile: Creating directory " & getDirectory($indest)) If (DirCreate(getDirectory($indest)) = 0) Then Return 0 EndIf EndIf $runcmd = @ComSpec & " /c copy /y " & chr(34) & $insource & chr(34) & " " & Chr(34) & $indest & Chr(34) debugMsg ("Command: " & $runcmd) $starttime = TimerInit() $pid = Run($runcmd, @ScriptDir, @SW_HIDE) If ($pid = 0) Then errorMsg ("Error running copy command") Return 0 EndIf $destsizeupdate = 0 While (ProcessExists($pid)) $procstats = ProcessGetStats($pid, 1) If (IsArray($procstats) And UBound($procstats) > 4) Then If (Int(timerdiff($starttime)) > $statusrefresh) Then $transferspeed = Int($destinationsize / (TimerDiff($copyfiletime) / 1000)) If ($transferspeed > 0) Then $timeremaining = (($sourcesize - $destinationsize) / $transferspeed) EndIf If ($transferspeed > $peakspeed) Then $peakspeed = $transferspeed $transfersize = $procstats[4] $starttime = TimerInit() EndIf ; set global destinationsize (current transfer size minus previous destfilesize) = bytestransfered $destinationsize = ($destinationsize + ($procstats[4] - $destfilesize)) $destsizeupdate = ($destsizeupdate + ($procstats[4] - $destfilesize)) $destfilesize = $procstats[4] If ($destfilesize > $sourcefilesize) Then $destfilesize = $sourcefilesize EndIf EndIf ; Update current file's progress GUICtrlSetData($currentprogressbar, Int(($destfilesize / $sourcefilesize) * 100)) ; Update overall progress display $progress = Int(($destinationsize / $sourcesize) * 100) progressUpdate($sourcesize, $destinationsize, $transferspeed, $timeremaining) $index = ($index + 1) WEnd ; After copy finished, display destination file size debugMsg ("Copy file finished") $destfilesize = FileGetSize($indest) ; if file copy was too fast, update global destination size If ($destsizeupdate < $destfilesize) Then $destinationsize = ($destinationsize + ($destfilesize - $destsizeupdate)) debugMsg ("Adding to destinationsize: " & ($destfilesize - $destsizeupdate)) EndIf ; If destination file doesn't exist, display error If (FileExists($indest) = 0) Then errorMsg ("Could not create file " & $indest) Return 0 EndIf ; Compare source file size and destination file size debugMsg("Source file size: " & $sourcefilesize) debugMsg("Destination file size: " & $destfilesize) If ($sourcefilesize <> $destfilesize) Then FileDelete($indest) Return 0 EndIf ; Update current file's progress GUICtrlSetData($currentprogressbar, Int(($destfilesize / $sourcefilesize) * 100)) ; Update transfer speed (now that file copy is finished) $transferspeed = Int($destinationsize / (TimerDiff($copyfiletime) / 1000)) If ($transferspeed > 0) Then $timeremaining = (($sourcesize - $destinationsize) / $transferspeed) EndIf If ($transferspeed > $peakspeed) Then $peakspeed = $transferspeed ; Update overall progress $progress = Int(($destinationsize / $sourcesize) * 100) progressUpdate($sourcesize, $destinationsize, $transferspeed, $timeremaining) Return 1EndFuncFunc copyDir($insource, $indest) Local $search Local $cursearchitem Local $sourcepath = "" Local $destpath = "" ; if destination ($indest) doesn't exist, create it first If (FileExists($indest) = 0) Then debugMsg ("copyDir: Creating directory " & $indest) If (DirCreate($indest) = 0) Then errorMsg ("Failed to create directory " & $indest) Return 0 EndIf EndIf ; search through current directory ; if @error = 1, directory is empty, return 1 $search = FileFindFirstFile ($insource & "\*.*") If (@error = 1) Then Return 1 If ($search = -1) Then errorMsg ("Error getting " & $insource & " contents") Exit EndIf While 1 $cursearchitem = FileFindNextFile($search) If @error Then ExitLoop $sourcepath = $insource & "\" & $cursearchitem $destpath = $indest & "\" & $cursearchitem If (StringInStr(StringUpper(FileGetAttrib($sourcepath)), "D")) Then ; if search is a directory, create it and search for files inside debugMsg("Creating directory " & $destpath) If (FileExists($destpath) = 0) Then If (DirCreate($destpath) = 0) Then debugMsg("Failed to create directory " & $destpath) FileClose($search) Return 0 EndIf EndIf debugMsg("Traversing " & $sourcepath) If (copyDir($sourcepath, $destpath) = 0) Then $fail = $fail & @LF & $destpath EndIf Else ; if search is a file, copy it debugMsg("Copying file " & $sourcepath & " -> " & $destpath) If (copyFile($sourcepath, $destpath) = 0) Then $fail = $fail & @LF & $destpath EndIf EndIf WEnd FileClose($search) Return 1EndFuncFunc displayHelp() ; displays help message ; if noerror <> 0, don't display help message Local $helpmsg If ($noerror = 0) Then $helpmsg = "CopyFileProgress.exe [options] source destination" & @CRLF _ & " [options]:" & @CRLF _ & " /noerror = disable error messages" & @CRLF _ & " /? = display this help message" & @CRLF _ & " /y = suppress prompt to overwrite destination" & @CRLF _ & " /k = keep dialog open after file copy" & @CRLF _ & " /title:<title> = set title of copy dialog box" & @CRLF _ & @CRLF _ & " source = source file/directory" & @CRLF _ & " destination = destination file/directory" & @CRLF MsgBox(64, "Help", $helpmsg) EndIfEndFuncFunc getDrive ($inpath) ; returns the drive for a given path Local $tmp Local $returnstring _PathSplit($inpath, $returnstring, $tmp, $tmp, $tmp) Return $returnstringEndFuncFunc getDirectory ($inpath) ; returns the directory for a given path Local $tmp Local $returnstring _PathSplit($inpath, $tmp, $returnstring, $tmp, $tmp) Return $returnstringEndFuncFunc getFilename ($inpath) ; returns the filename for a given path Local $tmp Local $tmpfilename Local $tmpfileext Local $returnstring _PathSplit($inpath, $tmp, $tmp, $tmpfilename, $tmpfileext) $returnstring = $tmpfilename & $tmpfileext Return $returnstringEndFuncFunc shortText($instring) ; shortens a line of text and places '...' in the middle ; returns string result Local $maxlen = 35 Local $resultstring = "" If (StringLen($instring) > $maxlen) Then $resultstring = StringLeft($instring, (Int($maxlen / 2) - 2)) $resultstring = $resultstring & "..." $resultstring = $resultstring & StringRight($instring, (Int($maxlen / 2) - 1)) Else $resultstring = $instring EndIf Return $resultstringEndFunc 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