Thursday, February 3, 2011

Best way to wrap rsync progress in a gui?

I use rsync to synchronize files to Windows clients in a server agnostic way. What methods are available to send the progress of rsync to the parent process for display in a gui progress bar?

I imagine two or three choices exist. (1) Watch STDOUT (2) Watch rsync.exe log file, similar to unix tail (3) Watch rsync console output in memory.

Which one is best/preferred?

  • .NET has a pretty straight forward way to read and watch STDOUT.
    I guess this would be the cleanest way, since it is not dependent on any external files, just the path to rsync. I would not be too surprised if there is a wrapper library out there either. If not, write and open source it :)

  • Check out I think it is called DeltaCopy. It is a windows gui for rsync (i believe)

    Looked it up. DeltaCopy http://www.download.com/DeltaCopy/3000-2242_4-10471616.html

  • For this type of tasks, I use my own AutoIt script (freeware, Windows only). The script redirects the standard output into a graphical window, displaying it with the ability to scroll back, etc (very useful in long processes like XCOPYs / PKZIPs to check if any error did happen).

    I use AutoIt because it's free, very easy to use, and can compile quickly into an .EXE. I think it's an excellent alternative to a complete programming language for this type of tasks. The downside is that it's for Windows only.

    $sCmd = "DIR E:\*.AU3 /S"  ; Test command
    $nAutoTimeout = 10      ; Time in seconds to close window after finish
    
    $nDeskPct = 60          ; % of desktop size (if percent)
    
    ; $nHeight = 480          ; height/width of the main window (if fixed)
    ; $nWidth = 480
    
    $sTitRun = "Executing process. Wait...."     ; 
    $sTitDone = "Process done"                ; 
    
    $sSound = @WindowsDir & "\Media\Ding.wav"       ; End Sound
    
    $sButRun = "Cancel"                           ; Caption of "Exec" button
    $sButDone = "Close"                            ; Caption of "Close" button
    
    #include <GUIConstants.au3>
    #include <Constants.au3>
    #Include <GuiList.au3>
    
    Opt("GUIOnEventMode", 1)
    
    if $nDeskPct > 0 Then
        $nHeight = @DesktopHeight * ($nDeskPct / 100)
        $nWidth = @DesktopWidth * ($nDeskPct / 100)
    EndIf
    
    
    If $CmdLine[0] > 0 Then
        $sCmd = ""
        For $nCmd = 1 To $CmdLine[0]
            $sCmd = $sCmd & " " & $CmdLine[$nCmd]
        Next
    
        ; MsgBox (1,"",$sCmd)
    EndIf
    
    ; AutoItSetOption("GUIDataSeparatorChar", Chr(13)+Chr(10))
    
    $nForm = GUICreate($sTitRun, $nWidth, $nHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "CloseForm")
    
    $nList = GUICtrlCreateList ("", 10, 10, $nWidth - 20, $nHeight - 50, $WS_BORDER + $WS_VSCROLL)
    GUICtrlSetFont (-1, 9, 0, 0, "Courier New")
    
    $nClose = GUICtrlCreateButton ($sButRun, $nWidth - 100, $nHeight - 40, 80, 30)
    GUICtrlSetOnEvent (-1, "CloseForm")
    
    GUISetState(@SW_SHOW)   ;, $nForm)
    
    $nPID = Run(@ComSpec & " /C " & $sCmd, ".", @SW_HIDE, $STDOUT_CHILD)
    ; $nPID = Run(@ComSpec & " /C _RunErrl.bat " & $sCmd, ".", @SW_HIDE, $STDOUT_CHILD)     ; # Con ésto devuelve el errorlevel en _ERRL.TMP
    
    While 1
        $sLine = StdoutRead($nPID)
        If @error Then ExitLoop
    
        If StringLen ($sLine) > 0 then
            $sLine = StringReplace ($sLine, Chr(13), "|")
            $sLine = StringReplace ($sLine, Chr(10), "")
            if StringLeft($sLine, 1)="|" Then
                $sLine = " " & $sLine
            endif
    
            GUICtrlSetData ($nList, $sLine)
    
            _GUICtrlListSelectIndex ($nList, _GUICtrlListCount ($nList) - 1)
        EndIf
    Wend
    
    $sLine = " ||"
    GUICtrlSetData ($nList, $sLine)
    _GUICtrlListSelectIndex ($nList, _GUICtrlListCount ($nList) - 1)
    
    GUICtrlSetData ($nClose, $sButDone)
    
    WinSetTitle ($sTitRun, "", $sTitDone)
    If $sSound <> "" Then
        SoundPlay ($sSound)
    EndIf
    
    $rInfo = DllStructCreate("uint;dword")      ; # LASTINPUTINFO
    DllStructSetData($rInfo, 1, DllStructGetSize($rInfo));
    
    DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($rInfo))
    $nLastInput = DllStructGetData($rInfo, 2)
    
    $nTime = TimerInit()
    
    While 1
        If $nAutoTimeout > 0 Then
            DllCall("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr($rInfo))
            If DllStructGetData($rInfo, 2) <> $nLastInput Then
                ; Tocó una tecla
                $nAutoTimeout = 0
            EndIf
        EndIf
    
        If $nAutoTimeout > 0 And TimerDiff ($nTime) > $nAutoTimeOut * 1000 Then
            ExitLoop
        EndIf
    
        Sleep (100)
    Wend
    
    
    Func CloseForm()
        Exit
    EndFunc
    
    From PabloG
  • Hello:

    I've built my own simple object for this, i get alot or reuse out of it, i can wrap it with a cmdline, web page, webserice, write output to a file, etc---

    the commented items contain some rsync examples--

    what i'd like to do sometime is embed rsync (and cygwin) into a resource & make a single .net executable out of it--

    Here you go:

    Imports System.IO

    Namespace cds

    Public Class proc
    
        Public _cmdString As String
        Public _workingDir As String
        Public _arg As String
    
    
        Public Function basic() As String
    
            Dim sOut As String = ""
    
            Try
                'Set start information.
                'Dim startinfo As New ProcessStartInfo("C:\Program Files\cwRsync\bin\rsync", "-avzrbP 192.168.42.6::cdsERP /cygdrive/s/cdsERP_rsync/gwy")
                'Dim startinfo As New ProcessStartInfo("C:\Program Files\cwRsync\bin\rsync", "-avzrbP 10.1.1.6::user /cygdrive/s/cdsERP_rsync/gws/user")
                'Dim startinfo As New ProcessStartInfo("C:\windows\system32\cscript", "//NoLogo c:\windows\system32\prnmngr.vbs -l")
    
                Dim si As New ProcessStartInfo(_cmdString, _arg)
    
                si.UseShellExecute = False
                si.CreateNoWindow = True
                si.RedirectStandardOutput = True
                si.RedirectStandardError = True
    
                si.WorkingDirectory = _workingDir
    
    
                ' Make the process and set its start information.
                Dim p As New Process()
                p.StartInfo = si
    
                ' Start the process.
                p.Start()
    
                ' Attach to stdout and stderr.
                Dim stdout As StreamReader = p.StandardOutput()
                Dim stderr As StreamReader = p.StandardError()
    
                sOut = stdout.ReadToEnd() & ControlChars.NewLine & stderr.ReadToEnd()
    
                'Dim writer As New StreamWriter("out.txt", FileMode.CreateNew)
                'writer.Write(sOut)
                'writer.Close()
    
                stdout.Close()
                stderr.Close()
                p.Close()
    
    
            Catch ex As Exception
    
                sOut = ex.Message
    
            End Try
    
            Return sOut
    
        End Function
    
    End Class
    

    End Namespace

  • Check NAsBackup http://www.nasbackup.com Its open source software that give Windows user Rsync GUI using Watch STDOUT.

0 comments:

Post a Comment