3

In this batch script I'm testing the errorlevel return of expected 1, but its echoing 0.

If there is no file to copy, folder is empty, why would it return 0 for success?

I'm going by the following xcopy errorlevels:

XCOPY should return the following exit codes:

  • 0 Files were copied without error.
  • 1 No files were found to copy.
  • 2 The user pressed CTRL+C to terminate xcopy.
  • 4 Initialization error occurred. There is not enough memory or disk space, or you entered an invalid drive name or invalid syntax on the command line.
  • 5 Disk write error occurred.

Here is my batch script:

@ECHO ON
SET ERRORS=0

REM Backup file first and report any errors if unsuccessful
xcopy /Y "C:\channels\filetransfer_process\*" "C:\channels\backup\"
echo %ERRORLEVEL%
REM Error Checking
REM Note The environmental variable ERRORLEVEL contains the return code of 
the last executed program or script.
if errorlevel 2 (
    SET BODY="not enough memory or disk space"
    GOTO :mailerror

)
if errorlevel 1 (
    SET BODY="No files were found to copy"
    GOTO :mailerror
)

if errorlevel 5 (
    SET BODY="Disk write error occurred"
    GOTO :mailerror
)
if NOT ["%errorlevel%"]==["0"] pause

REM Before doing the network connection make sure Z drive is free for use
if exist z:\ (  net use z: /delete )


REM proceed with a network connection using Z with error checking
net use Z: \\dcqwdbs034\D$\arrivals /user:sutter-chs\lawson Sutter1
if errorlevel 0 (
   goto :move
) else (
   SET BODY="net use connection failed"
   goto :mailerror
)

REM move file to MSCM server
:move
move /Y "C:\channels\filetransfer_process\*" "Z:\"
if errorlevel 1 (
    SET BODY="File not found, could not be moved/renamed or bad parameters"
    goto :mailerror
)

REM remove network mapped Z drive
net use z: /delete

REM perform the error notification via BLAT
:mailerror
"D:\Program Files\BLAT\blat.exe" -Install -Server mail1.sutterhealth.org -f 
 name@domain.org -u name@domain.org -Pw mypasswd
"D:\Program Files\BLAT\blat.exe" -To name@domain.org.org -Subject "File 
Transfer Error" -Body %BODY%
:EOF
Squashman
  • 13,649
  • 5
  • 27
  • 36
Configueroa
  • 315
  • 4
  • 14
  • 2
    As far as I know, [there is not any way](https://superuser.com/q/1180180/362853) for `xcopy` to return an `errorlevel 1` – MC ND Apr 09 '18 at 17:27
  • Given that `XCopy` was superseded by `RoboCopy` more years ago than I can now remember, you could try using that instead. See [this](https://ss64.com/nt/robocopy-exit.html) for more information, in conjunction with the command's usage information `RoboCopy /?` – Compo Apr 09 '18 at 23:03

1 Answers1

2

Here is the batch file rewritten to handle all error conditions right (hopefully as not fully tested).

@echo off
REM Backup files first and report any errors if not successful
%SystemRoot%\System32\xcopy.exe "C:\channels\filetransfer_process\*" "C:\channels\backup\" /C /Q /Y >"%TEMP%\%~n0.tmp"

REM Error checking
REM Note: The environment variable ERRORLEVEL contains the
REM       return code of  the last executed program or script.
if errorlevel 5 SET "BODY=File write error occurred" & GOTO MailError
if errorlevel 2 SET "BODY=Not enough memory or free space" & GOTO MailError
if not errorlevel 1 pause

set "FileCount=0"
for /F "usebackq" %%I in ("%TEMP%\%~n0.tmp") do set "FileCount=%%I"
if "FileCount" == "0" SET "BODY=No files were found to copy" & GOTO MailError

REM Temporary file with number of copied files as last line no longer needed.
del "%TEMP%\%~n0.tmp"
set "FileCount="

REM Before doing the network connection make sure Z drive is free for use
%SystemRoot%\System32\net.exe use Z: /delete 2>nul

REM Proceed with a network connection using Z with error checking.
%SystemRoot%\System32\net.exe use /persistent:no
%SystemRoot%\System32\net.exe use Z: \\dcqwdbs034\D$\arrivals password /user:domain\username
if errorlevel 1 SET "BODY=Net use connection failed" & GOTO MailError
if not exist Z:\ SET "BODY=Net use connection failed" & GOTO MailError

REM Move files to MSCM server.
move /Y "C:\channels\filetransfer_process\*" "Z:\"
if errorlevel 1 (
    %SystemRoot%\System32\net.exe use Z: /delete
    SET "BODY=File not found, could not be moved/renamed or bad parameters"
    GOTO MailError
)

REM Remove network mapped Z drive.
%SystemRoot%\System32\net.exe use Z: /delete
%SystemRoot%\System32\net.exe use /persistent:yes
goto :EOF

REM Perform the error notification via BLAT.
:MailError
%SystemRoot%\System32\net.exe use /persistent:yes
del "%TEMP%\%~n0.tmp" 2>nul
"D:\Program Files\BLAT\blat.exe" -Install -Server mail1.sutterhealth.org -f name@domain.org -u name@domain.org -Pw mypasswd "D:\Program Files\BLAT\blat.exe" -To name@domain.org.org -Subject "File Transfer Error" -Body "%BODY%"

XCOPY is executed with option /Q to suppress output of copied files. But XCOPY outputs nevertheless as final summary information the number of copied files. This output is redirected into a temporary file for later evaluation. But first is the exit code of XCOPY evaluated.

if errorlevel 2 means if exit code of command/application is greater or equal 2 and so if errorlevel 5 must be the first IF condition.

[ and ] have no special meanings on a string comparison. They are just two literal characters. So don't add them on a string comparison. if NOT "%errorlevel%"=="0" pause would be absolutely enough.

The double quotes have a special meaning for command interpreter as marking begin/end of an argument string in which the characters should be interpreted literally with exception of % and ! on delayed expansion enabled. But please note that " are always included by IF on comparing the two arguments. In other words if does not remove surrounding double quotes before comparing the arguments.

ERRORLEVEL has always an integer value assigned as string and therefore it is safe to use if NOT %ERRORLEVEL% == 0 pause to make the string comparison a bit faster because of just two bytes have to be compared (ASCII representation of 0 and string terminating null byte, i.e. 0x30, 0x00) instead of four bytes (quote byte, ASCII representation of 0, quote byte and string terminating null byte, i.e. 0x22, 0x30, 0x22, 0x00).

But best is using if not errorlevel 1 which means if exit code of previous command/application is lower than 1. Nearly all applications exit with 0 on success and a positive number greater 0 on an error condition. Therefore if not errorlevel 1 working also within a command block is nearly always better than if %ERRORLEVEL% == 0 for testing on success.

The command FOR with option /F as used in this batch file reads the lines from specified file line by line, skips empty lines, skips lines starting with a semicolon, splits up each line into substrings using default delimiters space and horizontal tab and assigns first space/tab delimited string to specified loop variable I. In this case this should be always the number of copied files.

The application NET does often not exit with a value greater 0 on an error. So better verify if drive Z: really exists after mapping network share to a drive letter. It is also better making the network drive mapping not persistent stored in Windows registry of current user. BTW: The domain, user name and password posted in code in question are hopefully fake data.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • del /?
  • echo /?
  • for /?
  • goto /?
  • move /?
  • net /?
  • net use /?
  • pause /?
  • rem /?
  • set /?
  • xcopy /?

See also:

Mofi
  • 46,139
  • 17
  • 80
  • 143