Não é possível obter o comportamento correto no loop de lote

2

Estou usando o seguinte loop em um arquivo de lote para chamar individualmente 'funções' no arquivo, começando exibindo o texto e terminando com uma verificação e exibição de nível de erro.

Chamar a função de loop usa duas variáveis.

  1. o nome da subfunção a ser chamado
  2. o texto a ser exibido na tela para facilitar o usuário

Isto é o que essas linhas de chamada parecem

call :loop BackupDatabase "Taking database backup"
call :loop StopBGService "Stopping the background service"

Esta é a própria função de loop

:loop
    :retry
    echo %~2
    call :%~1

    IF %ERRORLEVEL% NEQ 0 (
        SET ERRORLEV=%ERRORLEVEL%
        ECHO Executing %~2 failed
        ECHO Error Level: %ERRORLEV%
        ECHO.

        set /p ans=Do you want to retry %~2 [y/n]^>
        if "%ans%"== "y" goto :retry
        if "%ans%"== "Y" goto :retry
    )
GOTO :EOF

Abaixo você encontrará as funções que são chamadas por cada loop

:BackupDatabase
    Perform database backup commands
GOTO :EOF

:StopBGService
    Perform stop background service commands
GOTO :EOF

O problema que estou tendo é quando um "loop" está errado, o script deve perguntar se uma nova tentativa é necessária, a primeira vez que isso acontece, se você digitar "n", ele ainda tentará novamente? Eu li o script loop repetidamente e não posso dizer por que isso é. Se alguém puder consertar isso, seria uma grande ajuda, ou se alguém puder apontar uma maneira melhor de fazer o que estou tentando alcançar.

    
por Ghandi Manning 03.07.2013 / 19:17

1 resposta

2

O problema é que o Prompt de Comando do Windows / Interpretador de Linha de Comando (CLI), conhecido como CMD.EXE, tem um bug (bem, eu tenho certeza que a Microsoft acha que é um recurso) em que, quando lê uma construção de bloco como IF … ( … ) ou FOR loop, ele interpreta todas as variáveis %variable_name% imediatamente , antes que o loop seja executado. No seu exemplo, se ans for nulo quando você inserir o bloco IF %ERRORLEVEL% NEQ 0 ( … ) , então todas as ocorrências de %ans% dentro desse bloco são avaliadas como nulas, mesmo se você alterar ans dentro do bloco. Você pode ver isso se você deixar ECHO on (ou ligá-lo novamente antes de IF %ERRORLEVEL% NEQ 0 ).

A correção é dizer ao CMD para permitir que as variáveis sejam expandidas no momento certo, quando as declarações referentes a eles são executadas. Você faz isso adicionando

setlocal enabledelayedexpansion

em algum lugar perto do início do seu arquivo de lote e alterando o código da caixa de diálogo do usuário para que pareça

    set /p ans=Do you want to retry %~2 [y/n]^>
    if "!ans!" == "y" goto :retry
    if "!ans!" == "Y" goto :retry

usando o formulário !variable_name! para ativar a expansão atrasada. Veja SET /? e SETLOCAL /? para mais informações.

    
por 03.07.2013 / 19:53