Jump to content

RoboCopy in AutoIT %ErrorLevel% always 0 in script but ok outside


Recommended Posts

Good morning.  

I'm running into an issue where if I run the following example from a compiled script it always returns 0 in the command window.  If I run the same item outside of AUtoIT from a command prompt (both standard user and as Admin) it returns the proper error code.  Any ideas on what could be going on.  I'm not trying to pass a variable to AutoIT, I just need the proper error code returned at the command prompt.  Robocopy Version 10.0.16299.15  OS: Windows 10

- Outside of AutoIT this returns the proper error code:  

C:\windows\system32\robocopy.exe C:\Source_Files\ d:\ *.* /xf buttons2.ini /xd Local_Files /S /copy:DAT /dcopy:t /purge /fft /DST /R:1 /W:2 & Echo The Error level is %ERRORLEVEL%

- Within AutoIT script as follows always returns 0...

Global $sCommand = 'C:\windows\system32\robocopy.exe C:\Source_Files\ d:\ *.* /xf buttons2.ini /xd Local_Files /S /copy:DAT /dcopy:t /purge /fft /DST /R:1 /W:2 & Echo The Error level is %ERRORLEVEL%'
Run(@ComSpec & " /c " & $sCommand)

So what am I missing or doing wrong 😕

Edited by gonzo070777
Link to comment
Share on other sites

43 minutes ago, gonzo070777 said:

Within AutoIT the @error is always 0

It means success.  Tested the same code with different folders, works fine.  Why do you say it is not working ?  Is this the only code you run or there is other code not shown ?

Link to comment
Share on other sites

Robocopy should only report %errorlevel% of 0 when No errors occurred and no copying was done at the Command prompt

If files were copied/mismatched/deleted the %Errorlevel% should be between 1 and 7.

If there were any type of errors the %ErrorLevel% should be between 8 and 16. 

The issue is if I run the command through a pure DOS Command prompt outside of AutoIT I get the correct %errorlevel% returned in the DOS window.

If I run the same command via an AutoIT script the %ErrorLevel% in the DOS Command window that is opened by AutoIT always returns 0 even though there are files copied/deleted/mismatched and/or if an error occurs.  Unfortunately this prevents me from doing any type of error checking with Robocopy via AutoIT..

Edited by gonzo070777
Link to comment
Share on other sites

35 minutes ago, gonzo070777 said:

Robocopy should only report %errorlevel% of 0 when No errors occurred and no copying was done at the Command prompt

If files were copied/mismatched/deleted the %Errorlevel% should be between 1 and 7.

If there were any type of errors the %ErrorLevel% should be between 8 and 16. 

The issue is if I run the command through a pure DOS Command prompt outside of AutoIT I get the correct %errorlevel% returned in the DOS window.

If I run the same command via an AutoIT script the %ErrorLevel% in the DOS Command window that is opened by AutoIT always returns 0 even though there are files copied/deleted/mismatched and/or if an error occurs.  Unfortunately this prevents me from doing any type of error checking with Robocopy via AutoIT..

Ahhhh. That information would have been SO useful at the very start of this thread.  Instead of loosing my time checking @error I could have invested it for your true problem %ErrorLevel%.

Link to comment
Share on other sites

2 hours ago, Nine said:

Ahhhh. That information would have been SO useful at the very start of this thread.  Instead of loosing my time checking @error I could have invested it for your true problem %ErrorLevel%.

Sorry I tried to explain that in my first post.

Link to comment
Share on other sites

So i think I figured out the issue but don't know the workaround...  If I change the /c to /k to leave the window open and then manually type in Echo %errorlevel% it returns the proper code.  So it appears that by using the & joiner to add additional commands is the issue... the %errorlevel% will not return the proper code until you manually type in echo %errorlevel% after it completes

 

I guess this thread can be closed as this is probably a DOS limitation unless anyone has any ideas.

 

 

Edited by gonzo070777
Link to comment
Share on other sites

1 hour ago, gonzo070777 said:

I guess this thread can be closed as this is probably a DOS limitation unless anyone has any ideas.

Try this, works for me :

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

Opt ("MustDeclareVars", 1)

Opt("SendKeyDelay", 0)
Run("cmd.exe")
Local $handle = WinWait("[REGEXPTITLE:(?i)cmd.exe$]", "", 3)
ControlSend($handle, "", "", "cd \apps" & @CRLF)
ControlSend($handle, "", "", "robocopy C:\Apps\Mirc c:\Apps\Temp *.* /xf buttons2.ini /xd Local_Files /S /copy:DAT /dcopy:t /purge /fft /DST /R:1 /W:2" & @CRLF)
ControlSend($handle, "", "", "Echo The Error level is %ERRORLEVEL%" & @CRLF)
Sleep(5000) ; delay to check output. Delete line to continue without delay
ControlSend($handle, "", "", "cls" & @CRLF)
Sleep(2000)
ControlSend($handle, "", "", "exit" & @CRLF)

 

Link to comment
Share on other sites

Hi all,
I tried what follows and all exitcodes match, no matter I run the script from AutoIt, using Runwait() or _RunDos(), or if I launch a cmd file directly from the command prompt :

#include <Process.au3> ; for _RunDos()

; Global $iErrorLevel =_RunDos("C:\test\robocopy.exe C:\folder1 C:\folder2")
Global $iErrorLevel = RunWait(@ComSpec & " /k " & "C:\test\robocop.cmd")

MsgBox(0,"", "Exit code: " & $iErrorLevel & @CRLF & "@error: " & @error)

Here is the content of robocop.cmd

C:\test\robocopy.exe C:\folder1 C:\folder2
if %ERRORLEVEL% EQU 16 echo ***FATAL ERROR*** & goto end
if %ERRORLEVEL% EQU 15 echo OKCOPY + FAIL + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 14 echo FAIL + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 13 echo OKCOPY + FAIL + MISMATCHES & goto end
if %ERRORLEVEL% EQU 12 echo FAIL + MISMATCHES& goto end
if %ERRORLEVEL% EQU 11 echo OKCOPY + FAIL + XTRA & goto end
if %ERRORLEVEL% EQU 10 echo FAIL + XTRA & goto end
if %ERRORLEVEL% EQU 9 echo OKCOPY + FAIL & goto end
if %ERRORLEVEL% EQU 8 echo FAIL & goto end
if %ERRORLEVEL% EQU 7 echo OKCOPY + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 6 echo MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 5 echo OKCOPY + MISMATCHES & goto end
if %ERRORLEVEL% EQU 4 echo MISMATCHES & goto end
if %ERRORLEVEL% EQU 3 echo OKCOPY + XTRA & goto end
if %ERRORLEVEL% EQU 2 echo XTRA & goto end
if %ERRORLEVEL% EQU 1 echo OKCOPY & goto end
if %ERRORLEVEL% EQU 0 echo No Change & goto end
:end

When C:\Folder1 and C:\Folder2 don't exist on HD, exitcode is 16 *** Fatal Error***  (it will display 16 in Msgbox and in the Dos command window)

If C:\Folder1 and C:\Folder2 both exist, and there are new files in C:\Folder1, then exitcode will display 1 (okcopy), no matter you use the script in Autoit or the cmd file directly in dos command window.

Then if you run the script again, an errorlevel 0 will be displayed everywhere, meaning no change) etc...

Link to comment
Share on other sites

Thank you to all for the tips and suggestions.  I experimented with both proposed solutions and had forgotten about the cmd file route. 

The send option worked perfectly but it prevented easy concurrent data copies plus it was slow to type everything and not as transparent to the user.

I've been able to combine the cmd suggestion with my lengthy '&' command and found that i can still use my whole string except when I want to check the robocopy %errorlevel% I just have to do that tiny portion via the CMD line and it reports correctly so far.

CMD file contents:  ** added an edit so you can see which drive failed the cmd portion  %~d0 will tell you the drive letter of the error or success

Echo %ERRORLEVEL% 
If %ERRORLEVEL% GTR 7 Echo There was an error in the data copy for drive %~d0 & Echo. & Echo Please investigate further! & Echo. & Pause
If %ERRORLEVEL% LSS 8 Echo There were NO errors in the data copy for drive %~d0 & Echo. & Echo Enjoy using ...

So for future reference this works in case anyone else runs into the issue:  

Global $sCommand = 'C:\windows\system32\robocopy.exe C:\Source_Files\ d:\ *.* /xf buttons2.ini /xd Local_Files /S /copy:DAT /dcopy:t /purge /fft /DST /R:1 /W:2 & c:\temp\RoboERR.cmd & Echo Continue with any other operations as normal & Echo .... ' 
;So the error level will only report correctly with anything you put in the cmd file, once the cmd file is done the %ErrorLevel% will report as zero again with anything in the following & functions after the cmd file
Run(@ComSpec & " /c " & $sCommand) 
;I can't use runwait because I can have 7-10 robocopies running concurrently udating different USB sticks so any error checking needs to be done at the Command level

 

Edited by gonzo070777
Link to comment
Share on other sites

Run robocopy directly, and not through @ComSpec.  You should then get the correct exit code.  A few examples below.  

Using ProcessWaitClose

Global $sCommand = 'C:\windows\system32\robocopy.exe C:\Source_Files\ d:\ *.* /xf buttons2.ini /xd Local_Files /S /copy:DAT /dcopy:t /purge /fft /DST /R:1 /W:2'
Global $iRobocopyPID = Run($sCommand, "", @SW_HIDE)
If Not $iRobocopyPID Then Exit

ProcessWaitClose($iRobocopyPID)
Global $iExitCode = @extended
ConsoleWrite("Exit Code: " & $iExitCode & @CRLF)

Using _WinAPI_GetExitCodeProcess Example in the help file.  

#include <ProcessConstants.au3>
#include <WinAPIHObj.au3>
#include <WinAPIProc.au3>
#include <WinAPISys.au3>

Global $sCommand = 'C:\windows\system32\robocopy.exe C:\Source_Files\ d:\ *.* /xf buttons2.ini /xd Local_Files /S /copy:DAT /dcopy:t /purge /fft /DST /R:1 /W:2'
Global $iPID = Run($sCommand, "", @SW_HIDE)
If Not $iPID Then
    Exit
EndIf

Global $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $iPID)
If Not $hProcess Then
    Exit
EndIf

;Loop for process until closed.  
While ProcessExists($iPID)
    Sleep(10)
WEnd

ConsoleWrite('Exit code: ' & _WinAPI_GetExitCodeProcess($hProcess) & @CRLF)

_WinAPI_CloseHandle($hProcess)

For what you are needing I would do an array of PIDs and handles using the _WinAPI_GetExitCodeProcess example.  

 

Adam

 

Link to comment
Share on other sites

Hi,

 

As @AdamUL already stated, don't wrap Robocopy with comspec or anything else.

 

$Src="C:\some\Folder1"
$Dst="X:\destination\Folder2"

$result=RunWait(@SystemDir & '\robocopy.exe "' & $Src & '" "' & $dst & '" /mir /w:0 /r:0 /reg /tee',@SystemDir,@SW_SHOW)

MsgBox(0, '', $result)

Additional note: Not all versions of Robocopy.exe do provide EXITCODES. IIRC that one included in RobocopyGUI and some versions of older Windows Versions don't set the appropriate EXITCODE (Win7 without SP1, Vista, ...?)

That one coming with WindowsXP definitely provides exit codes, everthing 7 and below is informational, all 8 and above are indicating errors.

 

Rudi.

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...