Sign in to follow this  
Followers 0
darbid

Yet another please help me with progress bars

8 posts in this topic

I am unable to get my mind around progress bars, which actually reflect the progress of my event.

I am doing an "install" - a copy of a directory from a network (access could be at varied speeds - thus the need to show actual progress and not some timed progress bar)

I have found many snippets and exmples of file progress bars using file copy and arrays but not much on a directory.

I also have my own eyecandy PNG gui (which I am very chuffed about) so just want to add a progress bar to that and not use a standard windows window.

Could somebody link me to an example which WORKS, that I can then read, understand and convert for my own needs. I am sure there are loads of examples.

Share this post


Link to post
Share on other sites



Hi,

Bottom line is if you want to copy a directory that contains other directories and files and you want a semi accurate progress bar then do a recursive filelist to array of the directory, loop through the array copying each file/folder and set the progress bar a step each time a file/folder copies.

Cheers

Share this post


Link to post
Share on other sites

and would your answer change if there are no sub folders?

semi accurate progress bar then do a recursive filelist to array of the directory, loop through the array copying each file/folder and set the progress bar a step each time a file/folder copies.

and has someone ever posted an example of this here.

Share this post


Link to post
Share on other sites

This will handle sub directorys if needed. Alot of the _DirCopy func was hardcoded for my personal use, but could easily be adapted to update a global Progressbar.

#include <WindowsConstants.au3>
#include <GUIConstantsEX.au3>
#include <ProgressConstants.au3>


_DirCopy("c:\DRV","c:\DRV2") ;example use





;===============================================================================
; Function Name:    _DirCopy
; Description:      
; Requires:         GUIConstantsEx.au3, WindowsConstants.au3, ProgressConstants.au3
;                       must set $Progress_ControlID as Global
; Parameters:       $Source                 Source Directory to Copy from
;                   $Dest                   Destination directory to copy to
; Syntax:           _DirCopy($Source,$Dest)
; Author(s):        ofLight
; Returns:          
;===============================================================================
Func _DirCopy($Source,$Dest)
    If WinExists('GUI_RobocopyProgress') Then
        GUICtrlSetState($Progress_ControlID,0)
        GUISetState(@SW_SHOW,$GUI_RS_DirCopy)
        ;GUISetState(@SW_SHOW,$Progress_ControlID) ;WTF is up with THIS>?!?
        $Progress_ControlID = GUICtrlCreateProgress(10, 5, 380, 20, $PBS_SMOOTH)
        GUISetState(@SW_SHOW)
    Else
        $GUI_RS_DirCopy = GUICreate('GUI_RobocopyProgress',400,40, -1, (@DesktopHeight/2)+70, BitOR($WS_POPUP, $WS_BORDER))
                GUISetBkColor(16777215)
        $Progress_ControlID = GUICtrlCreateProgress(10, 5, 380, 20, $PBS_SMOOTH)
        $Progress_LabelID = GUICtrlCreateLabel("",10,25,380)
                GUISetBkColor(16777215)
                GUISetState(@SW_SHOW)
    EndIf

    If $Source <> "" Then _SUB_CopyDirWithProgress($Source, $Dest, $Progress_ControlID,$Progress_LabelID)

    GUICtrlSetState($Progress_ControlID,100)
    Sleep(50)
    GUISetState(@SW_HIDE,$GUI_RS_DirCopy)

EndFunc

Func _SUB_CopyDirWithProgress($sOriginalDir, $sDestDir, $Progress_ControlID, $Label_ControlID);SUB Function of _DirCopy

    If StringRight($sOriginalDir, 1) <> '\' Then $sOriginalDir = $sOriginalDir & '\'
    If StringRight($sDestDir, 1) <> '\' Then $sDestDir = $sDestDir & '\'
    If $sOriginalDir = $sDestDir Then Return -1

    ;ProgressOn('Copying...', 'Making list of files...' & @LF & @LF, '', -1, -1, 18)
    Local $aFileList = _SUB_FileSearch($sOriginalDir)
    If $aFileList[0] = 0 Then
        ;ProgressOff()
        SetError(1)
        Return -1
    EndIf

    If FileExists($sDestDir) Then
        If Not StringInStr(FileGetAttrib($sDestDir), 'd') Then
            ;ProgressOff()
            SetError(2)
            Return -1
        EndIf
    Else
        DirCreate($sDestDir)
        If Not FileExists($sDestDir) Then
            ;ProgressOff()
            SetError(2)
            Return -1
        EndIf
    EndIf

    Local $iDirSize, $iCopiedSize = 0, $fProgress = 0
    Local $c, $FileName, $iOutPut = 0, $sLost = '', $sError
    Local $Sl = StringLen($sOriginalDir)

    _SUB_Quick_Sort($aFileList, 1, $aFileList[0])

    $iDirSize = Int(DirGetSize($sOriginalDir) / 1024)

    GUICtrlSetData($Progress_ControlID,Int($fProgress * 100))
    GUICtrlSetData($Label_ControlID,$aFileList[$c])
    For $c = 1 To $aFileList[0]
        $FileName = StringTrimLeft($aFileList[$c], $Sl)
        GUICtrlSetData($Progress_ControlID,Int($fProgress * 100))
        GUICtrlSetData($Label_ControlID, 'Total: '&$iDirSize&'Kb  --> Done: '&$iCopiedSize&'Kb            '&StringTrimLeft($aFileList[$c],StringInStr($aFileList[$c],"\",0,-1)))
        
        If StringInStr(FileGetAttrib($aFileList[$c]), 'd') Then
            DirCreate($sDestDir & $FileName)
        Else
            If Not FileCopy($aFileList[$c], $sDestDir & $FileName, 1) Then
                If Not FileCopy($aFileList[$c], $sDestDir & $FileName, 1) Then;Tries a second time
                    If RunWait(@ComSpec & ' /c copy /y "' & $aFileList[$c] & '" "' & $sDestDir & $FileName & '">' & @TempDir & '\o.tmp', '', @SW_HIDE) = 1 Then;and a third time, but this time it takes the error message
                        $sError = FileReadLine(@TempDir & '\o.tmp', 1)
                        $iOutPut = $iOutPut + 1
                        $sLost = $sLost & $aFileList[$c] & '  ' & $sError & @CRLF
                    EndIf
                    FileDelete(@TempDir & '\o.tmp')
                EndIf
            EndIf
            
            FileSetAttrib($sDestDir & $FileName, "+A-RSH");<- Comment this line if you do not want attribs reset.
            
            $iCopiedSize = $iCopiedSize + Int(FileGetSize($aFileList[$c]) / 1024)
            $fProgress = $iCopiedSize / $iDirSize
        EndIf
    Next


    If $sLost <> '' Then;tries to write the log somewhere.
        If FileWrite($sDestDir & 'notcopied.txt', $sLost) = 0 Then
            If FileWrite($sOriginalDir & 'notcopied.txt', $sLost) = 0 Then
                FileWrite(@WorkingDir & '\notcopied.txt', $sLost)
            EndIf
        EndIf
    EndIf

    Return $iOutPut
EndFunc   ;==>_CopyDirWithProgress

Func _SUB_FileSearch($sIstr, $bSF = 1);SUB Function of _DirCopy
    ; $bSF = 1 means looking in subfolders
    ; $sSF = 0 means looking only in the current folder.
    ; An array is returned with the full path of all files found. The pos [0] keeps the number of elements.
    Local $sCriteria, $sBuffer, $iH, $iH2, $sCS, $sCF, $sCF2, $sCP, $sFP, $sOutPut = '', $aNull[1]
    ;Local $sIstr, $bSF, $sCriteria, $sBuffer, $iH, $iH2, $sCS, $sCF, $sCF2, $sCP, $sFP, $sOutPut = '', $aNull[1]
    $sCP = StringLeft($sIstr, StringInStr($sIstr, '\', 0, -1))
    If $sCP = '' Then $sCP = @WorkingDir & '\'
    $sCriteria = StringTrimLeft($sIstr, StringInStr($sIstr, '\', 0, -1))
    If $sCriteria = '' Then $sCriteria = '*.*'

    ;To begin we seek in the starting path.
    $sCS = FileFindFirstFile($sCP & $sCriteria)
    If $sCS <> -1 Then
        Do
            $sCF = FileFindNextFile($sCS)
            If @error Then
                FileClose($sCS)
                ExitLoop
            EndIf
            If $sCF = '.' Or $sCF = '..' Then ContinueLoop
            $sOutPut = $sOutPut & $sCP & $sCF & @LF
        Until 0
    EndIf

    ;And after, if needed, in the rest of the folders.
    If $bSF = 1 Then
        $sBuffer = @CR & $sCP & '*' & @LF;The buffer is set for keeping the given path plus a *.
        Do
            $sCS = StringTrimLeft(StringLeft($sBuffer, StringInStr($sBuffer, @LF, 0, 1) - 1), 1);current search.
            $sCP = StringLeft($sCS, StringInStr($sCS, '\', 0, -1));Current search path.
            $iH = FileFindFirstFile($sCS)
            If $iH <> -1 Then
                Do
                    $sCF = FileFindNextFile($iH)
                    If @error Then
                        FileClose($iH)
                        ExitLoop
                    EndIf
                    If $sCF = '.' Or $sCF = '..' Then ContinueLoop
                    If StringInStr(FileGetAttrib($sCP & $sCF), 'd') Then
                        $sBuffer = @CR & $sCP & $sCF & '\*' & @LF & $sBuffer;Every folder found is added in the begin of buffer
                        $sFP = $sCP & $sCF & '\';                               for future searches
                        $iH2 = FileFindFirstFile($sFP & $sCriteria);         and checked with the criteria.
                        If $iH2 <> -1 Then
                            Do
                                $sCF2 = FileFindNextFile($iH2)
                                If @error Then
                                    FileClose($iH2)
                                    ExitLoop
                                EndIf
                                If $sCF2 = '.' Or $sCF2 = '..' Then ContinueLoop
                                $sOutPut = $sOutPut & $sFP & $sCF2 & @LF;Found items are put in the Output.
                            Until 0
                        EndIf
                    EndIf
                Until 0
            EndIf
            $sBuffer = StringReplace($sBuffer, @CR & $sCS & @LF, '')
        Until $sBuffer = ''
    EndIf

    If $sOutPut = '' Then
        $aNull[0] = 0
        Return $aNull
    Else
        Return StringSplit(StringTrimRight($sOutPut, 1), @LF)
    EndIf
EndFunc   ;==>_FileSearch

Func _SUB_Quick_Sort(ByRef $SortArray, $First, $Last);Larry's code ;SUB Function of _DirCopy
    Dim $Low, $High
    Dim $Temp, $List_Separator

    $Low = $First
    $High = $Last
    $List_Separator = StringLen($SortArray[($First + $Last) / 2])
    Do
        While (StringLen($SortArray[$Low]) < $List_Separator)
            $Low = $Low + 1
        WEnd
        While (StringLen($SortArray[$High]) > $List_Separator)
            $High = $High - 1
        WEnd
        If ($Low <= $High) Then
            $Temp = $SortArray[$Low]
            $SortArray[$Low] = $SortArray[$High]
            $SortArray[$High] = $Temp
            $Low = $Low + 1
            $High = $High - 1
        EndIf
    Until $Low > $High
    If ($First < $High) Then _SUB_Quick_Sort($SortArray, $First, $High)
    If ($Low < $Last) Then _SUB_Quick_Sort($SortArray, $Low, $Last)
EndFunc   ;==>_Quick_Sort

There is always a butthead in the crowd, no matter how hard one tries to keep them out.......Volly

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

thanks oflight i will give it a go

edit: that is not going to be as easy as I thought. I can copy directories, YEH YEH but that is the easy bit.

As I am future planning what will be copied in these directories, but at the moment there is not much. This code really does not show progress if there are a small number of files in there, in fact with one file it showns none, but gets the job done.

Edited by darbid

Share this post


Link to post
Share on other sites

You are correct, this process does not keep track of how much of each file has been copied over, only how many have been completed ( I couldn't find that info being piped out by the copy command). Because of this, copying 1 or 2 large files will not display smoothly. This process works best for directories with large quantities of files.


There is always a butthead in the crowd, no matter how hard one tries to keep them out.......Volly

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

keeping in mind that I am an idiot and have no idea how these things work -

Has anyone seen a progress bar where it somehow measures the size of the task (here size of files) at the beginning and then measures the amount copied as it is copied thus giving a % complete.

for example this guys has used some other way ut sadly nothing is there.

forum post

Edited by darbid

Share this post


Link to post
Share on other sites

So I have found this solution which uses a windows explorer window

Windows Explorer Solution

But I too want to use my lovely GUI (with png background) that I have made and not go to a windows explorer window.

The reason why you all stop short of coming to a solution (I THINK) is that the logical answer is to use a dirgetsize on source and destination, but because windows allocates the destiantion directory size straight away the progress bar show 100% straight away.

eg problem with using dirgetsize

So at the risk of asking the same question another way :-) has anyone found a solution to this, or maybe can someone see a possibility here to try something new?

Share this post


Link to post
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
Sign in to follow this  
Followers 0