Jump to content

progressbars in Vista/7


llewxam
 Share

Recommended Posts

I have been annoyed with the slowness (or latency?) of progressbars in Vista and 7 for a while now and can't find a solution. Using dwmapi.dll hasn't helped, and other endless searches and attempts at fixes haven't helped. I even used sliders as an experiment ;) and they can keep up, why not progressbars? Does anyone have a suggestion on how to make Vista/7 keep up like XP? This lag is killing me!!! ggrrrrrr :)

Also, in the included script, it seems like any time a file hits roughly the 100MB mark there is a stutter which causes the GUI to seemingly twitch or move slightly, and then all of the controls hang until the file has finished copying. Any insights there??

Sorry my example script is so huge..... and thanks for any suggestions in to these issues!!!

Ian

#include <WindowsConstants.au3> ;needed for $WS_EX_ACCEPTFILES, $DT_END_ELLIPSIS
#include <EditConstants.au3> ;needed for $ES_READONLY
#include <GUIConstantsEx.au3> ;needed for $GUI_DROPACCEPTED, $GUI_HIDE, $GUI_EVENT_CLOSE, $GUI_SHOW, $GUI_UNCHECKED
#include <String.au3> ;needed for _StringAddThousandsSep

$main=GUICreate("Sync 2 Build 4",550,400,1,1,-1,$WS_EX_ACCEPTFILES)
$instructions=GUICtrlCreateLabel("Browse left, type path, or drag and drop",60,5,300,20)
GUICtrlCreateLabel("Total Files",400,5,100,20)
$totalfileslabel=GUICtrlCreateInput("",400,25,100,20,$ES_READONLY)
GUICtrlCreateLabel("Total Size",400,45,100,20)
$totalsizelabel=GUICtrlCreateInput("",400,65,100,20,$ES_READONLY)
$sourcebtn=GUICtrlCreateButton("Source",5,25,50,20)
$targetbtn=GUICtrlCreateButton("Target",5,65,50,20)
$addbtn=GUICtrlCreateButton("Add",315,65,50,20)
$startbtn=GUICtrlCreateButton("START",485,135,60,20)
$sourceinput=GUICtrlCreateInput("",60,25,250,20)
$targetinput=GUICtrlCreateInput("",60,65,250,20)
$job=GUICtrlCreateList("",5,160,540,215,$ES_READONLY)
GUICtrlSetState($sourceinput,$GUI_DROPACCEPTED)
GUICtrlSetState($targetinput,$GUI_DROPACCEPTED)
GUICtrlSetState($startbtn,$GUI_HIDE)
GUISetState(@SW_SHOW,$main)
ControlFocus("","",$sourceinput)

dim $accelkeys[1][2]=[["{ENTER}",$addbtn]]
GUISetAccelerators($accelkeys)

Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str') ;used in..........
Local $ptr = DllCallbackGetPtr($callback) ;............... _CopyWithProgress
local $size ;size of task (dir or single file)
local $count ;used to help with padding in the listbox
local $fill ;the spacing for above
local $queue ;the list of what is being copied (all tasks)
local $totalfiles ;total number of files to be copied
local $totalsize ;total byte count of files
local $donesofar ;total bytes copied so far
local $bytes ;used as placeholder in __Progress
local $failedfiles ;string of failed copies
local $failed ;count of failures

Do
    $msg=GUIGetMsg()
    if $msg=$GUI_EVENT_CLOSE then Exit
        
    if $msg=$sourcebtn then GUICtrlSetData($sourceinput,FileSelectFolder("Select a folder",""))

    if $msg=$targetbtn then GUICtrlSetData($targetinput,FileSelectFolder("Select a folder","",1))
        
    if $msg=$addbtn Then
        $source=GUICtrlRead($sourceinput)
        $target=GUICtrlRead($targetinput)
        if not FileExists($target) then DirCreate($target)
        if FileExists($source) and FileExists($target) Then
            $wait=GUICtrlCreateLabel("Please wait, files are being enumerated",100,100,400,20)

            If StringInStr(FileGetAttrib($source), "D") > 0 Then
                $count+=1
                for $padding=1 to $count
                    $fill&=" "
                Next            
                $sourceinfo=DirGetSize($source,1)
                GUICtrlSetData($job,$source&" -> "&$target)
                GUICtrlSetData($job,"("&_StringAddThousandsSep($sourceinfo[1])&" files "&_StringAddThousandsSep(round($sourceinfo[0]/1000000,2))&"MB)")
                GUICtrlSetData($job,$fill)
                $size+=$sourceinfo[0]
                $totalfiles+=$sourceinfo[1]
                $totalsize+=$sourceinfo[0]
                $queue&=$source&chr(1)&$target&chr(1)&"D"&chr(1)
                GUICtrlSetData($sourceinput,"")
                GUICtrlSetData($targetinput,"")
                GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
                GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
                GUICtrlDelete($wait)
                ControlFocus("","",$sourceinput)
                GUICtrlSetState($startbtn,$GUI_SHOW)
            Else
                $count+=1
                for $padding=1 to $count
                    $fill&=" "
                Next            
                $sourceinfo=FileGetSize($source)
                GUICtrlSetData($job,$source&" -> "&$target)
                GUICtrlSetData($job,"(1 file "&_StringAddThousandsSep(round($sourceinfo/1000000,2))&"MB)")
                GUICtrlSetData($job,$fill)
                $size+=$sourceinfo
                $totalfiles+=1
                $totalsize+=$sourceinfo
                $queue&=$source&chr(1)&$target&chr(1)&"F"&chr(1)
                GUICtrlSetData($sourceinput,"")
                GUICtrlSetData($targetinput,"")
                GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
                GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
                GUICtrlDelete($wait)
                ControlFocus("","",$sourceinput)
                GUICtrlSetState($startbtn,$GUI_SHOW)
            EndIf
        Else
            msgbox(0,"Error","Please check your source and target paths")           
        EndIf
    EndIf ;end $addbtn
    
    if $msg=$startbtn Then
        $display=TimerInit()
        $howlong=TimerInit()
        GUICtrlDelete($startbtn)
        GUICtrlDelete($instructions)
        ControlDisable("","",$sourcebtn)
        ControlDisable("","",$targetbtn)
        ControlDisable("","",$addbtn)
        ControlDisable("","",$startbtn)
        ControlDisable("","",$sourceinput)
        ControlDisable("","",$targetinput)
        ControlDisable("","",$job)
        $fileslide=GUICtrlCreateProgress(5,375,265,20)
        $totalslide=GUICtrlCreateProgress(280,375,265,20)
        $stop=GUICtrlCreateCheckbox("STOP",495,135,60,20)
        $showfilename=GUICtrlCreateLabel("",10,100,530,20,$DT_END_ELLIPSIS)
        GUICtrlCreateLabel("Overall progress - ",10,125,430,20)
        $showtotalprog=GUICtrlCreateLabel("",96,125,230,20)
        $breaksources=StringSplit($queue,chr(1))
        for $doit=1 to ($breaksources[0]-1) step 3
            if $breaksources[$doit+2]="D" then 
                $basedir=$breaksources[$doit]
                $target=$breaksources[$doit+1]
                $baselen = StringLen($basedir)
                theheart($basedir)
            EndIf
            if $breaksources[$doit+2]="F" then 
                $source=$breaksources[$doit]
                $target=$breaksources[$doit+1]
                $name=StringTrimLeft($source,StringInStr($source,"\",0,-1))
                $copied = _CopyWithProgress($source,$target&"\"&$name)
                if $copied=0 then 
                    $failed+=1
                    $failedfiles&=$source&chr(2)
                    $lastbyte=0
                    $bytes=0
                EndIf
            EndIf
        Next
        GUICtrlSetData($showfilename,"")
        $totaltimetorun=TimerDiff($howlong)
        $minutes=round($totaltimetorun/60000,2)
        if $failed=0 then msgbox(0,"Finished in "&$minutes&" minutes","Finished with no errors")
        if $failed<>0 then
            $yesorno=msgbox(4,"Finished in "&$minutes&" minutes","Finished with "&$failed&" errors, do you want to see the failed files?")
            if $yesorno=6 then
                $failedwindow=GUICreate("Failed Files",@DesktopWidth,300) ;to display the failed files
                $failedlist=GUICtrlCreateList("",5,5,@DesktopWidth-10,290) ;to display the failed files
                GUISetState(@sw_show,$failedwindow) ;done setting up GUI
                StringTrimRight($failedfiles,1) ;take off the trailing delimeter
                $failedarray=StringSplit($failedfiles,chr(2)) ;break up the list of failed files
                for $show=1 to $failedarray[0]-1
                    GUICtrlSetData($failedlist,$failedarray[$show]) ;list the failed files
                Next
                Do
                    $msg=GUIGetMsg()
                    if $msg=$GUI_EVENT_CLOSE then exit ;when the failed window is closed, quit the program
                until 1=2
            EndIf
        EndIf
        Exit
    EndIf ;end $startbtn
until 1=2


Func theheart($basedir)

    While GUICtrlRead($stop) == 1 ;look for the pause button
        $quit=msgbox(36,"Paused","Quit Now?")
        if $quit=6 then exit ;yes
        if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
    WEnd
    $basesearch = FileFindFirstFile($basedir & "\*.*")
    If $basesearch == -1 Then Return 0 ; specified folder is empty!
    While @error <> 1
        $basefile = FileFindNextFile($basesearch)
        ; skip these
        If $basefile == "." Or $basefile == ".." Or $basefile == "" Then
            ContinueLoop
        EndIf
        ; if it's a dir then call this function again (nesting the function is clever ;)
        $formattedfile = $basedir & "\" & $basefile
        If StringInStr(FileGetAttrib($formattedfile), "D") > 0 Then
            theheart($formattedfile)
        Else
            ; Files we need to deal with
            $dest=StringTrimLeft($formattedfile,$baselen)
                    
            While GUICtrlRead($stop) == 1 ;look for the pause button
                $quit=msgbox(36,"Paused","Quit Now?")
                if $quit=6 then exit ;yes
                if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
            WEnd
            GUICtrlSetData($showfilename,$formattedfile);&" - "&$BytesTransferred / $FileSize * 100&"%")
            if not FileExists($target&$dest) then 
                $copied = _CopyWithProgress($formattedfile,$target&"\"&$dest)
                if $copied=0 then 
                    $failed+=1
                    $failedfiles&=$formattedfile&chr(2)
                EndIf
            Else
                $donesofar+=FileGetSize($formattedfile)
                GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
            EndIf
            $lastbyte=0
            $bytes=0
        endif
    WEnd
    FileClose($basesearch)
    Return 1

EndFunc ;end theheart


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
      
    $DestDir = StringLeft($inDest, StringInStr($inDest, "\", "", -1))

    If Not FileExists($DestDir) Then DirCreate($DestDir)
    
    $ret = DllCall('kernel32.dll', 'int', 'CopyFileExA', 'str', $inSource, 'str', $inDest, 'ptr', $ptr, 'str', '', 'int', 0, 'int', 0)

    If $ret[0] <> 0 Then
    ; Success
        Return 1
    Else
    ; Fail
        Return 0
    EndIf
    
EndFunc


Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)

    $lastbyte=$bytes
    $bytes=$BytesTransferred
    $bytediff=$bytes-$lastbyte
    $donesofar+=$bytediff
    GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
    GUICtrlSetData($totalslide,$donesofar / $size * 100)
    GUICtrlSetData($fileslide,$BytesTransferred / $FileSize * 100)

EndFunc

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

  • 2 weeks later...

I wrote a progress bar for a single file copy here. All it uses is the native windows copy command (any version), and displays a progress bar with speed, bytes transfered, and estimated time remaining.

http://www.autoitscript.com/forum/index.php?showtopic=15384&st=0&p=755467&#entry755467

Link to comment
Share on other sites

First of all, your example script is indeed huge, and very hard to understand. It seems just to copy files from some folders to other folders, but it's hard to figure out because everything is just piled up with no organization whatsoever.

I tested it anyway. It copied 300MB of music from one folder to another with no hiccups, and the progress bars behaved as expected. I'm running Windows 7 RC1, which leads me to believe your problem is not what you believed it to be.

Link to comment
Share on other sites

First of all, your example script is indeed huge, and very hard to understand. It seems just to copy files from some folders to other folders, but it's hard to figure out because everything is just piled up with no organization whatsoever.

I tested it anyway. It copied 300MB of music from one folder to another with no hiccups, and the progress bars behaved as expected. I'm running Windows 7 RC1, which leads me to believe your problem is not what you believed it to be.

Sorry, which script were you referring to? If it's mine above, what about it should be changed?

Link to comment
Share on other sites

Sorry, which script were you referring to? If it's mine above, what about it should be changed?

LOL, too many funny things "all piled up" here! ;)

danielkza was referring to my script which I think is very easy to understand and is well organized, but it is very large and I know it is overwhelming to look at that much of someone else's code and feel comfortable. I know I get lost sometimes!! :evil: We all have our own styles, I usually choose to not go the "function for everything" model and code more linearly. Also, the point of my complaint was that it stutters on a SINGLE large file, not hundreds of megs of tiny ones, have it transfer something at least a few hundred MB and you will see it.

Back to the point though, as luck has it I saw your code late last night shovetech and played around with it a lot, it is excellent and is JUST what I needed! Right now I am kinda in between merging your code and mine, and I really am looking forward to getting it completed. I have been loosing my mind trying to get the _CopyWithProgress that has been floating around to work without stuttering, but now, I DON'T HAVE TO!! Hopefully more people will migrate towards yours who have been having issues.

Thanks for posting the code in the first place, and for giving a crap enough to point me in the direction of your post.

Ian

Edited by llewxam

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

I was referring to llewxam's script.

@llewxam:

It may seem organized to you, but the fact that logic is not compartmentalized in any way (having a function that does everything does not help). Also, you create and delete windows and controls often, and those are hard to keep track of, specially when you are not the one writing the code.

If this is a script you plan on using as-is, there is no problem in keeping it like that. But trust me, if you plan on writing any larger projects, having reusable code, that keeps track of its resources and frees you of caring about inner workings as much as possible will go a long way on improving the final product, and keeping you sane.

Link to comment
Share on other sites

LOL, too many funny things "all piled up" here! ;)

danielkza was referring to my script which I think is very easy to understand and is well organized, but it is very large and I know it is overwhelming to look at that much of someone else's code and feel comfortable. I know I get lost sometimes!! :evil: We all have our own styles, I usually choose to not go the "function for everything" model and code more linearly. Also, the point of my complaint was that it stutters on a SINGLE large file, not hundreds of megs of tiny ones, have it transfer something at least a few hundred MB and you will see it.

Back to the point though, as luck has it I saw your code late last night shovetech and played around with it a lot, it is excellent and is JUST what I needed! Right now I am kinda in between merging your code and mine, and I really am looking forward to getting it completed. I have been loosing my mind trying to get the _CopyWithProgress that has been floating around to work without stuttering, but now, I DON'T HAVE TO!! Hopefully more people will migrate towards yours who have been having issues.

Thanks for posting the code in the first place, and for giving a crap enough to point me in the direction of your post.

Ian

My code is not good by any means though. As it stands, it can only copy a single file. I'm working on having it copy multiple files (directories, etc.), using only the copy command. I was thinking about using xcopy, but wanted to keep the depencancy list minimal.

Anyway, looking forward to seeing your code. (That is until AutoIT internal devs create a function called '_CopyWithProgress' LOL!)

Link to comment
Share on other sites

My code is not good by any means though. As it stands, it can only copy a single file. I'm working on having it copy multiple files (directories, etc.), using only the copy command. I was thinking about using xcopy, but wanted to keep the depencancy list minimal.

Anyway, looking forward to seeing your code. (That is until AutoIT internal devs create a function called '_CopyWithProgress' LOL!)

No time to work on this today so far until now, I may try to get a few other things organized first though before continuing. I was trying to copy a directory (with subdirectories) with the original file recursion routine I have used for an eternity that I didn't write, but for some reason it isn't working well with that routine, something isn't playing nice and the app just stops before all of the files have been copied. Of course, if I hadn't commented or ripped out your error checking, maybe I'd have a clue as to what is happening!! hahahahhaha. I'll post it so you can see, but be warned - I have hacked out a LOT of your original code, and what I have here doesn't work well, at all! ;) I am going to try putting together my own recursion routine that I think will work well with what you have, and hopefully that will have a better result. Here it is, as-is, in all it's broken glory! :evil:

; Copies a file using the native Windows copy command, but
; displays statistics while copying.
; Works especially good in a WinPE environment
;
; Version: 1.0.0
;
; Author: Doug Shove
;

#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)



Global $invalidChars = "/ : * ? < > | " & chr(34)
Global $forceoverwrite = 0
Global $showcopytime = 0
Global $title = "Copying files..."
Global $source 
Global $destination 
Global $procstats
Global $filedrive
Global $filepath
Global $filename
Global $fileext
Global $copyfiletime

; Global GUI controls
Global $guiwin, $cancelbtn, $progressbar, $msg, $index, $lblbytes, $source, $basesearch, $basefile, $formattedfile, $basedir, $target, $baselen
Global $lbltransfer, $lblspin, $lblfiles, $lbltime
Global $spin = "|"
Global $progresstime = TimerInit()
Global $progresssubstring = ""
Global $pid = 0
Global $sourcesize = 0
Global $destinationsize = 0
Global $copystatus = 1
Global $statusrefresh = 1000

$guiwin = GUICreate($title, 300, 130)
$lblbytes = GUICtrlCreateLabel("Preparing...", 5, 5, 290)
$progressbar = GUICtrlCreateProgress(-1, 20, 290, 20, $PBS_SMOOTH)
$lblfiles = GUICtrlCreateLabel("Source: " & $source & @LF & "Destination: " & $destination , -1, 21, 290, 26)
$lbltransfer = GUICtrlCreateLabel("", -1, 27, 290, 13)
$lbltime = GUICtrlCreateLabel("", -1, 14, 290, 13)
$cancelbtn = GUICtrlCreateButton("Cancel", 230, 15, 60)

GUICtrlSetOnEvent($cancelbtn, "cancelop")
GUISetOnEvent($GUI_EVENT_CLOSE, "cancelop")
GUISetState(@SW_SHOW)



; Start copying file

$basedir="c:\users\me\desktop\inventory"
$baselen = StringLen($basedir)
$target="d:\new"

theheart($basedir)


Exit



Func killproc($pid)
    ; kills a process
    While (ProcessExists($pid))
        ProcessClose($pid)
    WEnd
EndFunc

Func cancelop()
    ; If copystatus = 0 (not copying...)
    If ($copystatus = 0) Then
        GUISetState(@SW_HIDE)
        Exit
    EndIf
    
    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, "")
        killproc($pid)
        GUICtrlSetData($lblbytes, "Removing " & $destination & " .....")
        If (FileExists($destination)) Then
            FileDelete($destination)
        EndIf   
        Exit
    EndIf
EndFunc

Func copyFile($source, $destination)
    
    Dim $sourceprefix = 0
    Dim $sourcesuffix = ""
    getByteSuffix($sourcesize, $sourceprefix, $sourcesuffix)

    Dim $bytestransfered = 0
    Dim $transferspeed = 0
    Dim $transfersize = 0
    Dim $timeremaining = 0
    Dim $progress = 0
    Dim $maxbytes = 0
    Dim $minbytes = 0
    Dim $index = 1

    Dim $starttime = TimerInit()
    $pid = Run(@ComSpec & " /c copy /y " & chr(34) & $source & chr(34) & " " & Chr(34) & $destination & Chr(34), @ScriptDir, @SW_HIDE)
    If ($pid = 0) Then
;~      MsgBox(16, "Error", "Error running copy command")
;~      Exit
    EndIf
    
    While (ProcessExists($pid))
        $procstats = ProcessGetStats($pid, 1)
        If (IsArray($procstats) And UBound($procstats) > 4) Then
            If (Int(timerdiff($starttime)) > $statusrefresh) Then
                $transferspeed = Int($procstats[4] / (TimerDiff($copyfiletime) / 1000))
                If ($transferspeed > 0) Then
                    $timeremaining = (($sourcesize - $procstats[4]) / $transferspeed)
                EndIf
                $transfersize = $procstats[4]

                $starttime = TimerInit()                
                $progresstime = TimerInit()
            EndIf
            
            $destinationsize = $procstats[4]
            
            If ($destinationsize > $sourcesize) Then
                $destinationsize = $sourcesize
            EndIf
            
            $progress = $destinationsize / $sourcesize * 100
            progressUpdate($progress, $sourcesize, $destinationsize, $transferspeed, $timeremaining)
        EndIf
        Sleep(100)
        $index = ($index + 1)
    WEnd

    ; After copy finished, display destination file size
    $destinationsize = FileGetSize($destination)
    $progress = Int(($destinationsize / $sourcesize) * 100)
    $timeremaining = 0
    $transferspeed = 0
    $spin = ""
    progressUpdate($progress, $sourcesize, $destinationsize, $transferspeed, $timeremaining)
    
    ; If destination file doesn't exist, display error
    If (FileExists($destination) = 0) Then
;~      MsgBox(16, "Error", "Could not create file " & $destination)
;~      Exit
    EndIf
    
    ; Compare source file size and destination file size
    If ($sourcesize <> $destinationsize) Then
;~      MsgBox(16, "Error", "Source and destination file sizes are different.  Could not copy.")
;~      FileDelete($destination)
;~      Exit
    EndIf
EndFunc

Func progressUpdate($progress, $sourcesize, $destsize, $transferspeed, $timeremaining)

    ; Don't let progress bar above 100%
    If ($progress > 100) Then
        $progress = 100
    EndIf

    ; 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
    
    Local $sourceprefix = 0
    Local $sourcesuffix = ""
    getByteSuffix($sourcesize, $sourceprefix, $sourcesuffix)
    
    Local $byteprefix = 0
    Local $bytesuffix = ""
    getByteSuffix($destsize, $byteprefix, $bytesuffix)
    
    Local $speedprefix = 0
    Local $speedsuffix = ""
    Local $speedstring = ""
    Local $timeremainstring = ""
    
    If ($destsize > 0) Then
        ; display current speed
        If ($transferspeed > 0) Then
            getByteSuffix($transferspeed, $speedprefix, $speedsuffix)
            If (Int($speedprefix) > 0) Then
                $speedstring = "Speed: " & Int($speedprefix) & " " & $speedsuffix & "/s"                            
            EndIf
        EndIf
        $progresssubstring = $speedstring
        
        ; display time remaining
        If (Int($timeremaining) > 0) Then
            $timeremainstring = " - Remaining: " & getTime($timeremaining)
        EndIf


        GUICtrlSetData($progressbar, $progress)
        GUICtrlSetData($lblbytes, Int($byteprefix) & " " & $bytesuffix & " / " & Int($sourceprefix) & " " & $sourcesuffix & " " & $spin)
        GUICtrlSetData($lbltransfer, $progresssubstring)
        GUICtrlSetData($lbltime, "Elapsed: " & getTime(timerdiff($copyfiletime) / 1000) & $timeremainstring)
        WinSetTitle($guiwin, "", $title & " " & $progress & " %")
    EndIf
EndFunc

Func 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 $timestring
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

;~ Func 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 1
;~ EndFunc














func theheart($basedir)
    

    $basesearch = fileFindFirstFile($basedir & "\*.*")
    if $basesearch==-1 then return 0 ; specified folder is empty!
    while @error<>1
        $basefile = fileFindNextFile($basesearch)
        ; skip these
        if $basefile=="." or $basefile==".." or $basefile=="" then
            continueLoop
        endIf
        ; if it's a dir then call this function again (nesting the function is clever ;)
        $formattedfile=$basedir&"\"&$basefile
        if stringInStr(fileGetAttrib($formattedfile), "D") > 0 then
            
            theheart($formattedfile)
            
        else
            
            ; Files we need to deal with

            $source = $formattedfile
            $sourcesize = FileGetSize($source)
            $destination=$target&StringTrimLeft($formattedfile,$baselen)
            GUICtrlSetData($lblfiles,"Source: " & $source & @LF & "Destination: " & $destination)

            if not FileExists($destination) then 
                ; Check for illegal characters in destination
                _PathSplit($destination, $filedrive, $filepath, $filename, $fileext)
;~              If (validPath($filepath) = 0 Or _
;~                  validPath($filename) = 0 Or _
;~                  validPath($fileext) = 0) Then
;~                  MsgBox (16, "Error", "Destination file name invalid.  File name cannot contain: " & @LF & $invalidChars)
;~                  Exit
;~              EndIf

                ; if destination directory doesn't exist, create it
                If ($filedrive <> "" And $filepath <> "" And _
                    FileExists($filedrive & $filepath) = 0) Then
                    DirCreate($filedrive & $filepath)
                    If (FileExists($filedrive & $filepath) = 0) Then
                        MsgBox(16, "Error", "Could not create " & $filedrive & $filepath & ". File copy failed")
;~                      Exit
                    EndIf
                EndIf

                $copyfiletime = TimerInit()
                copyFile($source, $destination)
                $copystatus = 0
                If ($showcopytime = 1) Then
                    _GUICtrlButton_SetText ($cancelbtn, "Close")
                    while (1)
                        Sleep (1000)
                    WEnd
                EndIf
            EndIf
        endIf
    wEnd
    fileClose($basesearch)
    return 1
endFunc

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Dunno shove, I just wrote a file recursion script of my own and the app still died before it was done. Doubting myself I found another recursion routing and used it, same thing. I thought it was due to a huge file since that is when it died, but after I moved them elsewhere I am still having the same issue. BTW, I like your sizing method but my file was 1.36GB and your GUI just showed it as 1GB, kinda odd. Oh, and I broke the INT on the titlebar, my bad, but didn't fix it. Anyway, here is what I did tonight, and maybe the post I did above would work just fine but the error is somewhere else (kinda seems likely)

; Copies a file using the native Windows copy command, but
; displays statistics while copying.
; Works especially good in a WinPE environment
;
; Version: 1.0.0
;
; Author: Doug Shove
;

#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)

Global $invalidChars = "/ : * ? < > | " & chr(34)
Global $forceoverwrite = 0
Global $showcopytime = 0
Global $title = "Copying files..."
Global $source 
Global $destination 
Global $procstats
Global $filedrive
Global $filepath
Global $filename
Global $fileext
Global $copyfiletime

; Global GUI controls
Global $guiwin, $cancelbtn, $progressbar, $msg, $index, $lblbytes, $source, $basesearch, $basefile, $formattedfile, $basedir, $target, $baselen, $search, $next, $sourcelen
Global $lbltransfer, $lblspin, $lblfiles, $lbltime
Global $spin = "|"
Global $progresstime = TimerInit()
Global $progresssubstring = ""
Global $pid = 0
Global $sourcesize = 0
Global $destinationsize = 0
Global $copystatus = 1
Global $statusrefresh = 1000

$guiwin = GUICreate($title, 300, 130)
$lblbytes = GUICtrlCreateLabel("Preparing...", 5, 5, 290)
$progressbar = GUICtrlCreateProgress(-1, 20, 290, 20, $PBS_SMOOTH)
$lblfiles = GUICtrlCreateLabel("Source: " & $source & @LF & "Destination: " & $destination , -1, 21, 290, 26)
$lbltransfer = GUICtrlCreateLabel("", -1, 27, 290, 13)
$lbltime = GUICtrlCreateLabel("", -1, 14, 290, 13)
$cancelbtn = GUICtrlCreateButton("Cancel", 230, 15, 60)

GUICtrlSetOnEvent($cancelbtn, "cancelop")
GUISetOnEvent($GUI_EVENT_CLOSE, "cancelop")
GUISetState(@SW_SHOW)



; Start copying file
Global $source = "c:\users\me\desktop"
$sourcelen = StringLen($source)
Global $target = "d:\new"
Global $sourcesize
RecursiveFileSearch($source)

Exit



Func killproc($pid)
    ; kills a process
    While (ProcessExists($pid))
        ProcessClose($pid)
    WEnd
EndFunc

Func cancelop()
    ; If copystatus = 0 (not copying...)
    If ($copystatus = 0) Then
        GUISetState(@SW_HIDE)
        Exit
    EndIf
    
    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, "")
        killproc($pid)
        GUICtrlSetData($lblbytes, "Removing " & $destination & " .....")
        If (FileExists($destination)) Then
            FileDelete($destination)
        EndIf   
        Exit
    EndIf
EndFunc

Func copyFile($source, $destination)
    
    Dim $sourceprefix = 0
    Dim $sourcesuffix = ""
    getByteSuffix($sourcesize, $sourceprefix, $sourcesuffix)

    Dim $bytestransfered = 0
    Dim $transferspeed = 0
    Dim $transfersize = 0
    Dim $timeremaining = 0
    Dim $progress = 0
    Dim $maxbytes = 0
    Dim $minbytes = 0
    Dim $index = 1

    Dim $starttime = TimerInit()
    $pid = Run(@ComSpec & " /c copy /y " & chr(34) & $source & chr(34) & " " & Chr(34) & $destination & Chr(34), @ScriptDir, @SW_HIDE)
    If ($pid = 0) Then
;~      MsgBox(16, "Error", "Error running copy command")
;~      Exit
    EndIf
    
    While (ProcessExists($pid))
        $procstats = ProcessGetStats($pid, 1)
        If (IsArray($procstats) And UBound($procstats) > 4) Then
            If (Int(timerdiff($starttime)) > $statusrefresh) Then
                $transferspeed = Int($procstats[4] / (TimerDiff($copyfiletime) / 1000))
                If ($transferspeed > 0) Then
                    $timeremaining = (($sourcesize - $procstats[4]) / $transferspeed)
                EndIf
                $transfersize = $procstats[4]

                $starttime = TimerInit()                
                $progresstime = TimerInit()
            EndIf
            
            $destinationsize = $procstats[4]
            
            If ($destinationsize > $sourcesize) Then
                $destinationsize = $sourcesize
            EndIf
            
            $progress = $destinationsize / $sourcesize * 100
            progressUpdate($progress, $sourcesize, $destinationsize, $transferspeed, $timeremaining)
        EndIf
        Sleep(100)
        $index = ($index + 1)
    WEnd

    ; After copy finished, display destination file size
    $destinationsize = FileGetSize($destination)
    $progress = Int(($destinationsize / $sourcesize) * 100)
    $timeremaining = 0
    $transferspeed = 0
    $spin = ""
    progressUpdate($progress, $sourcesize, $destinationsize, $transferspeed, $timeremaining)
    
    ; If destination file doesn't exist, display error
    If (FileExists($destination) = 0) Then
;~      MsgBox(16, "Error", "Could not create file " & $destination)
;~      Exit
    EndIf
    
    ; Compare source file size and destination file size
    If ($sourcesize <> $destinationsize) Then
;~      MsgBox(16, "Error", "Source and destination file sizes are different.  Could not copy.")
;~      FileDelete($destination)
;~      Exit
    EndIf
EndFunc

Func progressUpdate($progress, $sourcesize, $destsize, $transferspeed, $timeremaining)

    ; Don't let progress bar above 100%
    If ($progress > 100) Then
        $progress = 100
    EndIf

    ; 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
    
    Local $sourceprefix = 0
    Local $sourcesuffix = ""
    getByteSuffix($sourcesize, $sourceprefix, $sourcesuffix)
    
    Local $byteprefix = 0
    Local $bytesuffix = ""
    getByteSuffix($destsize, $byteprefix, $bytesuffix)
    
    Local $speedprefix = 0
    Local $speedsuffix = ""
    Local $speedstring = ""
    Local $timeremainstring = ""
    
    If ($destsize > 0) Then
        ; display current speed
        If ($transferspeed > 0) Then
            getByteSuffix($transferspeed, $speedprefix, $speedsuffix)
            If (Int($speedprefix) > 0) Then
                $speedstring = "Speed: " & Int($speedprefix) & " " & $speedsuffix & "/s"                            
            EndIf
        EndIf
        $progresssubstring = $speedstring
        
        ; display time remaining
        If (Int($timeremaining) > 0) Then
            $timeremainstring = " - Remaining: " & getTime($timeremaining)
        EndIf


        GUICtrlSetData($progressbar, $progress)
        GUICtrlSetData($lblbytes, Int($byteprefix) & " " & $bytesuffix & " / " & Int($sourceprefix) & " " & $sourcesuffix & " " & $spin)
        GUICtrlSetData($lbltransfer, $progresssubstring)
        GUICtrlSetData($lbltime, "Elapsed: " & getTime(timerdiff($copyfiletime) / 1000) & $timeremainstring)
        WinSetTitle($guiwin, "", $title & " " & $progress & " %")
    EndIf
EndFunc

Func 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 $timestring
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

Func RecursiveFileSearch ($startDir, $depth = 0)
    If $depth = 0 Then Global $RFSstring = ""
    $search = FileFindFirstFile($startDir & "\*.*")
    If @error Then Return

    ;Search through all files and folders in directory
    While 1
        $next = FileFindNextFile($search)
        If @error Then ExitLoop
        ;If folder, recurse
        If StringInStr(FileGetAttrib($startDir & "\" & $next), "D") Then
            RecursiveFileSearch ($startDir & "\" & $next, $depth + 1)
        Else
            $destination=$target&(StringTrimLeft($startDir&"\"&$next,$sourcelen))
            if not FileExists($destination) then 
                _PathSplit($destination, $filedrive, $filepath, $filename, $fileext)
                ; if destination directory doesn't exist, create it
                If ($filedrive <> "" And $filepath <> "" And _
                    FileExists($filedrive & $filepath) = 0) Then
                    DirCreate($filedrive & $filepath)
                    If (FileExists($filedrive & $filepath) = 0) Then
                        MsgBox(16, "Error", "Could not create " & $filedrive & $filepath & ". File copy failed")
;~                      Exit
                    EndIf
                EndIf
                $sourcesize = FileGetSize($startDir&"\"&$next)
                GUICtrlSetData($lblfiles,"Source: " & $source & @LF & "Destination: " & $destination)
                $copyfiletime = TimerInit()
                copyFile($startDir&"\"&$next, $destination)
                $copystatus = 0
                If ($showcopytime = 1) Then
                    _GUICtrlButton_SetText ($cancelbtn, "Close")
                    while (1)
                        Sleep (1000)
                    WEnd
                EndIf
            EndIf
        EndIf
    WEnd
    FileClose($search)
    If $depth = 0 Then Return

EndFunc;==>RecursiveFileSearch

Hopefully you can figure out the glitch, I really would be happy to have a better copy w/ progress!!!!! Good luck, let me know

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Why don't you guys use SHFileOperation?

I haven't tried any Micrsoft APIs yet, I just assumed from reading some other posts around the net that people were reporting they were not able to get an explorer-like copy dialog box when using WinPE. This is what prompted me to create my own. As for full installs of XP/Vista/Win7, I'm sure you can do this pretty easy.

I've updated my code here a bit. It now supports copying of files or directories as input.

As far as the file size (ex. 1.3 GB) showing as 1 GB, this is by design. You can extend this to any number of decimal places you like by editing

Func progressUpdate

the line: GUICtrlSetData($lblbytes, Int($byteprefix) & " " & $bytesuffix & " / " & Int($sourceprefix)

to this: GUICtrlSetData($lblbytes, Round($byteprefix, 3) & " " & $bytesuffix & " / " & Round($sourceprefix,3)

Link to comment
Share on other sites

Here is another update on my take on your code ;) All I did was transplant a few functions, add a DirCreate to make paths work, and a GetFileSize on the source and destination to add some error correction. I still have much to do (GUIOnEventMode, find a way to do a running tally of overall progress during large transfers, no doubt many more things will come up) but wanted to put it up for you to see.

#include <EditConstants.au3> ;needed for $ES_READONLY
#include <GUIConstantsEx.au3> ;needed for $GUI_DROPACCEPTED, $GUI_HIDE, $GUI_EVENT_CLOSE, $GUI_SHOW, $GUI_UNCHECKED
#include <String.au3> ;needed for _StringAddThousandsSep
#include <WindowsConstants.au3> ;needed for $WS_EX_ACCEPTFILES, $DT_END_ELLIPSIS

$main=GUICreate("Sync 2 Build 5",550,400,1,1,-1,$WS_EX_ACCEPTFILES)
$instructions=GUICtrlCreateLabel("Browse left, type path, or drag and drop",60,5,300,20)
GUICtrlCreateLabel("Total Files",400,5,100,20)
$totalfileslabel=GUICtrlCreateInput("",400,25,100,20,$ES_READONLY)
GUICtrlCreateLabel("Total Size",400,45,100,20)
$totalsizelabel=GUICtrlCreateInput("",400,65,100,20,$ES_READONLY)
$sourcebtn=GUICtrlCreateButton("Source",5,25,50,20)
$targetbtn=GUICtrlCreateButton("Target",5,65,50,20)
$addbtn=GUICtrlCreateButton("Add",315,65,50,20)
$startbtn=GUICtrlCreateButton("START",485,135,60,20)
$sourceinput=GUICtrlCreateInput("",60,25,250,20)
$targetinput=GUICtrlCreateInput("",60,65,250,20)
$job=GUICtrlCreateList("",5,160,540,215,$ES_READONLY)
GUICtrlSetState($sourceinput,$GUI_DROPACCEPTED)
GUICtrlSetState($targetinput,$GUI_DROPACCEPTED)
GUICtrlSetState($startbtn,$GUI_HIDE)
GUISetState(@SW_SHOW,$main)
ControlFocus("","",$sourceinput)

dim $accelkeys[1][2]=[["{ENTER}",$addbtn]]
GUISetAccelerators($accelkeys)

local $size ;size of task (dir or single file)
local $count ;used to help with padding in the listbox
local $fill ;the spacing for above
local $queue ;the list of what is being copied (all tasks)
local $totalfiles ;total number of files to be copied
local $totalsize ;total byte count of files
local $donesofar ;total bytes copied so far
local $bytes ;used as placeholder in __Progress
local $failedfiles ;string of failed copies
local $failed ;count of failures
Local $destination,$statusrefresh,$copyfiletime,$sourcesize,$progressbar,$xferspd,$copystatus,$cancelbtn,$pid
Global $statusrefresh = 5
local $transferspeed
local $formattedfile

Do
    $msg=GUIGetMsg()
    if $msg=$GUI_EVENT_CLOSE then Exit
        
    if $msg=$sourcebtn then GUICtrlSetData($sourceinput,FileSelectFolder("Select a folder",""))

    if $msg=$targetbtn then GUICtrlSetData($targetinput,FileSelectFolder("Select a folder","",1))
        
    if $msg=$addbtn Then
        $source=GUICtrlRead($sourceinput)
        $target=GUICtrlRead($targetinput)
        if not FileExists($target) then DirCreate($target)
        if FileExists($source) and FileExists($target) Then
            $wait=GUICtrlCreateLabel("Please wait, files are being enumerated",100,100,400,20)

            If StringInStr(FileGetAttrib($source), "D") > 0 Then
                $count+=1
                for $padding=1 to $count
                    $fill&=" "
                Next            
                $sourceinfo=DirGetSize($source,1)
                GUICtrlSetData($job,$source&" -> "&$target)
                GUICtrlSetData($job,"("&_StringAddThousandsSep($sourceinfo[1])&" files "&_StringAddThousandsSep(round($sourceinfo[0]/1000000,2))&"MB)")
                GUICtrlSetData($job,$fill)
                $size+=$sourceinfo[0]
                $totalfiles+=$sourceinfo[1]
                $totalsize+=$sourceinfo[0]
                $queue&=$source&chr(1)&$target&chr(1)&"D"&chr(1)
                GUICtrlSetData($sourceinput,"")
                GUICtrlSetData($targetinput,"")
                GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
                GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
                GUICtrlDelete($wait)
                ControlFocus("","",$sourceinput)
                GUICtrlSetState($startbtn,$GUI_SHOW)
            Else
                $count+=1
                for $padding=1 to $count
                    $fill&=" "
                Next            
                $sourceinfo=FileGetSize($source)
                GUICtrlSetData($job,$source&" -> "&$target)
                GUICtrlSetData($job,"(1 file "&_StringAddThousandsSep(round($sourceinfo/1000000,2))&"MB)")
                GUICtrlSetData($job,$fill)
                $size+=$sourceinfo
                $totalfiles+=1
                $totalsize+=$sourceinfo
                $queue&=$source&chr(1)&$target&chr(1)&"F"&chr(1)
                GUICtrlSetData($sourceinput,"")
                GUICtrlSetData($targetinput,"")
                GUICtrlSetData($totalfileslabel,_StringAddThousandsSep($totalfiles))
                GUICtrlSetData($totalsizelabel,_StringAddThousandsSep(round($totalsize/1000000,2))&"MB")
                GUICtrlDelete($wait)
                ControlFocus("","",$sourceinput)
                GUICtrlSetState($startbtn,$GUI_SHOW)
            EndIf
        Else
            msgbox(0,"Error","Please check your source and target paths")           
        EndIf
    EndIf ;end $addbtn
    
    if $msg=$startbtn Then
        $display=TimerInit()
        $howlong=TimerInit()
        GUICtrlDelete($startbtn)
        GUICtrlDelete($instructions)
        ControlDisable("","",$sourcebtn)
        ControlDisable("","",$targetbtn)
        ControlDisable("","",$addbtn)
        ControlDisable("","",$startbtn)
        ControlDisable("","",$sourceinput)
        ControlDisable("","",$targetinput)
        ControlDisable("","",$job)
        $fileprog=GUICtrlCreateProgress(5,375,265,20)
        $totalprog=GUICtrlCreateProgress(280,375,265,20)
        $stop=GUICtrlCreateCheckbox("STOP",495,135,60,20)
        $showfilename=GUICtrlCreateLabel("",10,100,530,20,$DT_END_ELLIPSIS)
        GUICtrlCreateLabel("Overall progress - ",10,125,430,20)
        $showtotalprog=GUICtrlCreateLabel("",96,125,230,20)
        $breaksources=StringSplit($queue,chr(1))
        for $doit=1 to ($breaksources[0]-1) step 3
            if $breaksources[$doit+2]="D" then 
                $basedir=$breaksources[$doit]
                $target=$breaksources[$doit+1]
                $baselen = StringLen($basedir)
                theheart($basedir)
            EndIf
            if $breaksources[$doit+2]="F" then 
                $source=$breaksources[$doit]
                $target=$breaksources[$doit+1]
                $name=StringTrimLeft($source,StringInStr($source,"\",0,-1))
                $copyfiletime=0
                $sourcesize=FileGetSize($source)
                $destination=$target&"\"&$name
                copyfile($source,$destination)
                if FileGetSize($source)<>FileGetSize($destination) Then
                    $failed+=1
                    $failedfiles&=$formattedfile&chr(2)
                EndIf
            EndIf
        Next
        GUICtrlDelete($fileprog)
        GUICtrlDelete($totalprog)
        GUICtrlSetData($showfilename,"")
        $totaltimetorun=TimerDiff($howlong)
        $minutes=round($totaltimetorun/60000,2)
        if $failed=0 then msgbox(0,"Finished in "&$minutes&" minutes","Finished with no errors")
        if $failed<>0 then
            $yesorno=msgbox(4,"Finished in "&$minutes&" minutes","Finished with "&$failed&" errors, do you want to see the failed files?")
            if $yesorno=6 then
                $failedwindow=GUICreate("Failed Files",@DesktopWidth,300) ;to display the failed files
                $failedlist=GUICtrlCreateList("",5,5,@DesktopWidth-10,290) ;to display the failed files
                GUISetState(@sw_show,$failedwindow) ;done setting up GUI
                StringTrimRight($failedfiles,1) ;take off the trailing delimeter
                $failedarray=StringSplit($failedfiles,chr(2)) ;break up the list of failed files
                for $show=1 to $failedarray[0]-1
                    GUICtrlSetData($failedlist,$failedarray[$show]) ;list the failed files
                Next
                Do
                    $msg=GUIGetMsg()
                    if $msg=$GUI_EVENT_CLOSE then exit ;when the failed window is closed, quit the program
                until 1=2
            EndIf
        EndIf
        Exit
    EndIf ;end $startbtn
until 1=2


Func theheart($basedir)

    While GUICtrlRead($stop) == 1 ;look for the pause button
        $quit=msgbox(36,"Paused","Quit Now?")
        if $quit=6 then exit ;yes
        if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
    WEnd
    $basesearch = FileFindFirstFile($basedir & "\*.*")
    If $basesearch == -1 Then Return 0 ; specified folder is empty!
    While @error <> 1
        $basefile = FileFindNextFile($basesearch)
        ; skip these
        If $basefile == "." Or $basefile == ".." Or $basefile == "" Then
            ContinueLoop
        EndIf
        ; if it's a dir then call this function again (nesting the function is clever ;)
        $formattedfile = $basedir & "\" & $basefile
        If StringInStr(FileGetAttrib($formattedfile), "D") > 0 Then
            theheart($formattedfile)
        Else
            ; Files we need to deal with
            $dest=StringTrimLeft($formattedfile,$baselen)
            While GUICtrlRead($stop) == 1 ;look for the pause button
                $quit=msgbox(36,"Paused","Quit Now?")
                if $quit=6 then exit ;yes
                if $quit=7 then GUICtrlSetState($stop,$GUI_UNCHECKED) ;no, so uuncheck the box  
            WEnd
            GUICtrlSetData($showfilename,$formattedfile);&" - "&$BytesTransferred / $FileSize * 100&"%")
            if not FileExists($target&$dest) then 
                $copyfiletime=0
                $source=$formattedfile
                $sourcesize=FileGetSize($source)
                $destination=$target&$dest
                $lastdir=$target&StringMid($dest,1,StringInStr($dest,"\",2,-1)-1)
                if not FileExists($lastdir) then DirCreate($lastdir)
                copyfile($source,$destination)
                if FileGetSize($source)<>FileGetSize($destination) Then
                    $failed+=1
                    $failedfiles&=$formattedfile&chr(2)
                EndIf
;~          Else
            EndIf
            $donesofar+=FileGetSize($formattedfile)
            GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
            GUICtrlSetData($totalprog,$donesofar / $size * 100)
;~          EndIf
            $lastbyte=0
            $bytes=0
        endif
    WEnd
    FileClose($basesearch)
    Return 1

EndFunc ;end theheart


func copyfile($source,$destination)  
    
    Dim $starttime = TimerInit()
    $pid = Run(@ComSpec & " /c copy /y " & chr(34) & $source & chr(34) & " " & chr(34) & $destination & chr(34), @ScriptDir, @SW_HIDE)
    If ($pid = 0) Then
;~      MsgBox(16, "Error", "Error running copy command")
;~      Exit
    EndIf
    
    While (ProcessExists($pid))
        
        $procstats = ProcessGetStats($pid, 1)
        If (IsArray($procstats) And UBound($procstats) > 4) Then
            If (Int(timerdiff($starttime)) > $statusrefresh) Then
                $transferspeed = $procstats[4]
                $transfersize = $procstats[4]
                $starttime = TimerInit()                
                $progresstime = TimerInit()
            EndIf
            $destinationsize = $procstats[4]
            If ($destinationsize > $sourcesize) Then
                $destinationsize = $sourcesize
            EndIf
            $progress = $destinationsize / $sourcesize * 100
;~          $donesofar+=
            GUICtrlSetData($showtotalprog,round($donesofar / $size * 100,4)&"%")
            GUICtrlSetData($totalprog,$donesofar / $size * 100)
            GUICtrlSetData($fileprog, $progress)
        EndIf
    Sleep(5)
    WEnd
EndFunc
    
    
Func killproc($pid)
    ; kills a process
    While (ProcessExists($pid))
        ProcessClose($pid)
    WEnd
EndFunc


Func cancelop()
    ; If copystatus = 0 (not copying...)
    If ($copystatus = 0) Then
        GUISetState(@SW_HIDE)
        Exit
    EndIf
    
    If (MsgBox(4 + 32 + 256, "Copy File Progress", "Are you sure you want to cancel file copy?") = 6) Then
        GUICtrlSetState($cancelbtn, $GUI_DISABLE)
            killproc($pid)
            If (FileExists($destination)) Then
            FileDelete($destination)
        EndIf   
        Exit
    EndIf
EndFunc

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

llewxam:

I like your thinking about a dual progress bar. One for current file, and one for total transfer complete.

I've updated my code once again to add decimal places when displaying byte data in variable (default is 2).

I also tried my attempt at the dual progress bar idea.

As of this post, version is v1.1.3

Link to comment
Share on other sites

Looking good, couple things though:

Line 250, $destinationesize should be $destinationsize

There is a command for what your "shortText" function does, add #include <WindowsConstants.au3> and set $DT_END_ELLIPSIS as style for GUICtrlCreateLabel. You would have to make 2 Labels instead of linebreaking one as in $lblfiles, and just use a static Label to show "Source:" and "Destination:", and use $DT_END_ELLIPSIS for the Labels showing $source and $destination. For me this was much easier than manually coding it, is faster, and is more consistent.

Otherwise very good, glad you dig the dual progbars ;)

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
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...