1@echo off 2 3:: 4:: Some basic tests 5:: 6 7echo ------------ Testing FOR loop ------------ 8echo --- Multiple lines 9for %%i in (A 10B 11C) do echo %%i 12 13echo --- Lines and spaces 14for %%i in (D 15 E 16 F) do echo %%i 17 18echo --- Multiple lines and commas 19for %%i in (G, 20H, 21I 22) do echo %%i 23 24echo --- Multiple lines and %%I 25:: The FOR-variable is case-sensitive 26for %%i in (J 27 K 28 L) do echo %%I 29 30echo --- Multiple lines and %%j 31for %%i in (M, 32N, 33O 34) do echo %%j 35 36 37echo ---------- Testing AND operator ---------- 38:: Test for TRUE condition - Should be displayed 39ver | find "Ver" > NUL && echo TRUE AND condition 40 41:: Test for FALSE condition - Should not display 42ver | find "1234" > NUL && echo FALSE AND condition 43 44echo ---------- Testing OR operator ----------- 45:: Test for TRUE condition - Should not display 46ver | find "Ver" > NUL || echo TRUE OR condition 47 48:: Test for FALSE condition - Should be displayed 49ver | find "1234" > NUL || echo FALSE OR condition 50 51 52 53:: 54:: Testing CMD exit codes and errorlevels. 55:: 56:: Observations: 57:: - OR operator || converts the LHS error code to ERRORLEVEL only on failure; 58:: - Pipe operator | converts the last error code to ERRORLEVEL. 59:: 60:: See https://stackoverflow.com/a/34987886/13530036 61:: and https://stackoverflow.com/a/34937706/13530036 62:: for more details. 63:: 64setlocal enableextensions 65 66echo ---------- Testing CMD exit codes and errorlevels ---------- 67 68:: Tests for CMD returned exit code. 69 70echo --- CMD /C Direct EXIT call 71 72call :setError 0 73cmd /c "exit 42" 74call :checkErrorLevel 42 75 76call :setError 111 77cmd /c "exit 42" 78call :checkErrorLevel 42 79 80echo --- CMD /C Direct EXIT /B call 81 82call :setError 0 83cmd /c "exit /b 42" 84call :checkErrorLevel 42 85 86call :setError 111 87cmd /c "exit /b 42" 88call :checkErrorLevel 42 89 90:: Non-existing ccommand, or command that only changes 91:: the returned code (but NOT the ERRORLEVEL) and EXIT. 92 93echo --- CMD /C Non-existing command 94 95:: EXIT alone does not change the ERRORLEVEL 96call :setError 0 97cmd /c "nonexisting & exit" 98call :checkErrorLevel 9009 99 100call :setError 111 101cmd /c "nonexisting & exit" 102call :checkErrorLevel 9009 103 104call :setError 0 105cmd /c "nonexisting & exit /b" 106call :checkErrorLevel 9009 107 108call :setError 111 109cmd /c "nonexisting & exit /b" 110call :checkErrorLevel 9009 111 112echo --- CMD /C RMDIR (no ERRORLEVEL set) 113 114call :setError 0 115cmd /c "rmdir nonexisting & exit" 116call :checkErrorLevel 0 117 118call :setError 111 119cmd /c "rmdir nonexisting & exit" 120call :checkErrorLevel 0 121 122call :setError 0 123cmd /c "rmdir nonexisting & exit /b" 124call :checkErrorLevel 0 125 126call :setError 111 127cmd /c "rmdir nonexisting & exit /b" 128call :checkErrorLevel 0 129 130:: Failing command (sets ERRORLEVEL to 1) and EXIT 131echo --- CMD /C DIR (sets ERRORLEVEL) - With failure 132 133:: EXIT alone does not change the ERRORLEVEL 134call :setError 0 135cmd /c "dir nonexisting>NUL & exit" 136call :checkErrorLevel 1 137 138call :setError 111 139cmd /c "dir nonexisting>NUL & exit" 140call :checkErrorLevel 1 141 142call :setError 0 143cmd /c "dir nonexisting>NUL & exit /b" 144call :checkErrorLevel 1 145 146call :setError 111 147cmd /c "dir nonexisting>NUL & exit /b" 148call :checkErrorLevel 1 149 150:: Here EXIT changes the ERRORLEVEL 151call :setError 0 152cmd /c "dir nonexisting>NUL & exit 42" 153call :checkErrorLevel 42 154 155call :setError 111 156cmd /c "dir nonexisting>NUL & exit 42" 157call :checkErrorLevel 42 158 159call :setError 0 160cmd /c "dir nonexisting>NUL & exit /b 42" 161call :checkErrorLevel 42 162 163call :setError 111 164cmd /c "dir nonexisting>NUL & exit /b 42" 165call :checkErrorLevel 42 166 167:: Succeeding command (sets ERRORLEVEL to 0) and EXIT 168echo --- CMD /C DIR (sets ERRORLEVEL) - With success 169 170call :setError 0 171cmd /c "dir>NUL & exit" 172call :checkErrorLevel 0 173 174call :setError 111 175cmd /c "dir>NUL & exit" 176call :checkErrorLevel 0 177 178call :setError 0 179cmd /c "dir>NUL & exit 42" 180call :checkErrorLevel 42 181 182call :setError 111 183cmd /c "dir>NUL & exit 42" 184call :checkErrorLevel 42 185 186call :setError 0 187cmd /c "dir>NUL & exit /b 42" 188call :checkErrorLevel 42 189 190call :setError 111 191cmd /c "dir>NUL & exit /b 42" 192call :checkErrorLevel 42 193 194 195:: Same sorts of tests, but now from within an external batch file: 196:: Tests for CALL command returned exit code. 197 198:: Use an auxiliary CMD file 199mkdir foobar && cd foobar 200 201:: Non-existing ccommand, or command that only changes 202:: the returned code (but NOT the ERRORLEVEL) and EXIT. 203 204echo --- CALL Batch Non-existing command 205 206:: EXIT alone does not change the ERRORLEVEL 207echo nonexisting ^& exit /b> tmp.cmd 208call :setError 0 209call tmp.cmd 210call :checkErrorLevel 9009 211 212echo nonexisting ^& exit /b> tmp.cmd 213call :setError 111 214call tmp.cmd 215call :checkErrorLevel 9009 216 217:: These tests show that || converts the returned error code 218:: from RMDIR on failure, and converts it to an ERRORLEVEL 219:: (first two tests: no ||, thus no ERRORLEVEL set; 220:: last two tests: ||used and ERRORLEVEL is set). 221:: 222 223echo --- CALL Batch RMDIR (no ERRORLEVEL set) 224 225:: This test shows that if a batch returns error code 0 from CALL, 226:: then CALL will keep the existing ERRORLEVEL (here, 111)... 227echo rmdir nonexisting> tmp.cmd 228echo exit /b>> tmp.cmd 229call :setError 0 230call tmp.cmd 231call :checkErrorLevel 0 232 233echo rmdir nonexisting> tmp.cmd 234echo exit /b>> tmp.cmd 235call :setError 111 236call tmp.cmd 237call :checkErrorLevel 111 238 239echo --- CALL Batch RMDIR with ^|^| (sets ERRORLEVEL) 240 241:: ... but if a non-zero error code is returned from CALL, 242:: then CALL uses it as the new ERRORLEVEL. 243echo rmdir nonexisting ^|^| rem> tmp.cmd 244echo exit /b>> tmp.cmd 245call :setError 0 246call tmp.cmd 247call :checkErrorLevel 2 248:: This gives the same effect, since the last command's error code 249:: is returned and transformed by CALL into an ERRORLEVEL: 250echo rmdir nonexisting> tmp.cmd 251call :setError 0 252call tmp.cmd 253call :checkErrorLevel 2 254 255echo rmdir nonexisting ^|^| rem> tmp.cmd 256echo exit /b>> tmp.cmd 257call :setError 111 258call tmp.cmd 259call :checkErrorLevel 2 260:: This gives the same effect, since the last command's error code 261:: is returned and transformed by CALL into an ERRORLEVEL: 262echo rmdir nonexisting> tmp.cmd 263call :setError 111 264call tmp.cmd 265call :checkErrorLevel 2 266 267 268:: Failing command (sets ERRORLEVEL to 1) and EXIT 269echo --- CALL Batch DIR (sets ERRORLEVEL) - With failure 270 271echo dir nonexisting^>NUL> tmp.cmd 272call :setError 0 273call tmp.cmd 274call :checkErrorLevel 1 275 276echo dir nonexisting^>NUL> tmp.cmd 277call :setError 111 278call tmp.cmd 279call :checkErrorLevel 1 280 281echo dir nonexisting^>NUL ^& goto :eof> tmp.cmd 282call :setError 0 283call tmp.cmd 284call :checkErrorLevel 1 285 286echo dir nonexisting^>NUL ^& goto :eof> tmp.cmd 287call :setError 111 288call tmp.cmd 289call :checkErrorLevel 1 290 291echo dir nonexisting^>NUL ^& exit /b> tmp.cmd 292call :setError 0 293call tmp.cmd 294call :checkErrorLevel 1 295 296echo dir nonexisting^>NUL ^& exit /b> tmp.cmd 297call :setError 111 298call tmp.cmd 299call :checkErrorLevel 1 300 301echo dir nonexisting^>NUL ^& exit /b 42 > tmp.cmd 302call :setError 0 303call tmp.cmd 304call :checkErrorLevel 42 305 306echo dir nonexisting^>NUL ^& exit /b 42 > tmp.cmd 307call :setError 111 308call tmp.cmd 309call :checkErrorLevel 42 310 311:: Succeeding command (sets ERRORLEVEL to 0) and EXIT 312echo --- CALL Batch DIR (sets ERRORLEVEL) - With success 313 314echo dir^>NUL> tmp.cmd 315call :setError 0 316call tmp.cmd 317call :checkErrorLevel 0 318 319echo dir^>NUL> tmp.cmd 320call :setError 111 321call tmp.cmd 322call :checkErrorLevel 0 323 324echo dir^>NUL ^& goto :eof> tmp.cmd 325call :setError 0 326call tmp.cmd 327call :checkErrorLevel 0 328 329echo dir^>NUL ^& goto :eof> tmp.cmd 330call :setError 111 331call tmp.cmd 332call :checkErrorLevel 0 333 334echo dir^>NUL ^& exit /b> tmp.cmd 335call :setError 0 336call tmp.cmd 337call :checkErrorLevel 0 338 339echo dir^>NUL ^& exit /b> tmp.cmd 340call :setError 111 341call tmp.cmd 342call :checkErrorLevel 0 343 344echo dir^>NUL ^& exit /b 42 > tmp.cmd 345call :setError 0 346call tmp.cmd 347call :checkErrorLevel 42 348 349echo dir^>NUL ^& exit /b 42 > tmp.cmd 350call :setError 111 351call tmp.cmd 352call :checkErrorLevel 42 353 354 355:: Cleanup 356del tmp.cmd 357cd .. & rmdir /s/q foobar 358 359 360:: 361:: Finished! 362:: 363echo --------- Finished -------------- 364goto :EOF 365 366:checkErrorLevel 367if %errorlevel% neq %1 (echo Unexpected errorlevel %errorlevel%, expected %1) else echo OK 368goto :eof 369 370:: Subroutine to set errorlevel and return 371:: in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported 372:setError 373exit /B %1 374:: This line runs under cmd in windows NT 4, but not in more modern versions. 375