Sign in to follow this  
Followers 0
Matt Houston

Stdoutread And Robocopy - How To Parse All The Info?

30 posts in this topic

Hi,

I would like to combine my script with robocopy in order to get some (per-file) percentage values.

Basically it's working but i'm stuck with parsing the data. Here's my code so far (not much indeed...):

#include <constants.au3>

$sourcedir = "c:\copytest\"
$destdir = "c:\copytest2\"

$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir & ' /E /NJH /NJS /NDL /NC', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)

While 1
    $line = StdoutRead($copyjob)
    If @error = -1 Then ExitLoop
    MsgBox(0, "STDOUT read:", $line)
Wend

I just used a message box to see if anything is read by StoudRead - that's working! The message box is FULL of info!

At the moment the fetched data looks like this:

filesize   filename.exe
1%
2%
4%
6%
7%
8%
....

My question is: Is it possible to "StdoutRead-line-by-line"? Is there some way to parse the info?

My idea was to get this line by line and parse it in order to get the single values (this is the actual output from robocopy in the cmd box):

100%                       4.2 m        c:\copytest\file1.xls
100%                       53248        c:\copytest\file2.exe    
100%                          52        c:\copytest\file3.ini

Maybe somebody as a few hints to get me back on track...

Greetings,

MattHouston

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Maybe you could add something like

If StringLeft($line, 4) = "100%" Then MsgBox(0, "STDOUT read:", $line)

??? I don't have a copy to test it now, so it's up to you :think: .

Have a look at tail if this doesn't do the trick.

Edited by dabus

Share this post


Link to post
Share on other sites

Post the output from here:

#include <constants.au3>

$sourcedir = "c:\copytest\"
$destdir = "c:\copytest2\"

$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir & ' /E /NJH /NJS /NDL /NC', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)

$output = ""
While ProcessExists($copyjob)
    If StdoutRead($copyjob, 0, true) > 0 Then
        $output &= StdoutRead($copyjob)
    EndIf
    Sleep(1000)
WEnd
If StdoutRead($copyjob, 0, true) > 0 Then
    $output &= StdoutRead($copyjob)
EndIf
ClipPut($output); So you can copy it into the forums
MsgBox(0,"",$output)

If you post the output from there (all of the output amassed into one string), and then tell exactly what you want parsed out of it, then I should be able to help you out. You could also have a look at StringRegExp guide, in my signature, it tells you (not all of) how to use the function StringRegExp() to parse text.


[u]My UDFs[/u]Coroutine Multithreading UDF LibraryStringRegExp GuideRandom EncryptorArrayToDisplayString"The Brain, expecting disaster, fails to find the obvious solution." -- neogia

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

neogia - thanks for your help! I didn't even know ClipPut :think:

So here's what i got:

4.2 m   c:\copytest\filename1.xls
  0%  
  1%  
  2%  
  4%  
  5%  
  7%  
  8%  
 10%  
 11%  
........
 94%  
 96%  
 97%  
 99%  
100%  
                 53248  c:\copytest\filename2.EXE
  0%  
100%  
                147654  c:\copytest\filename3.bmp
  0%  
 44%  
 88%  
100%
I just shortened it a bit in the middle - no need to watch all those numbers...

I would like to use these three values (percentage, filesize and filename) to make a progress bar / progress window.

I will definately read your guide - but i'm unsure if i find the time today.

Again, thank you very much for your help! I really appreciate that!

Matt

Edited by Matt Houston

Share this post


Link to post
Share on other sites

Alright, this should get you started, I'll leave the GUI part to you, it's good to learn. What I've done here is created a StringRegExp that will either return an array of one element (If it is a progress update line [0] = progress in percent) or two elements (If it is a new file being copied [0] = filesize [1] = filename). I've also set up the loop that should run after you start the robocopy job. It assumes you save the PID from the Run() command in the variable $copyjob.

While ProcessExists($copyjob)
    If StdoutRead($copyjob, 0, true) > 0 Then
        $output &= StdoutRead($copyjob)
        If StringInStr($output, @CRLF) Then
            $output = StringSplit($output, @CRLF)
            For $i = 1 To $output[0]
                $result = StringRegExp($output[$i], '(\d+%)|([0-9\\.]+\s*[mg]?)\s*(.*)', 1)
                If IsArray($result) Then
                    If StringInStr($result[0], "%") Then; Current line is a progress update line
                    ; Set current progress bar to StringTrimRight($result[0], 1)
                    ; Set current progress percent label to $result[0]
                    Else; Current line is a new file line
                    ; Reset progress bar to 0
                    ; Reset progress percent label to "0%"
                    ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                    ; Set current file name label to $result[1] (outputted as full filepath)
                    EndIf
                EndIf
            Next
        EndIf
    EndIf
WEnd
; Do one more in case there's any output left in the stream after the $copyjob closes
If StdoutRead($copyjob, 0, true) > 0 Then
    $output &= StdoutRead($copyjob)
    If StringInStr($output, @CRLF) Then
        $output = StringSplit($output, @CRLF)
        For $i = 1 To $output[0]
            $result = StringRegExp($output[$i], '(\d+%)|([0-9\\.]+\s*[mg]?)\s*(.*)', 1)
            If IsArray($result) Then
                If StringInStr($result[0], "%") Then; Current line is a progress update line
                ; Set current progress bar to StringTrimRight($result[0], 1)
                ; Set current progress percent label to $result[0]
                Else; Current line is a new file line
                ; Reset progress bar to 0
                ; Reset progress percent label to "0%"
                ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                ; Set current file name label to $result[1] (outputted as full filepath)
                EndIf
            EndIf
        Next
    EndIf
EndIf

[u]My UDFs[/u]Coroutine Multithreading UDF LibraryStringRegExp GuideRandom EncryptorArrayToDisplayString"The Brain, expecting disaster, fails to find the obvious solution." -- neogia

Share this post


Link to post
Share on other sites

I had this same issue a while back. The solution is to run RoboCopy with the "/np" option. Also note that RoboCopy has a "/tee" parameter which works very much like the linux tee command.

RoboCopy has a ton of options, do a "/?" to see them. It also comes with a pretty good manual.

Share this post


Link to post
Share on other sites

I think np could be no-process.

tee writes output to stdout and a file.

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Oops, sorry I got this post mixed up with another one I was helping with RoboCopy.

the "/np" parameter turns off the percentage signs.

What you want to do is read a line and parse the file name out of it. if the line has a percentage sign in it, then it is a percentage for the last file. Since a file cannot has a percentage sign in it's name, then you automatically know that all lines that contain percentage signs are progress marks for the last-mentioned file.

Some other options you might want to look into are /NJH /NJS /ETA.

Again I will say that using the /? and the RoboCopy documentation will answer all your questions. I've been doing some automation using RoboCopy to synchronize folders and shares and I have to say that it is well documented.

Here is the command summary ( /? ) for reference for those who are trying to help that do not have RoboCopy installed:

-------------------------------------------------------------------------------
   ROBOCOPY  ::  Robust File Copy for Windows    ::  Version XP010
-------------------------------------------------------------------------------

  Started : Fri Apr 28 14:07:36 2006

              Usage :: ROBOCOPY source destination [file [file]...] [options]

             source :: Source Directory (drive:\path or \\server\share\path).
        destination :: Destination Dir  (drive:\path or \\server\share\path).
               file :: File(s) to copy  (names/wildcards: default is "*.*").

::
:: Copy options :
::
                 /S :: copy Subdirectories, but not empty ones.
                 /E :: copy subdirectories, including Empty ones.
             /LEV:n :: only copy the top n LEVels of the source directory tree.

                 /Z :: copy files in restartable mode.
                 /B :: copy files in Backup mode.
                /ZB :: use restartable mode; if access denied use Backup mode.

  /COPY:copyflag[s] :: what to COPY (default is /COPY:DAT).
                       (copyflags : D=Data, A=Attributes, T=Timestamps).
                       (S=Security=NTFS ACLs, O=Owner info, U=aUditing info).

               /SEC :: copy files with SECurity (equivalent to /COPY:DATS).
           /COPYALL :: COPY ALL file info (equivalent to /COPY:DATSOU).
            /NOCOPY :: COPY NO file info (useful with /PURGE).

             /PURGE :: delete dest files/dirs that no longer exist in source.
               /MIR :: MIRror a directory tree (equivalent to /E plus /PURGE).

               /MOV :: MOVe files (delete from source after copying).
              /MOVE :: MOVE files AND dirs (delete from source after copying).

       /A+:[RASHNT] :: add the given Attributes to copied files.
       /A-:[RASHNT] :: remove the given Attributes from copied files.

            /CREATE :: CREATE directory tree and zero-length files only.
               /FAT :: create destination files using 8.3 FAT file names only.
               /FFT :: assume FAT File Times (2-second granularity).
               /256 :: turn off very long path (> 256 characters) support.

             /MON:n :: MONitor source; run again when more than n changes seen.
             /MOT:m :: MOnitor source; run again in m minutes Time, if changed.

      /RH:hhmm-hhmm :: Run Hours - times when new copies may be started.
                /PF :: check run hours on a Per File (not per pass) basis.

             /IPG:n :: Inter-Packet Gap (ms), to free bandwidth on slow lines.

::
:: File Selection Options :
::
                 /A :: copy only files with the Archive attribute set.
                 /M :: copy only files with the Archive attribute and reset it.
    /IA:[RASHCNETO] :: Include only files with any of the given Attributes set.
    /XA:[RASHCNETO] :: eXclude files with any of the given Attributes set.

 /XF file [file]... :: eXclude Files matching given names/paths/wildcards.
 /XD dirs [dirs]... :: eXclude Directories matching given names/paths.

                /XC :: eXclude Changed files.
                /XN :: eXclude Newer files.
                /XO :: eXclude Older files.
                /XX :: eXclude eXtra files and directories.
                /XL :: eXclude Lonely files and directories.
                /IS :: Include Same files.
                /IT :: Include Tweaked files.

             /MAX:n :: MAXimum file size - exclude files bigger than n bytes.
             /MIN:n :: MINimum file size - exclude files smaller than n bytes.

          /MAXAGE:n :: MAXimum file AGE - exclude files older than n days/date.
          /MINAGE:n :: MINimum file AGE - exclude files newer than n days/date.
          /MAXLAD:n :: MAXimum Last Access Date - exclude files unused since n.
          /MINLAD:n :: MINimum Last Access Date - exclude files used since n.
                       (If n < 1900 then n = n days, else n = YYYYMMDD date).

                /XJ :: eXclude Junction points. (normally included by default).

::
:: Retry Options :
::
               /R:n :: number of Retries on failed copies: default 1 million.
               /W:n :: Wait time between retries: default is 30 seconds.

               /REG :: Save /R:n and /W:n in the Registry as default settings.

               /TBD :: wait for sharenames To Be Defined (retry error 67).

::
:: Logging Options :
::
                 /L :: List only - don't copy, timestamp or delete any files.
                 /X :: report all eXtra files, not just those selected.
                 /V :: produce Verbose output, showing skipped files.
                /TS :: include source file Time Stamps in the output.
                /FP :: include Full Pathname of files in the output.

                /NS :: No Size - don't log file sizes.
                /NC :: No Class - don't log file classes.
               /NFL :: No File List - don't log file names.
               /NDL :: No Directory List - don't log directory names.

                /NP :: No Progress - don't display % copied.
               /ETA :: show Estimated Time of Arrival of copied files.

          /LOG:file :: output status to LOG file (overwrite existing log).
         /LOG+:file :: output status to LOG file (append to existing log).

               /TEE :: output to console window, as well as the log file.

               /NJH :: No Job Header.
               /NJS :: No Job Summary.

::
:: Job Options :
::
       /JOB:jobname :: take parameters from the named JOB file.
      /SAVE:jobname :: SAVE parameters to the named job file
              /QUIT :: QUIT after processing command line (to view parameters).

              /NOSD :: NO Source Directory is specified.
              /NODD :: NO Destination Directory is specified.
                /IF :: Include the following Files.
Edited by blindwig

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Well.. I wrote this without seeing that neogia had posted a solution already. His is much more elegant.

So, here is one that will give you a Progress bar with the filepath, filesize, and % completed.

#include <Constants.au3>

$sourcedir = "c:\copytest\"
$destdir = "c:\copytest2\"
$ourProcess = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir & ' /E /NJH /NJS /NDL /NC', @ScriptDir, @SW_HIDE, $STDOUT_CHILD)

ProgressOn("RoboCopy", "Copying Files...", "0%",-1,-1,18)

While 1
   If $ourProcess Then
      $charsWaiting = StdoutRead($ourProcess, 0 , 1)
      If @error = -1 Then
         $ourProcess = 0
            MsgBox(0, "App Exited", "Process has exited...")
         ContinueLoop
      EndIf
      If $charsWaiting Then
         $currentRead = StdoutRead($ourProcess)
         $fileinfo = StringRegExp($currentRead, '(.*?)([:alpha:]:.*\.[a-zA-Z]{3})',3)
         If IsArray($fileinfo) = 1 Then
             $filesize = StringStripCR(StringStripWS($fileinfo[0],8))
             $filename = $fileinfo[1]
         EndIf
         $percent = StringRegExp($currentRead, '([0-9]{1,3})(?:.[0-9]{1,3})(?:%)',3)
         If IsArray($percent) = 1 Then
         ProgressSet($percent[0],$percent[0]&"% "&@CRLF&"Filename: "&$filename&@CRLF&"Filesize: "&$filesize)
         EndIf
      EndIf
   EndIf
WEnd
ProgressOff()
Exit
Edited by Simucal

AutoIt Scripts:Aimbot: Proof of Concept - PixelSearching Aimbot with several search/autoshoot/lock-on techniques.Sliding Toolbar - Add a nice Sliding Toolbar to your next script. Click the link to see an animation of it in action!FontInfo UDF - Get list of system fonts, or search to see if a particular font is installed.Get Extended Property UDF - Retrieve a files extended properties (e.g., video/image dimensions, file version, bitrate of song/video, etc)

Share this post


Link to post
Share on other sites

#11 ·  Posted

Thanks for your help mates! Sorry that i could not get back earlier... (way too much work these days...)

@neogia:

i just had a quick go on your script - unfortunately it did not work (at least my part...) i tried to build a prograssbar around it - with no success. if i understood the concept i need to create the progressbar *BEFORE* the loop starts, the update should then be done inside the loop, right?

...
If IsArray($result) Then
                    If StringInStr($result[0], "%") Then; Current line is a progress update line
                    $progress = StringTrimRight($result[0], 1)
                    MsgBox (4096,"Test", $progress)
...

I just used a message box in order to see if this part is running - i also tried to update a progressbar at this point.

One small thing - on line number three your script says:

$output &= StdoutRead($copyjob)
Is the "&" a typo?

@simucal:

Your script is working - for one file. As soon, as there are some more files in the folder it struggles and the progressbar is no longer updated.

Unfortunately i don't have the time to investigate all this at the moment. My boss gave me some high priority tasks - so i will get back to this in about 2 weeks.

But at least i wanted to thank you for your support! I learned a lot in this forum and i'm sure we will get this working too!

So long!

Matt Houston

Share this post


Link to post
Share on other sites

#12 ·  Posted

$output &= StdoutRead($copyjob)

Is not a typo: it means "concatenate StdoutRead($copyjob) to whatever's already in $output".

It's equivalent to:

$output = $output & StdoutRead($copyjob)

Could you maybe post the files that you're using, and I can work on finding out why neither mine nor simucal's scripts are working sufficiently? Like robocopy.exe and a test input file?


[u]My UDFs[/u]Coroutine Multithreading UDF LibraryStringRegExp GuideRandom EncryptorArrayToDisplayString"The Brain, expecting disaster, fails to find the obvious solution." -- neogia

Share this post


Link to post
Share on other sites

#13 ·  Posted

$output &= StdoutRead($copyjob)

Is not a typo: it means "concatenate StdoutRead($copyjob) to whatever's already in $output".

It's equivalent to:

$output = $output & StdoutRead($copyjob)
Ooops... Have to read more about the syntax... :think:

Could you maybe post the files that you're using, and I can work on finding out why neither mine nor simucal's scripts are working sufficiently? Like robocopy.exe and a test input file?

Sure - robocopy.exe is attached to this post. I think that's ok, as Microsoft is distributing this freely. I don't think that it is important to use the same files which i've been using. I just picked some random files (i always took one larger file (200 MB), because otherwise the script does not run long enough).

Greetings,

MattHouston

robocopy.zip

Share this post


Link to post
Share on other sites

#14 ·  Posted

Well, this is a working script, but it's a little fishy: with large files, it appears that robocopy spews out thousands and thousands of percentage updates, which causes a delay in the update of the progress bar. After the delay, the progress updates smoothly, but I'm sure there's a way to either skip some of the percentage updates or something to prevent that lag. Anywho, here's a script for you to play around with at least:

#include <GUIConstants.au3>

$GUI = GUICreate("Progress", 300, 100)
GUICtrlCreateLabel("Current File: ", 10, 10)
$fileLbl = GUICtrlCreateLabel("N/A", 75, 10, 225)
GUICtrlCreateLabel("Current File Size: ", 10, 25)
$sizeLbl = GUICtrlCreateLabel("N/A", 95, 25, 105)
$progress = GUICtrlCreateProgress(10, 50, 280)
GUISetState()

$sourcedir = "c:\copytest\"
$destdir = "c:\copytest2\"

$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir, @ScriptDir, @SW_HIDE, 7)
$output = ""
$switch = 0; We don't want to run StringRegExp on lines that don't matter to us
While ProcessExists($copyjob)
    If StdoutRead($copyjob, 0, true) > 0 Then
        $output &= StdoutRead($copyjob)
        If StringInStr($output, @CRLF) Then
            $output = StringSplit($output, @CRLF)
            For $i = 1 To $output[0] - 1
                If  Not $switch Then
                    If StringRegExp($output[$i], '\d+\s+' & StringReplace($sourcedir, "\", "\\")) == 1 Then 
                        $switch = Not $switch
                        $i += 1
                    EndIf
                EndIf
                If $switch Then
                    $result = StringRegExp($output[$i], '([0-9.]+%)|([0-9.]+\s*[mg]?)\s*(.*)', 1)
                    If IsArray($result) Then
                        If StringInStr($result[0], "%") Then; Current line is a progress update line
                        ; Set current progress bar to StringTrimRight($result[0], 1)
                            GUICtrlSetData($progress, StringTrimRight($result[0], 1))
                        ; Set current progress percent label to $result[0]
                        Else; Current line is a new file line
                        ; Reset progress bar to 0
                            GUICtrlSetData($progress, 0)
                        ; Reset progress percent label to "0%"
                        ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                            GUICtrlSetData($sizeLbl, $result[0])
                        ; Set current file name label to $result[1] (outputted as full filepath)
                            GUICtrlSetData($fileLbl, $result[1])
                        EndIf
                    EndIf
                EndIf
            Next
            $output = $output[$output[0]]
        EndIf
    EndIf
WEnd
; Do one more in case there's any output left in the stream after the $copyjob closes
If StdoutRead($copyjob, 0, true) > 0 Then
    $output &= StdoutRead($copyjob)
    If StringInStr($output, @CRLF) Then
        $output = StringSplit($output, @CRLF)
        For $i = 1 To $output[0]
            If  Not $switch Then
                If StringRegExp($output[$i], '\d+\s+' & StringReplace($sourcedir, "\", "\\")) Then 
                    $switch = Not $switch
                    $i += 1
                EndIf
            EndIf
            If $switch Then
                $result = StringRegExp($output[$i], '([0-9.]+%)|([0-9.]+\s*[mg]?)\s*(.*)', 1)
                If IsArray($result) Then
                    If StringInStr($result[0], "%") Then; Current line is a progress update line
                    ; Set current progress bar to StringTrimRight($result[0], 1)
                        GUICtrlSetData($progress, StringTrimRight($result[0], 1))
                    ; Set current progress percent label to $result[0]
                    Else; Current line is a new file line
                    ; Reset progress bar to 0
                        GUICtrlSetData($progress, 0)
                    ; Reset progress percent label to "0%"
                    ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                        GUICtrlSetData($sizeLbl, $result[0])
                    ; Set current file name label to $result[1] (outputted as full filepath)
                        GUICtrlSetData($fileLbl, $result[1])
                    EndIf
                EndIf
            EndIf
        Next
    EndIf
EndIf

Note: You'll have to try files > ~50Mb for a human to be able to read the output. :)


[u]My UDFs[/u]Coroutine Multithreading UDF LibraryStringRegExp GuideRandom EncryptorArrayToDisplayString"The Brain, expecting disaster, fails to find the obvious solution." -- neogia

Share this post


Link to post
Share on other sites

Hello,

Anyone have a all code complete with progressbar?

I trie use this code but copy files, not copy folders, subfolders and progressbar not run.

My project is copy one disk partition with letter D:\ (Total 60gb) to folder user that this to my server.

Share this post


Link to post
Share on other sites

Hi,

I have the same sort of question (see http://www.autoitscript.com/forum/index.php?showtopic=84017 ). I want to show a progress bar but it doesn't work. I have tried the example up here. Same behaviour. The task runs in the background, the copy is effective but nothing is visible in the progress bar. I suspect that the StdoutRead never returns before completing of external task even with the switch "peek" (3rd parameter). It returns at the end with the total output of external task. Not what I need. Does someone of the development team can address such a problem? Thank you. Regards

Share this post


Link to post
Share on other sites

Sorry to resurrect an old thread, but I thought it might be worth mentioning that each time a percentage is output by robocopy, it prepends it with an @LF, not a @CRLF. If you manually run robocopy, you'll notice that the percent is always at the beginning of the line; it doesn't scroll, thus the @LF only.

Watching for the @LF and taking from that to the % sign will give you your percentage. Compare that to the percent you already have and only update the progress bar if it has changed to avoid the thousands of updates issue.


My UDFs: ExitCodes

Share this post


Link to post
Share on other sites

Well, this is a working script, but it's a little fishy: with large files, it appears that robocopy spews out thousands and thousands of percentage updates, which causes a delay in the update of the progress bar. After the delay, the progress updates smoothly, but I'm sure there's a way to either skip some of the percentage updates or something to prevent that lag. Anywho, here's a script for you to play around with at least:

#include <GUIConstants.au3>

$GUI = GUICreate("Progress", 300, 100)
GUICtrlCreateLabel("Current File: ", 10, 10)
$fileLbl = GUICtrlCreateLabel("N/A", 75, 10, 225)
GUICtrlCreateLabel("Current File Size: ", 10, 25)
$sizeLbl = GUICtrlCreateLabel("N/A", 95, 25, 105)
$progress = GUICtrlCreateProgress(10, 50, 280)
GUISetState()

$sourcedir = "c:\copytest\"
$destdir = "c:\copytest2\"

$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir, @ScriptDir, @SW_HIDE, 7)
$output = ""
$switch = 0; We don't want to run StringRegExp on lines that don't matter to us
While ProcessExists($copyjob)
    If StdoutRead($copyjob, 0, true) > 0 Then
        $output &= StdoutRead($copyjob)
        If StringInStr($output, @CRLF) Then
            $output = StringSplit($output, @CRLF)
            For $i = 1 To $output[0] - 1
                If  Not $switch Then
                    If StringRegExp($output[$i], '\d+\s+' & StringReplace($sourcedir, "\", "\\")) == 1 Then 
                        $switch = Not $switch
                        $i += 1
                    EndIf
                EndIf
                If $switch Then
                    $result = StringRegExp($output[$i], '([0-9.]+%)|([0-9.]+\s*[mg]?)\s*(.*)', 1)
                    If IsArray($result) Then
                        If StringInStr($result[0], "%") Then; Current line is a progress update line
                    ; Set current progress bar to StringTrimRight($result[0], 1)
                            GUICtrlSetData($progress, StringTrimRight($result[0], 1))
                    ; Set current progress percent label to $result[0]
                        Else; Current line is a new file line
                    ; Reset progress bar to 0
                            GUICtrlSetData($progress, 0)
                    ; Reset progress percent label to "0%"
                    ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                            GUICtrlSetData($sizeLbl, $result[0])
                    ; Set current file name label to $result[1] (outputted as full filepath)
                            GUICtrlSetData($fileLbl, $result[1])
                        EndIf
                    EndIf
                EndIf
            Next
            $output = $output[$output[0]]
        EndIf
    EndIf
WEnd
; Do one more in case there's any output left in the stream after the $copyjob closes
If StdoutRead($copyjob, 0, true) > 0 Then
    $output &= StdoutRead($copyjob)
    If StringInStr($output, @CRLF) Then
        $output = StringSplit($output, @CRLF)
        For $i = 1 To $output[0]
            If  Not $switch Then
                If StringRegExp($output[$i], '\d+\s+' & StringReplace($sourcedir, "\", "\\")) Then 
                    $switch = Not $switch
                    $i += 1
                EndIf
            EndIf
            If $switch Then
                $result = StringRegExp($output[$i], '([0-9.]+%)|([0-9.]+\s*[mg]?)\s*(.*)', 1)
                If IsArray($result) Then
                    If StringInStr($result[0], "%") Then; Current line is a progress update line
                ; Set current progress bar to StringTrimRight($result[0], 1)
                        GUICtrlSetData($progress, StringTrimRight($result[0], 1))
                ; Set current progress percent label to $result[0]
                    Else; Current line is a new file line
                ; Reset progress bar to 0
                        GUICtrlSetData($progress, 0)
                ; Reset progress percent label to "0%"
                ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                        GUICtrlSetData($sizeLbl, $result[0])
                ; Set current file name label to $result[1] (outputted as full filepath)
                        GUICtrlSetData($fileLbl, $result[1])
                    EndIf
                EndIf
            EndIf
        Next
    EndIf
EndIf

Note: You'll have to try files > ~50Mb for a human to be able to read the output. ^_^

Dragging this one up a little further from the depths of time. I'm trying to use this very script with very little success. I've change the @CRLF to just @CR and @LF with no success.

If StringInStr($output, @LF) Then
            $output = StringSplit($output, @LF)

I've put in place some msgbox's to display the stdout data and I can see the data output and it looks like it's formatted correctly. However, I only get N/A from the Current file: and Current File Size:. The progress bar does not move either. Could there have been some changes to some of the built in functions between the version that this was written in and the current version?

For example, I had to change this:

StdoutRead($copyjob, 0, true)

to:

StdoutRead($copyjob, True, True)

in order to get any stdout data to display.

I've been racking my brain over this, but have yet to figure it out.

Also as a side note. People who want to use this may want to change the following lines:

$sourcedir = "c:\copytest\"
$destdir = "c:\copytest2\"

$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir, @ScriptDir, @SW_HIDE, 7)

to:

$sourcedir = '"c:\copytest\"'
$destdir = '"c:\copytest2\"'

$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe /E /NJH /NJS' & $sourcedir & ' ' & $destdir, @ScriptDir, @SW_HIDE, 8)

Use of the single quote around the double quote allows the use of spaces in the folder name for source and destdir's. Using /E /NJH /NJS makes sure that everything is copied recursively, and that you don't dirty up stdout with stuff this script does not use. I could be wrong about the script using that information, but it did not look like it.

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Hello everybody,

I'm aware that this post is rather old, but is there any news when it comes to the progressbar with robocopy?

I'm looking for a suitable solution for quite some time now, but I wasn't lucky to find one yet.

Looks a bit like flighing to the moon was easier then get robocopy up and running with a progressbar :mellow:

Any remarks/comments welcome.

Edited by Symphatico

Share this post


Link to post
Share on other sites

Probably a bit late for most of you but i have had to get a progress bar working on a Robocopy. So used this code, with several major tweaks. I had to rejig the cmd line, and the if statements werenot passing through the correct information. I've still got some more work to do on this, to tidy it up as it is just your code dumped in a function. I've also got to get a second full progress bar at the bottom for the client, which i think i will do by running a test copy first to workout the number of files and size to compare against final.

#include <GUIConstants.au3>
#include <file.au3>
Local $tempOutput
$GUI = GUICreate("Progress", 500, 200)
GUICtrlCreateLabel("Current File: ", 10, 100)
$fileLbl = GUICtrlCreateLabel("N/A", 75, 100, 400)
GUICtrlCreateLabel("Current File Size: ", 10, 125)
$sizeLbl = GUICtrlCreateLabel("N/A", 95, 125, 105)
$progress = GUICtrlCreateProgress(10, 150, 480)
$SourceBtn = GUICtrlCreateButton("...S",400, 35, 25, 25)
$DestBtn = GUICtrlCreateButton("...D",400, 65, 25, 25)
$SourceLabel = GUICtrlCreateInput("Select the Source Folder:", 10, 40, 380, 17)
$DestLabel = GUICtrlCreateInput("Select the Destination Folder:", 10, 70, 380, 17)
$GoBtn = GUICtrlCreateButton("GO", 225, 180, 25, 25)
$ExitBtn = GUICtrlCreateButton("EXIT", 275, 180, 25, 25)
GUISetState()
Local $Destination, $Source
While 1
$nMsg = GUIGetMsg()
Switch $nMsg

  Case $GUI_EVENT_CLOSE
  Case $SourceBtn
   $Source=_GetSourceDir()
   GUICtrlSetData($SourceLabel,$Source)
  Case $DestBtn
   $Destination=_GetDestinationDir()
   GUICtrlSetData($DestLabel,$Destination)
  Case $GoBtn
   _Copier($Source, $Destination)
  Case $ExitBtn
   _ExitProgram()

EndSwitch
WEnd

Func _ExitProgram()
Exit
EndFunc

Func _GetSourceDir()
$SourceDir=FileSelectFolder("Get Source", "", 2, "EditPlus 2")
Return $SourceDir
EndFunc
Func _GetDestinationDir()
$DestinationDir=FileSelectFolder("Select Destination", "", 1, "EditPlus 2")
Return '"' & $DestinationDir & '"'
Return $DestinationDir
EndFunc

Func _Copier($Source, $Destination)
msgbox(1,"Source", $Source)
msgbox(1,"Destination", $Destination)
$sourcedir=$Source
$destdir=$Destination
$copyjob = Run (@ComSpec & " /c " & 'robocopy.exe ' & $sourcedir & ' ' & $destdir & " /TEE", @ScriptDir, @SW_Hide, 2 )
$output = ""
$switch = 0; We don't want to run StringRegExp on lines that don't matter to us
While ProcessExists($copyjob)
  $tempOutput =  StdoutRead($copyjob , False , False)
If not $tempOutput = "" Then
         $output = $tempOutput
            $output = StringSplit($output, @CRLF)
            For $i = 1 To $output[0] - 1
                If  Not $switch Then
                    If StringRegExp($output[$i], '\d+\s+' & StringReplace($sourcedir, "\", "\\")) == 1 Then
                        $switch = Not $switch
                        $i += 1
                    EndIf
                EndIf
                If $switch Then
                    $result = StringRegExp($output[$i], '([0-9.]+%)|([0-9.]+\s*[mg]?)\s*(.*)', 1)
                    If IsArray($result) Then
                        If StringInStr($result[0], "%") Then; Current line is a progress update line
                        ; Set current progress bar to StringTrimRight($result[0], 1)
                            GUICtrlSetData($progress, StringTrimRight($result[0], 1))
                        ; Set current progress percent label to $result[0]
                        Else; Current line is a new file line
                        ; Reset progress bar to 0
                            GUICtrlSetData($progress, 0)
                        ; Reset progress percent label to "0%"
                        ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                            GUICtrlSetData($sizeLbl, $result[1])
                        ; Set current file name label to $result[1] (outputted as filename)
                            GUICtrlSetData($fileLbl, $result[2])
                        EndIf
                    EndIf
                EndIf
            Next
            $output = $output[$output[0]]
    EndIf
WEnd
; Do one more in case there's any output left in the stream after the $copyjob closes
If StdoutRead($copyjob, 0, true) > 0 Then
    $output &= StdoutRead($copyjob)
    If StringInStr($output, @CRLF) Then
        $output = StringSplit($output, @CRLF)
        For $i = 1 To $output[0]
            If  Not $switch Then
                If StringRegExp($output[$i], '\d+\s+' & StringReplace($sourcedir, "\", "\\")) Then
                    $switch = Not $switch
                    $i += 1
                EndIf
            EndIf
            If $switch Then
                $result = StringRegExp($output[$i], '([0-9.]+%)|([0-9.]+\s*[mg]?)\s*(.*)', 1)
                If IsArray($result) Then
                    If StringInStr($result[0], "%") Then; Current line is a progress update line
                    ; Set current progress bar to StringTrimRight($result[0], 1)
                        GUICtrlSetData($progress, StringTrimRight($result[0], 1))
                    ; Set current progress percent label to $result[0]
                    Else; Current line is a new file line
                    ; Reset progress bar to 0
                        GUICtrlSetData($progress, 0)
                    ; Reset progress percent label to "0%"
                    ; Set current file size label to $result[0] (either a number in bytes or something like (4.2 m)
                        GUICtrlSetData($sizeLbl, $result[1])
                    ; Set current file name label to $result[1] (outputted as full filepath)
                        GUICtrlSetData($fileLbl, $result[2])
                    EndIf
                EndIf
            EndIf
        Next
    EndIf
EndIf
EndFunc

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