Is it possible to get an `errorlevel 1` from `xcopy` in Windows 10?

5

2

Microsoft documentation states that the xcopy exit codes are

Exit code   Description
    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.

I'm running a Windows 10 64bit system (spanish locale), and I've tried everything I could think of to get an errorlevel 1 from xcopy, but I've not been able. And by everything I mean the only thing I did not test was /N with long file names in a source where short names are not enabled (in my environment I can not test it). The usual suspects non matching wildcards, non present file names, empty folders, /D, /EXCLUDE, /A, /M, /U, ... were tested.

I though it should be easy (not files found?, easy), but I was wrong, it was not, so I debugged xcopy.exe and this is what I saw:

  • xcopy internally uses a method called DisplayMessageAndExit(messageID, WSTRING, exitCode) to, well, display a message and exit. It also uses several exit calls to leave the program in some cases (ex. Ctrl-C)

  • I have not found any exit call that could use a value of 1

  • From the list of calls made to DisplayMessageAndExit, none of them pass/receive a value of 1 as exit code.

  • From the list of calls made to DisplayMessageAndExit only one of them use the MessageID 0x5622 (in my install the resources associated are in C:\Windows\System32\es-ES\ulib.dll.mui, it is locale dependent), that is No se encuentra el archivo: %1 (File not found - %1), and the exit code used in the call is 4

Maybe there is a way in which xcopy is able to generate the 1 exit code, but I don't know how.

So the question is: Is there a way to get errorlevel 1 exit code from xcopy? What am I missing?

MC ND

Posted 2017-02-18T11:17:06.283

Reputation: 1 286

I would expect it if you use /d and no files are newer. – AFH – 2017-02-18T11:58:06.487

@AFH Nope. /d doesn't do it. – DavidPostill – 2017-02-18T13:04:18.767

@DavidPostill - Sorry, I didn't have time to check. I did say I would expect it, and I feel it should. – AFH – 2017-02-18T13:07:16.573

@AFH You are right it should (it returns 0). I tried xcopy foo bar where foo doesn't exist and that didn't do it either (it returns 4). – DavidPostill – 2017-02-18T13:24:45.927

@DavidPostill, As I see it there are two options: it is impossible or it is something so obvious I'm not seeing it. But all that I though as obvious did not work. – MC ND – 2017-02-18T13:35:06.397

@DavidPostill - The only other possibilities I can think of which should return 1 are copying an empty directory or using a file mask has no matches. – AFH – 2017-02-18T21:11:46.140

@MCND - Like you, I've tried everything I can think of, without finding anything which returns 1. It very much looks like a long-standing bug. The best you can do is xcopy ... >%temp%\xcopy.tmp; if the return code is 0, use findstr /l "0 File(s) copied"<%temp%\xcopy.tmp to check for no files copied. Don't be tempted to pipe to anything: eg piping to tee will give the return code set by tee, not from xcopy. – AFH – 2017-02-19T18:52:17.830

@AFH, After testing I was 80% sure it is a bug. After debugging xcopy I was 99.9% sure it is a bug, but I could have overlooked something that someone else knows. Yes, I know how to handle the 0 File(s), and the pipe behaviour but in this case I'm only interested on the exit code behaviour. Anyway, thank you for your testing. – MC ND – 2017-02-19T19:37:32.347

2I guess that they in Microsoft know it. There is a sample COPYIT.BAT at the provided link to perform xcopy operations and use the batch if command to process the exit code if an error occurs. The batch does not care about errorlevel 1 at all and processes only errolevels 4, 2 and 0 (it's not a bug, it's a feature?) – JosefZ – 2017-04-06T07:20:21.587

@JosefZ, Thank you, I missed the batch file (rendering in one line does not help). It seems that who write it don't really know how errorlevel works. if errorlevel 0 is always true for any non negative errorlevel value, and xcopy doesn't document negative values. It seems the intention is to use a fallthrough into the following label to handle the errorlevel 1 case, but, as said, the code is wrong. – MC ND – 2017-04-06T08:15:05.327

I guess that if errorlevel 0 goto exit is intended to skip following :lowmemory label (please note the if errorlevel 4 goto lowmemory. Errorlevel is tested properly in descending order. Missing check of if errorlevel 1 is more interesting thing for me from view of your question. – JosefZ – 2017-04-06T10:26:03.193

2@JosefZ, to skip :lowmemory you only need a goto, not a if errorlevel 0 that in this scenario is always true. Why to use an if? It is just my opinion, but for me it seems a (wrong) fallthrough, as in C switch statement. Of course I don't know "why" and I could be wrong (again). In any case, yes, your point creates a suspicious omission in their code. – MC ND – 2017-04-06T10:48:57.980

Tried a wildcard expand that expanded to nothing; nope that error code is 0! – Joshua – 2018-12-05T18:36:11.680

Answers

0

The only thing I can think of is some sort of race condition that between xcopy gathering the list of files it will copy and actually doing the copy, some other process deletes or moves the files.

If you can get an error 1 if only SOME of the source files were missing then it might be able to do this on purpose. About the only way I can think to do this on purpose is to have 2 or more separate processes running, one xcopy and one delete or move command, all operating on the same source files. You will need a source with lots of files in them to give the competing processes time to overtake each other.

  1. start a move, del, or robocopy /mov command on a folder with lots of files in it.
  2. in another window, and well before the first command finishes start your xcopy command

Omitting the /C switch may mean that if it is the first file xcopy tries and fails on it will give up straight away without copying any files, thus satisfying the condition of NO files copied.

BeowulfNode42

Posted 2017-02-18T11:17:06.283

Reputation: 1 629

1Good try, but no. To avoid having to wait for a collision I directly put a break point in the xcopy program just before the file copy operation and when it is reached I deleted the file to be copied. When resuming the xcopy executable I get error code 4. – MC ND – 2018-03-14T15:24:00.383