关于windows:在gui中包装rsync进度的最佳方法?

关于windows:在gui中包装rsync进度的最佳方法?

Best way to wrap rsync progress in a gui?

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

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

哪一个最好/首选?


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
$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

我为此构建了自己的简单对象,我从中获得了大量的重用,我可以用cmdlineweb pagewebservice包装它,将输出写入文件等等---

评论的项目包含一些rsync示例 -

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

干得好:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
sync","-avzrbP 192.168.42.6::cdsERP /cygdrive/s/cdsERP_rsync/gwy")
            'Dim startinfo As New ProcessStartInfo("C:\Program Files\cwRsync\bin
sync","-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


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


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


查看DeltaCopy。它是rsync的Windows GUI。


推荐阅读