#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 [meta][Space][Std switches] (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
16 Serious 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[0]
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
这段代码运行出错,可能是我不会使用,求高手哥指点一下小弟!