ERRORLEVEL env atualizações de variáveis no script em lote, mas% ERRORLEVEL% não

2

Eu tenho o seguinte script em lote que é executado em um servidor ftp. Eu uso um agendador que passa 4 variáveis; SouRCe, EXTension, DESTination e ZIP Directory. É um script simples que requer as 3 primeiras variáveis, mas o usuário pode omitir o último 4º, se não precisar zipar os arquivos.

@ECHO OFF

SET SRC=%1
SET EXT=%2
SET DEST=%3
SET ZIPD=%4
SET DTE=%DATE:~4,2%%DATE:~7,2%%DATE:~10,4%
FOR /F "TOKENS=1-3 DELIMS=: " %%L IN ('TIME /T') DO SET hhmm=%%L%%M%

DIR /B /A:-d %SRC%
IF ERRORLEVEL 1 (
        ECHO *** There are no files to process. *** RC=%ERRORLEVEL%
    SET ERRORLEVEL=0
        GOTO EXIT
)

DEL /Q %SRC%\Thumbs.db

IF DEFINED ZIPD (
    WZZIP %ZIPD%\%DTE%%hhmm%.zip %SRC%\*%EXT%
    IF ERRORLEVEL 1 (
        ECHO *** WZZIP for "%SRC%\*%EXT%" failed. *** RC=%ERRORLEVEL%
        ECHO.
        GOTO EXIT
    )
    ECHO.
    ECHO successfully zipped %SRC% TO %ZIPD%: %DTE%%hhmm%.zip
    ECHO.
)

MOVE /Y %SRC%\*%EXT% %DEST%
IF ERRORLEVEL 1 (
    ECHO ** MOVE "%SRC%\*%EXT%" TO "%DEST%"  Failed. *** RC=%ERRORLEVEL%
)

:EXIT
EXIT /B %ERRORLEVEL%

O problema que estou encontrando é que, se nada estiver no diretório às 8:15 da manhã (o Scheduler o executa),

DIR /B /A:-d %SRC%

falha com um errorlevel de 1. Ele entra no loop e sai. O teste para errorlevel funciona como

IF ERRORLEVEL 1

e como

IF NOT %ERRORLEVEL% == 0

O problema que estou encontrando é que quaisquer falhas subsequentes não estão atualizando a variável de usuário% ERRORLEVEL%. É por isso que eu tenho que usar SE ERRORLEVEL 1 para as outras verificações. Agora, se WZZIP falhar, ele entrará no loop após o comando, mas a mensagem ECHO exibirá "RC = 0" mesmo que ERRORLEVEL tenha que ser maior que ou igual a 1 e, como tal, deve ter atualizado% ERRORLEVEL% para tudo o que é suposto ser. Eu testei o script adicionando

ECHO %ERRORLEVEL%

para todas as outras linhas apenas para ver as alterações e, embora o teste DIR atualize% ERRORLEVEL% corretamente, novamente DEL do thumb.db, que falha 99,999% do tempo, retorna% ERRORLEVEL% = 0 e WZZIP se forçado a falhar também sai RC = 0. Tentei SETLOCAL, SETLOCAL ENABLEEXTENSIONS, e um monte de outras coisas, até tentei remover tudo, mas a parte WZZIP e ainda não atualizou% ERRORLEVEL%. É um servidor FTP, que estamos constantemente executando scripts para transferir arquivos, então eu queria saber se talvez haja algum conflito com outros fluxos de cmd alterando a variável env enquanto eu estou executando o meu script? Além disso, a maioria dos outros scripts não foram escritos por mim e eles AMAM usando SET ERRORLEVEL=whatevernumber e sei que isso me causou conflitos no passado. Eu estou querendo saber se isso poderia ser o culpado.

    
por user3377627 13.08.2016 / 02:32

1 resposta

1

Você precisa Expansão atrasada se quiser usar uma variável que você alterou no mesmo bloco de comando. (Um bloco de comandos é uma série de comandos entre parênteses ( e ) .) Variáveis atrasadas são referenciadas usando !var! em vez de %var% .

Exemplo :

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
cmd /C exit /B 99
echo before ^(command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
(
  (call)
  echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
  (call )
  echo ^(inside command block^) %%errorlevel%%=%errorlevel% ^^!errorlevel^^!=!errorlevel!
)
echo  after ^(command block^) %%errorlevel%%=%errorlevel%  ^^!errorlevel^^!=!errorlevel!

Saída :

==> D:\bat\SU13027.bat
before (command block) %errorlevel%=99 !errorlevel!=99
(inside command block) %errorlevel%=99 !errorlevel!=1
(inside command block) %errorlevel%=99 !errorlevel!=0
 after (command block) %errorlevel%=0  !errorlevel!=0

Os truques (call) e (call ) foram roubados de essa resposta de Dbenham para definir ERRORLEVEL como 0 pergunta:

If you want to force the errorlevel to 0, then you can use this totally non-intuitive, but very effective syntax: (call ). The space after call is critical. If you want to set the errorlevel to 1, you can use (call). It is critical that there not be any space after call.

    
por 13.08.2016 / 09:14