Eu tenho um bat com algum rótulo nele, então eu começo meu bat verificando se algum argumento foi passado, caso contrário, a execução fará uma nova chamada do próprio bat passando um argumento, e uma vez feito isso ele continua executando o próximo comandos.
Quando bat inicia por uma chamada recebendo um argumento, sua execução é colocada em loop dentro de um :label (permanentemente)
É um morcego que pode levar muito tempo para ser executado, então a chamada faz com que uma barra de progresso "infinita" apareça no título da janela e permaneça em um loop fazendo isso em segundo plano.
Porque é tedioso ver uma linha estática ( "Finding Nemo, Files, etc..." ) na tela ou na barra de título, e um exemplo recente de uma tarefa/script que leva muito tempo é encontrar uma nova executável (versão/data) verificando todos os drivers e comparando os resultados para obter um (mais recente), respondido aqui .
Tomando o código vinculado acima para um exemplo de tarefa demorada e adicionando uma barra de progresso no título, tenho o seguinte código:
@echo off
if "%~1."=="." (call start ".:." /b cmd.exe /v:on /c "%~f0" ? )else goto %:^|
setlocal enabledelayedexpansion && set "_f=" && set "_ff=" && set /a "_cnt=0"
for /f usebackq^tokens^=* %%f in (`%__AppDir__%mountvol.exe^|find.exe /i ":\"
`)do 2>nul pushd %%~f && (set/a "_cnt+=1" && call %:^) _ff_!_cnt! & popd)
for /f useback^tokens^=1*delims^=^=^ %%i in (`^<nul ^<con: set _ff_ ^|%__AppDir__%sort.exe /r
`)do <con: <nul call set "_ffprobe=%%~dpnxj" & call set "_ffprob_Path=%%~dpj" & goto %:^V
%:^)
for /f usebackq^tokens^=2^,4* %%i in =;(`2^>nul %__AppDir__%where.exe /r \ ffprobe.exe /t ^|^
%__AppDir__%sort.exe /r^|^|exit/b`)do set "_f=%%~k" && for /f useback^delims^=. %%G in (`
^<con %__AppDir__%wbem\wmic.exe DataFile where name^="!_f:\=\\!" get LastModified ^|^
%__AppDir__%findstr.exe /rb [0-9]`)do <con: <nul call set "%~1=%%~k" && exit /b 0
%:^|
>nul chcp 65001 & mode 89,5 & set "_title=Looking for your latest ffprob.exe, please wait^!!"
<con: ;color 0a && set^ "_176=░░░░░░░░░░" && set^ "_255=▓▓▓▓▓▓▓▓▓▓" && set^ "_022=▬▬▬▬▬▬▬▬▬▬"
call setlocal enabledelayedexpansion & set "_ping=%__AppDir__%pathping.exe 127.1 -q 1 -p 050"
%:^/
set "_title=I'm doing something that takes a while, please wait^!!"
for %%G in =;(1,2,3,4,5,6,0)do if "!_ffprob_Path!\." == "\." =;( if ".\%%~G\." == ".\1\." =;(
for /l %%L in (0 01 10)do %_ping% |title !_title! [!_255:~0,%%~L!!_022:~%%L!] !time:~,8!
)else if "%%G\" == "2\" =;(if "!_ffprob_Path!\." == "\." =;(
for /l %%L in (10 -1 0)do %_ping% |title !_title! [!_255:~0,%%~L!!_176:~%%L!] !time:~,8!
))else if "%%G\" == "3\" =;(if "!_ffprob_Path!\." == "\." =;(
for /l %%L in (0 01 10)do %_ping% |title !_title! [!_022:~0,%%~L!!_176:~%%L!] !time:~,8!
))else if "%%G\" == "4\" =;(if "!_ffprob_Path!\." == "\." =;(
for /l %%L in (10 -1 0)do %_ping% |title !_title! [!_022:~0,%%~L!!_255:~%%L!] !time:~,8!
))else if "%%G\" == "5\" =;(if "!_ffprob_Path!\." == "\." =;(
for /l %%L in (0 01 10)do %_ping% |title !_title! [!_176:~0,%%~L!!_255:~%%L!] !time:~,8!
))else if "%%G\" == "6\" =;(if "!_ffprob_Path!\." == "\." =;(
for /l %%L in (10 -1 1)do %_ping% |title !_title! [!_176:~0,%%~L!!_022:~%%L!] !time:~,8!
))else if "%%G\" == "0\" =;(if "!_ffprob_Path!\." == "\." =;(
goto %:^/
)));=
%:^V
rem./ your code continues at this point using: / & echo+!_ffprob_Path! & echo+!_ffprobe!
O resultado é que a barra de progresso "infinita" inicia e não para, mesmo após a variável ser definida, onde deveria sinalizar o fim do loop no rótulo da barra de progresso, mas não funciona...
Foram feitas várias tentativas com enable/disable setlocal, invertendo a ordem da chamada do label, e coisas que nem lembro, mas houve várias tentativas de finalizar o loop e sem sucesso...
Como terminar o loop de um rótulo rodando em segundo plano do mesmo morcego?
Estou neste ponto há tanto tempo que não vejo nada.
Qualquer ideia?
O mesmo código no layout convencional...
@echo off
if "%~1." == "." (
call start ".:." /b cmd.exe /v:on /c "%~f0" ?
) else (
goto %:^p
)
setlocal enabledelayedexpansion
set "_f="
set "_ff="
set /a "_cnt=0"
for /f "usebackq tokens=*" %%f in (`%__AppDir__%mountvol.exe ^| %__AppDir__%find.exe /i ":\"`) do 2>nul (
pushd %%~f && (
set /a "_cnt+=1"
call %:^) _ff_!_cnt!
popd
)
)
for /f "usebackq tokens=1* delims==" %%i in (`set _ff_ ^| %__AppDir__%sort.exe /r`) do (
call set "_ffprobe=%%~dpnxj"
call set "_ffprob_Path=%%~dpj"
goto %:^V
)
%:^)
for /f "usebackq tokens=2,4*" %%i in (`2^>nul %__AppDir__%where.exe /r \ ffprobe.exe /t ^| %__AppDir__%sort.exe /r ^|^| exit /b`) do (
set "_f=%%~k"
for /f "usebackq delims=." %%G in (`^<con: call %__AppDir__%wbem\wmic.exe DataFile where name^="!_f:\=\\!" get LastModified ^| %__AppDir__%findstr.exe /rb [0-9]`)do (
call set "%~1=%%~k"
exit /b 0
)
)
%:^p
>nul chcp 65001
%__AppDir__%mode.com con: cols=89 lines=5
set "_title=Looking for your latest ffprob.exe, please wait^!!"
color 0a
set "_176=░░░░░░░░░░"
set "_255=▓▓▓▓▓▓▓▓▓▓"
set "_022=▬▬▬▬▬▬▬▬▬▬"
setlocal enabledelayedexpansion
set "_ping=%__AppDir__%pathping.exe 127.1 -q 1 -p 050"
%:^/
for %%G in =;(1,2,3,4,5,6,0)do (
if "!_ffprob_Path!\." == "\." (
if ".\%%~G\." == ".\1\." (
for /l %%L in (0 01 10) do %_ping% | title !_title! [!_255:~0,%%~L!!_022:~%%L!] !time:~,8!
)else if "%%G\" == "2\" (
if "!_ffprob_Path!\." == "\." (
for /l %%L in (10 -1 0) do %_ping% | title !_title! [!_255:~0,%%~L!!_176:~%%L!] !time:~,8!
)
)else if "%%G\" == "3\" (
if "!_ffprob_Path!\." == "\." (
for /l %%L in (0 01 10) do %_ping% | title !_title! [!_022:~0,%%~L!!_176:~%%L!] !time:~,8!
)
)else if "%%G\" == "4\" (
if "!_ffprob_Path!\." == "\." (
for /l %%L in (10 -1 0) do %_ping% | title !_title! [!_022:~0,%%~L!!_255:~%%L!] !time:~,8!
)
)else if "%%G\" == "5\" (
if "!_ffprob_Path!\." == "\." (
for /l %%L in (0 01 10) do %_ping% | title !_title! [!_176:~0,%%~L!!_255:~%%L!] !time:~,8!
)
)else if "%%G\" == "6\" (
if "!_ffprob_Path!\." == "\." (
for /l %%L in (10 -1 1) do %_ping% | title !_title! [!_176:~0,%%~L!!_022:~%%L!] !time:~,8!
)
)else if "%%G\" == "0\" (
if "!_ffprob_Path!\." == "\." (
goto %:^/
)
)
)
)
%:^V
rem./ your code continues at this point using: /
echo+!_ffprob_Path!
echo+!_ffprobe!
Minha abordagem para isso é usar um loop infinito para /l em um rótulo que é iniciado como um encadeamento separado. Eu uso um ADS do arquivo para me comunicar com o thread do arquivo principal quando parar, depois uma saída difícil para sair do thread.