【问题标题】:Best way to wrap rsync progress in a gui?将 rsync 进度包装在 gui 中的最佳方法?
【发布时间】:2010-09-05 16:47:08
【问题描述】:

我使用rsync 以与服务器无关的方式将文件同步到 Windows 客户端。有哪些方法可以将 rsync 的进度发送到父进程以显示在 gui 进度条中?

我想存在两三个选择。 (1) 观察 STDOUT (2) 观察 rsync.exe 日志文件,类似于 unix tail (3) 观察内存中的 rsync 控制台输出。

哪一个最好/首选?

【问题讨论】:

    标签: windows user-interface rsync


    【解决方案1】:

    对于此类任务,我使用自己的AutoIt 脚本(免费软件,仅限Windows)。该脚本将标准输出重定向到一个图形窗口,显示它并具有向后滚动的能力等(在 XCOPYs / PKZIPs 等长流程中非常有用,可以检查是否确实发生了任何错误)。

    我使用 AutoIt 是因为它是免费的,非常易于使用,并且可以快速编译成 .EXE。我认为它是完成此类任务的完整编程语言的绝佳替代品。缺点是它仅适用于 Windows。

    $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
    

    【讨论】:

      【解决方案2】:

      .NET 有一种非常直接的方式来阅读和观看 STDOUT。
      我想这将是最干净的方式,因为它不依赖于任何外部文件,只依赖于 rsync 的路径。如果那里有一个包装库,我也不会太惊讶。如果没有,请编写并开源它:)

      【讨论】:

        【解决方案3】:

        我为此构建了自己的简单对象,我从中得到了很多重用,我可以用cmdline、web page、webservice 包装它,将输出写入文件等- --

        评论项包含一些rsync的例子--

        我有时想做的是将rsync(和cygwin)嵌入到资源中并从中生成单个.net 可执行文件--

        给你:

        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
        

        【讨论】:

          【解决方案4】:

          查看DeltaCopy。它是一个用于 rsync 的 Windows GUI。

          【讨论】:

            【解决方案5】:

            查看NAsBackup 它的开源软件,它为 Windows 用户提供使用 Watch STDOUT 的 Rsync GUI。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-09-18
              • 2022-01-05
              • 1970-01-01
              • 2016-08-18
              • 2018-03-02
              相关资源
              最近更新 更多