Sign in to follow this  
Followers 0
zdarma

Multiple copies and multiple progress bars

7 posts in this topic

I'm a noob to the world of AutoIT,. I've searched the web and searched the forums on this site, but have not found something that corresponds to my problem.

I have a script that copies files or folders to multiple machines at the same time. I pre-set the number of machines to copy too launch simultaneously in an INI file. This works without a problem. I have a function that is supposed to show the progress for each individual copy that is being done. This is where things seem to get a bit tricky. This is the copy section that calls the function progress GUI:

For $copie = 1 to $aMagCopie[0]
    $aMagasinsChoisi = StringSplit($aMagCopie[$copie], ";")
    run("NET USE \\" & $aMagasinsChoisi[5] & "\d$ /PERSISTENT:NO /USER:" & $sLogin & " " & $sMdp)
    $sDestinationPlace = '"\\' & $aMagasinsChoisi[5] & $sFichiersDest & "\" & $sDossierVerif[$iDossierCreation - 1] &'"'
    Run($sRobocopyCmd & " " & '"' & $sFichierSource & '"' & " " & $sDestinationPlace & " /MIR /R:0 /W:0 /FFT /TEE /LOG:Robocopy_" & $aMagasinsChoisi[1] & "_" & $iDateCopie & ".log")

    _Progress($sFichierSource, $aMagasinsChoisi[1], $sDestinationPlace)

    While 1
        $aProcRobocopy = ProcessList("robocopy.exe")
        If $aProcRobocopy[0][0] < $iMaxCopie Then ExitLoop
        Sleep(500)
    WEnd
Next

This is my GUI progress fucntion

Func _Progress($sSource, $sNomMagasin, $sDestination)

    Global $iGetFicherTaille = StringReplace($sDestination,'"',"")
    Global $iCopierPourcent = 0
    Global $checkadvance = 0

    GUICreate("Progress de la copie pour " & $sNomMagasin, 290, 150, 300, 115) ;Creation de la formulaire
    GUICtrlCreateLabel("Pourcentage de la copie fait pour " & @CRLF & $sNomMagasin, 20, 10, 390, 41)
    GUICtrlSetFont(-1, 10, 400, 0, "MS Sans Serif")

    Global $oBarAvance1 = GUICtrlCreateProgress(20, 75, 250, 15) ;bar de progression

    GUISetState(@SW_SHOW)
    
    If $sFichierTypes = "File" Then
        $iFichierOrigin = FileGetSize($sSource)

        While $iCopierPourcent <= 100
            $iFichierCopied = FileGetSize($iGetFicherTaille)
            $iCopierPourcent = Round((($iFichierCopied / $iFichierOrigin) * 100), 0)
                                
            If $iCopierPourcent > $checkadvance Then
                GUICtrlSetData($oBarAvance1, $iCopierPourcent)
                $spercentEcrit = GUICtrlCreateLabel($iCopierPourcent & "% de la copie est terminée", 20, 125, 250, 15)
            EndIf
            Return
            $checkadvance = $iCopierPourcent
        WEnd
        
    Else
        $iFichierOrigin = DirGetSize($sSource)
        
        While $iCopierPourcent <= 100
            $iFichierCopied = DirGetSize($iGetFicherTaille)
            $iCopierPourcent = Round((($iFichierCopied / $iFichierOrigin) * 100), 0)
        
            If $iCopierPourcent > $checkadvance Then
                GUICtrlSetData($oBarAvance1, $iCopierPourcent)
                $spercentEcrit = GUICtrlCreateLabel($iCopierPourcent & "% de la copie est terminée", 20, 125, 250, 15)
            EndIf
            
            $checkadvance = $iCopierPourcent
            If $iCopierPourcent >= 100 Then
                GUISetState(@SW_HIDE)
                MsgBox(64, "Copie terminé", "La copie est terminé pour" & @CRLF & $sNomMagasin)
                ExitLoop
            EndIf
            Return
        WEnd
    EndIf
EndFunc

If I remove the "return", my script will only do one copy at a time showing me the progress of the copy being done. Once the copy is done for a machine, it will proceed to the next and create a new GUI progress bar for me. If I leave the "return", my script will open up an individual advancement GUI for each copy being done, but will not update the progress at all; but will proceed with the maximum number of copies I've pre-set in my INI file, without showing any advancement.

I've tried putting the GUI progress bar directly in the part of my script that does the copy, but I still run into the same problem. I've tried to create my GUI progress bar as a script and pass the parameters to the script, but for some reason AutoIT doesn't seem to like that any more than the way I have it set up now.

Does any one have an idea how I can get a work around. If needed, I can post my entire script or clear up anything that isn't clear.

Share this post


Link to post
Share on other sites



You should be catching all the PIDs from Run() in an array, creating a progress for each of them and tracking those in an a matching array (or keep both in a 2D array together). While you wait for them to run your loop will update each progress bar for each PID by walking through the array(s).

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

You should be catching all the PIDs from Run() in an array, creating a progress for each of them and tracking those in an a matching array (or keep both in a 2D array together). While you wait for them to run your loop will update each progress bar for each PID by walking through the array(s).

:)

Thanks for the pointer.

Just to be clear, I should use the Run PIDs from the Robocopy.exe ? I am catching those PIDs already to check for number of simultaneous copies running and could use them to loop for each progress bar I need.

Share this post


Link to post
Share on other sites

Maybe I didn't understand your question.

You will have multiple instances of robocopy running at once, right? Did you want a progress bar for each instance, or one progress bar reflecting total progress of all instances?

Either way, you have to poll all the instances of robocopy at regular intervals to either get individual progress or create the total progress. You don't necessarily need the PID to do that, it depends on your method for checking current progress of each copy.

Your GUI needs to be created outside the _Progress() function call. The function should only be updating the GUI, not creating a new one for each copy if you want multiple copies running at once and only one GUI reporting on them.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Maybe I didn't understand your question.

You will have multiple instances of robocopy running at once, right? Did you want a progress bar for each instance, or one progress bar reflecting total progress of all instances?

Either way, you have to poll all the instances of robocopy at regular intervals to either get individual progress or create the total progress. You don't necessarily need the PID to do that, it depends on your method for checking current progress of each copy.

Your GUI needs to be created outside the _Progress() function call. The function should only be updating the GUI, not creating a new one for each copy if you want multiple copies running at once and only one GUI reporting on them.

:)

No worries, if you didn't understand my question. If needed, I can upload my entire script when I get into the office tomorrow and maybe that will make things a little clearer.

I have multiple instances of robocopy running and need a progress bar for each instance. I may need to copy a file or folder to 20 machines, but only 5 will be getting the copy at the same time. As soon as one robocopy is finished, the next machine begins to copy. I'm already checking the number of robocpies running in my script by looking at the value in $aArray[0][0] from ProcessList("robocopy.exe"). Once a copy has finished, I need a message sent that Machine X is done. Then, start copying the next machine in the list and create a new progress bar for the new robocpy instance.

My method for checking the progress done, is by comparing the size of the source to the destination, I do a ((destination/source) * 100) to get the percentage done. It is this number that I use to get the progress bar to advance X number of spaces forward.

Do I still need to create the GUI outside of the _Progress() function call if I want multiple progress bars. If so, do I need to create a function called for example _ProgressGUI() and send the data from _Progress() to _ProgressGUI()?

Edited by zdarma

Share this post


Link to post
Share on other sites

Yes, create the GUI once and just create/update/delete the progress bars as required during the updates.

Here is a working simulation:

#include <GuiConstants.au3>
#include <Array.au3>

Opt("GuiOnEventMode", 1)

Global $iSourceSize = 1234 ; Simulated source size
Global $iTargets = 20 ; Count of targets
Global $aTargets[$iTargets]
For $n = 0 To UBound($aTargets) - 1
    $aTargets[$n] = "Target_" & $n
Next

Global $hGUI
Global $aidProgBars[5] = [-1, -1, -1, -1, -1], $aidLabels[5], $aProgress[5]

$hGUI = GUICreate("Multi-Robo", 400, 385)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit")
GUISetState()

While 1
    _UpdateProgBars()
    _UpdateProgress()
    Sleep(250)
WEnd

Func _UpdateProgBars()
    Local $f_DoneCheck = True

    ; Check the progress bar slots
    For $n = 0 To UBound($aidProgBars) - 1
        If $aidProgBars[$n] = -1 Then
            ; Unused progress spot
            If IsArray($aTargets) Then
                $f_DoneCheck = False ; Not done if there are any new targets left
                $aidLabels[$n] = GUICtrlCreateLabel($aTargets[0], 10, 10 + ($n * 75), 380, 15)
                $aidProgBars[$n] = GUICtrlCreateProgress(10, 25 + ($n * 75), 380, 50)
                $aProgress[$n] = 0
                _ArrayDelete($aTargets, 0)
            EndIf
        Else
            $f_DoneCheck = False ; Not done if there are any active progress bars left
            If $aProgress[$n] >= $iSourceSize Then
                ; Finished progress spot
                GUICtrlDelete($aidLabels[$n])
                GUICtrlDelete($aidProgBars[$n])
                $aidProgBars[$n] = -1
            EndIf
        EndIf
    Next

    If $f_DoneCheck Then
        MsgBox(64, "Multi-Robo", "Done")
        Exit
    EndIf
EndFunc   ;==>_UpdateProgBars

Func _UpdateProgress()
    For $n = 0 To UBound($aidProgBars) - 1
        If $aidProgBars[$n] <> -1 Then
            ; Simulated progress
            If $aProgress[$n] < $iSourceSize Then $aProgress[$n] += Random(10, 100, 1)
            If $aProgress[$n] > $iSourceSize Then $aProgress[$n] = $iSourceSize

            ; Update the GUI
            GUICtrlSetData($aidProgBars[$n], $aProgress[$n] / $iSourceSize * 100)
        EndIf
    Next
EndFunc   ;==>_UpdateProgress

Func _Quit()
    Exit
EndFunc   ;==>_Quit

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

PsaltyDS, thanks for the snippet. I took a look at it and it does exactly what I wanted to happen.

I'm going to try and integrate it into my script now. Youùll know when its done when you see me :) in the streets.

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