hzxymkb 发表于 2011-6-25 23:41:25

robocopy UDF 问题

本帖最后由 hzxymkb 于 2011-6-25 23:52 编辑

这个UDF是从官网找到的,运行不了!请高手帮一下!#include <Constants.au3> ; STDIN & STDOUT
;Global Const $STDIN_CHILD            = 1
;Global Const $STDOUT_CHILD             = 2
;Global Const $STDERR_CHILD             = 4
;Global Const $STDERR_MERGED            = 8
;Global Const $STDIO_INHERIT_PARENT   = 0x10
;Global Const $RUN_CREATE_NEW_CONSOLE   = 0x00010000
;===============================================================================
;
; Function Name:    _robocopy($source, $target, $stitches = "mirror", $excludeFiles = "", $excludeFolders = "", $logFile = "", $statusBox = "", $progressBar = "")
; Description::   Runs the Robocopy command
; Parameter(s):   $source   -   Source directory
;                   $target   -   Target Directory
;                   $stitches   -   Standard Robocopy switches, predefined meta commands or combination of both
;                               -   "Meta" or "Std Switches" or (eg mirror /r:0 /w:0)
;                               -   Mirror - Clone source to target (includeing subdirectories)
;                               -   Add - Add new/updates files but don't delete anything
;                               -   Copy - Same as Add
;                               -   CopySub - Same as add but also copies all subdirectories
;                               -   Move - Move files to destination
;                               -   MoveSub - Same as move but also copies all subdirectories
;                   $includeFiles   -   A list of files to include (Comma delimited)
;                                 -   OR An array of files
;                   $excludeFiles   -   A list of files to exclude (Comma delimited)
;                                 -   OR An array of files
;                   $excludeFolders -   A list of folders to exclude (Comma delimited)
;                                 -   OR An array of files
;                   $logFile      -   Filename for log file
;                                       If File starts with + then append to log
;                   $outputFunction -   Function name to pass text to from robocopy
;                                 -   Only full lines will be passed to this function
;                                 -   This will be run by execute command in the form {Function name}($text)
; Requirement(s):Robocopy is installed on the computer or in the same directoy as script
; Return Value(s): Success: ???
;                   Error: 0 and @error =
;                   = 1 - Robocopy.exe can't be found
;                   = 2 - Source doesn't Exist
;                   = 3 - Destination can't be created (eg maybe read only media)
;                   = 4 - Log File can't be created
;                   = 5 - Robocopy Cant' be run
; Author(s):       John Morrison
;
; Basis:
; Thanks:   PsaltyDS http://www.autoitscript.com/forum/index....p?showtopic=98602&view=findpos _ProcessGetExitCode()
;===============================================================================
Func _robocopy($source, $target, $switches = "mirror", $includeFiles = "", $excludeFiles = "", $excludeFolders = "", $logFile = "", $outputFunction = "")
    #cs
    ConsoleWrite("All Switches" & @CR & _
            "$source = <" & $source & ">" & @CR & _
            "$target = <" & $target & ">" & @CR & _
            "$switches = <" & $switches & ">" & @CR & _
            "$includeFiles = <" & $includeFiles & ">" & @CR & _
            "$excludeFolders = <" & $excludeFolders & ">" & @CR & _
            "$logFile = <" & $logFile & ">" & @CR & _
            "$outputFunction = <" & $outputFunction & ">" & @CR)
    #ce

    ; Check if Robocopy can be executed
    Local $roboCopyCMD = ""
    While $roboCopyCMD = ""
      If FileExists(@SystemDir & "\robocopy.exe") Then
            $roboCopyCMD = @SystemDir & "\robocopy.exe "
      ElseIf FileExists(@ScriptDir & "\robocopy.exe") Then
            $roboCopyCMD = @ScriptDir & "\robocopy.exe "
      ElseIf FileExists(@ScriptDir & "\getrobocopy.exe") Then
            ;Download Robocopy
            If RunWait(@ScriptDir & "\getrobocopy.exe", @TempDir) <> 0 Then
                Return SetError(1, "", 0) ; Can't find Robocopy
            EndIf
      Else
            Return SetError(1, "", 0) ; Can't find Robocopy
      EndIf
    WEnd

    $workingdir = $source
    ; Check source exists
    If StringRight($source, 1) = "\" Then
      ; remove trailing slash \
      $source = StringLeft($source, StringLen($source) - 1)
    EndIf
    If Not FileExists($source) Then
      ; source doesn't exist
      Return SetError(2, "", 0) ; Source doesn't Exist
    EndIf
    $source = _RCProcessFilelist($source)

    ; Check Target reachable
    If StringRight($target, 1) = "\" Then
      ; remove trailing slash \
      $target = StringLeft($target, StringLen($target) - 1)
    EndIf
    If Not FileExists($target) Then
      If Not DirCreate($target) Then
            Return SetError(3, "", 0) ; Destination can't be created (eg maybe read only media)
      EndIf
    EndIf
    $target = _RCProcessFilelist($target)

    ;Workout Robocopy switches from Meta
    While 1
      ;Loop until all metas are removed
      Select
            ;Case _RCcheckMeta("sub", "/E", $switches)
            Case _RCcheckMeta("mirror", "/MIR ", $switches)
            Case _RCcheckMeta("Add", "", $switches)
            Case _RCcheckMeta("Copy", "", $switches)
            Case _RCcheckMeta("CopySub", "/E", $switches)
            Case _RCcheckMeta("Move", "/MOVE", $switches)
            Case _RCcheckMeta("MoveSub", "/MOVE /E", $switches)
            Case Else
                ;MsgBox(0, "pause", "META EKSE")
                ExitLoop
      EndSelect
      ;MsgBox(0, "pause", "META")
    WEnd

    ;Include files
    If $includeFiles = "" Then $includeFiles = "*.*"
    $switches = _RCProcessFilelist($includeFiles) & " " & StringStripWS($switches, 1)

    ;Exclude files/folders
    If $excludeFiles <> "" Then
      $switches &= " /XF " & _RCProcessFilelist($excludeFiles)
    EndIf
    If $excludeFolders <> "" Then
      ; Add target to 'excluded files' in case tragete is inside source (eg source=c: target=c:\backup)
      $switches &= " /XD " & _RCProcessFilelist($excludeFolders) & " " & _RCProcessFilelist($target)
    EndIf

    ; LOG
    If $logFile <> "" Then
      If StringLeft($logFile, 1) = "+" Then
            $logFile = StringMid($logFile, 2, 255)
            $switches &= ' /log+:"' & $logFile & '"'
      Else
            $switches &= ' /log:"' & $logFile & '"'
      EndIf

      $hfile = FileOpen($logFile, 1)
      If $hfile = -1 Then
            Return SetError(4, "", 0) ;Can't append/create Log file error
      EndIf
      FileClose($hfile)
    EndIf

    ;Add extra switches if nessacary
    If Not StringInStr($switches, "/r:") Then
      ; retry count
      $switches &= " /r:0"
    EndIf
    If Not StringInStr($switches, "/w:") Then
      ; Wait time
      $switches &= " /w:0"
    EndIf
    If Not StringInStr($switches, "/ZB") Then
      ; Tries to copy files in restartable mode, but if that fails with an “Access Denied” error, switches automatically to Backup mode.
      ;TODO - MAY drop this out as slows copy ???
      $switches &= " /ZB"
    EndIf
    If Not StringInStr($switches, "/FFT") Then
      ; Assume FAT File Times (2-second granularity). Useful for copying to third-party systems that declare a volume to be NTFS but only implement file times with a 2-second granularity..
      $switches &= " /FFT"
    EndIf
    If Not StringInStr($switches, "/COPY:") Then
      ; Copies Data, Attributes, Timestamps only (SEE
      $switches &= " /COPY:DAT"
    EndIf
    ; Wasn't as useful as it looked-removed
    ;If Not StringInStr($switches, "/ETA") Then
    ;   ; Shows estimated time of completion for copied files.
    ;   $switches &= " /ETA"
    ;EndIf
    If StringInStr($switches, "/log") Then
      ; Displays output in the console window, in addition to directing it to the log file specified by /LOG or /LOG+.
      ; Needed for status and progress displays
      $switches &= " /TEE"
    EndIf
    ; DEGUB TODO - remove commenting after testing
    ;If $progressBar = "" Then
    ;   ; no progress bar so "suppress the display of progress information"
    ;   $switches &= " /NP "
    ;EndIf

#cs
    MsgBox(0, "ROBOCOPY", _
            "$source = <" & $source & ">" & @CR & _
            "$target = <" & $target & ">" & @CR & _
            "$switches = <" & $switches & ">" & @CR & _
            "$roboCopyCMD = <" & $roboCopyCMD & " " & $source & " " & $target & " " & $switches & ">" & @CR & _
            "")
            #ce
    ConsoleWrite($roboCopyCMD & " " & $source & " " & $target & " " & $switches & @CR)

    ;Exit

    ; run robocopy
    Local $robocopyPID = Run('"' & $roboCopyCMD & '" ' & $source & " " & $target & " " & $switches, $workingdir, @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
    If $robocopyPID = 0 Then
      Return SetError(5, "", 0) ; Robocopy failed to run
    Else
      Local $hrobocopy = _ProcessGetHandle($robocopyPID)
      ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hrobocopy = ' & $hrobocopy & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
      If @error Then MsgBox(0,"Error _ProcessGetHandle", "@error = " & @error)

      Local $cmdOut, $cmdoutlast, $buffer, $loopCount, $buffer2, $sPosit
      ;Local $cmdOutErr = 1 ; so loop is run at least once
      While 1 ; ProcessExists($robocopyPID); Or ($cmdOutErr = 0) ; $cmdOurErr - used to wait untill ALL data is extracted from command line

            $cmdOut = StdoutRead($robocopyPID)
            ;$cmdOutErr = @error
            If @error Then ExitLoop

            If $cmdOut <> $cmdoutlast Then
                $cmdoutlast = $cmdOut
                $fnewdata = True
                $buffer &= $cmdOut ; Stores all data for processing

                ;interpret $BUFFER data
                ;extract and send to $statusFunc() the buffer string up to and including the last @CRLF
                $posit = StringInStr($buffer, @CRLF, 0, -1) + 2
                If Not @error Then
                  $buffer2 = StringStripWS(StringLeft($buffer, $posit), 2)
                  If $buffer2 <> "" Then
                        ;ConsoleWrite($posit & "|" & StringLen($buffer) & "<<" & $buffer2 & ">>" & Asc(StringMid($buffer, $posit, 1)) & "|" & $buffer & "|" & @CR)
                        Execute($outputFunction & '("' & $buffer2 & '")')
                  EndIf
                  $buffer = StringMid($buffer, $posit, 1000)
                  ;ConsoleWrite("<<<" & StringMid($buffer, $posit, 1000) & ">>>" & @CR)

                EndIf
            EndIf ; $cmdOut
            ;endif ; $outputFunction

            Sleep(20)
      WEnd

      Local $iReturnCode = _ProcessGetExitCode($hrobocopy)
      ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iReturnCode = ' & $iReturnCode & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
      If @error Then MsgBox(0,"Error _ProcessGetExitCode", "@error = " & @error)
      #cs
            BITMAP
            Value   Meaning If Set
            16Serious error. Robocopy did not copy any files. This is either a usage error or an error due to insufficient access privileges on the source or destination directories.
            8   Some files or directories could not be copied (copy errors occurred and the retry limit was exceeded). Check these errors further.
            4   Some Mismatched files or directories were detected. Examine the output log. Housekeeping is probably necessary.
            2   Some Extra files or directories were detected. Examine the output log. Some housekeeping may be needed.
            1   One or more files were copied successfully (that is, new files have arrived).
            0   No errors occurred, and no copying was done. The source and destination directory trees are completely synchronized.
      #ce
      _ProcessCloseHandle($hrobocopy)
      If @error Then MsgBox(0,"Error _ProcessCloseHandle", "@error = " & @error)

      Return $iReturnCode
    EndIf

EndFunc   ;==>_robocopy

Func _RCcheckMeta($meta, $metaSwitch, ByRef $switches)
    ;check if meta is the first part of $switches or whole of switches
    ; if so replace with Robocopy switches for that meta
    $meta = StringLower($meta)
    If StringInStr($switches, $meta & " ") = 1 Or StringLower($switches) = $meta Then
      $switches = StringStripWS(StringStripWS($metaSwitch & " " & StringStripWS(StringMid($switches, StringLen($meta) + 1, 100), 1), 1), 2)
      Return True
    Else
      Return False
    EndIf
EndFunc   ;==>_RCcheckMeta

Func _RCProcessFilelist($fileList)
    ; $includeFiles = either a comma delimited string or Array of strings
    Local $sReturn = ""

    If Not IsArray($fileList) Then
      ;Standard string so convert to array
      $fileList = StringSplit($fileList, ",", 2)
    EndIf

    For $item = 0 To UBound($fileList) - 1
      $fileList[$item] = StringStripWS(StringStripWS($fileList[$item], 1), 2)
      If StringLeft($fileList[$item], 1) <> '"' Then ;Search for inverted commas as first character
            $fileList[$item] = '"' & $fileList[$item]
      EndIf
      If StringRight($fileList[$item], 1) <> '"' Then ;Search for inverted commas as first character
            $fileList[$item] &= '"'
      EndIf
      $sReturn &= " " & $fileList[$item]
    Next
    Return StringStripWS($sReturn, 1) ; Strip leading space
EndFunc   ;==>_RCProcessFilelist

; Return handle of given PID
Func _ProcessGetHandle($iPID)
    Local Const $PROCESS_QUERY_INFORMATION = 0x0400
    Local $avRET = DllCall("kernel32.dll", "ptr", "OpenProcess", "int", $PROCESS_QUERY_INFORMATION, "int", 0, "int", $iPID)
    If @error Then
      Return SetError(1, 0, 0)
    Else
      Return $avRET
    EndIf
EndFunc   ;==>_ProcessGetHandle

; Close process handle
Func _ProcessCloseHandle($hProc)
    Local $avRET = DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProc)
    If @error Then
      Return SetError(1, 0, 0)
    Else
      Return 1
    EndIf
EndFunc   ;==>_ProcessCloseHandle

; Get process exit code from handle
Func _ProcessGetExitCode($hProc)
    Local $t_ExitCode = DllStructCreate("int")
    Local $avRET = DllCall("kernel32.dll", "int", "GetExitCodeProcess", "ptr", $hProc, "ptr", DllStructGetPtr($t_ExitCode))
    If @error Then
      Return SetError(1, 0, 0)
    Else
      Return DllStructGetData($t_ExitCode, 1)
    EndIf
EndFunc   ;==>_ProcessGetExitCode

这段代码运行出错,可能是我不会使用,求高手哥指点一下小弟!


 这个是代码运行所需要的XP下的文件!

官网地址:http://www.autoitscript.com/forum/topic/121576-robocopy-function/page__p__890595__hl__robocopy__fromsearch__1#entry890595

yangjh 发表于 2011-6-25 23:45:41

我是菜鸟帮顶!!等高手来解答,p神,a神等等的大神快来啊!!!顶起

sdc7 发表于 2011-6-25 23:49:50

干你,,还又这加分一说! 1024

olala 发表于 2011-6-25 23:50:53

路过,实在看不懂,只能帮顶贴了,

sdc7 发表于 2011-6-26 00:34:56

Function Name:    _robocopy($source, $target, $stitches = "mirror", $excludeFiles = "", $excludeFolders = "", $logFile = "", $statusBox = "", $progressBar = "")
; Description::   Runs the Robocopy command
; Parameter(s):   $source   -   Source directory
;                   $target   -   Target Directory
;                   $stitches   -   Standard Robocopy switches, predefined meta commands or combination of both
;                               -   "Meta" or "Std Switches" or (eg mirror /r:0 /w:0)
;                               -   Mirror - Clone source to target (includeing subdirectories)克隆源到目标(includeing子目录)
;                               -   Add - Add new/updates files but don't delete anything添加 - 添加新/更新文件,但不删除任何

;                               -   Copy - Same as Add 复制 - 相同
;                               -   CopySub - Same as add but also copies all subdirectories 添加相同,但也将所有子目录
;                               -   Move - Move files to destination 移动文件到目的地
;                               -   MoveSub - Same as move but also copies all subdirectories
;                   $includeFiles   -   A list of files to include (Comma delimited)文件清单
;                                 -   OR An array of files
;                   $excludeFiles   -   A list of files to exclude (Comma delimited)排除文件

;                                 -   OR An array of files
;                   $excludeFolders -   A list of folders to exclude (Comma delimited)排除目录
;                                 -   OR An array of files
;                   $logFile      -   Filename for log file 文件日志
;                                       If File starts with + then append to log
;                   $outputFunction -   Function name to pass text to from robocopy
;                                 -   Only full lines will be passed to this function
;                                 -   This will be run by execute command in the form {Function name}($text)

happytc 发表于 2011-6-26 06:37:47

回复 1# hzxymkb


    试了下,可以用呀,直接用就可以了

#include "_robocopy.au3"
_robocopy("f:\PicPick", "d:\picpick", "/MIR /r:0 /w:0 /ZB /FFT /COPY:DAT")

happytc 发表于 2011-6-26 06:41:53

不过,写这个已经没有多大意思,微软已经把这个搞成有gui窗口的了。并且Win7下的还是多线程的

魔帝 发表于 2011-6-26 09:59:13

{:face (411):}大哥,我是来顶贴的

menfan1 发表于 2011-7-2 15:54:31

我这边也是可以用的哦。

joyue9 发表于 2011-7-2 16:46:01

顶下顶下顶下
页: [1]
查看完整版本: robocopy UDF 问题