por off lotes lenguaje informatica ejemplos crear como comandos batch bat avanzados archivos archivo batch-file spinner

batch file - off - ¿Cómo codificar un spinner para procesos en espera en un archivo Batch?



echo off bat (12)

Esto realmente se puede hacer bastante fácilmente con comandos nativos puros, solo tienes que saber cómo usar los más difíciles. No es necesario el uso de herramientas externas como VBScript o efectos secundarios desagradables como borrar la pantalla.

Lo que estás buscando es el equivalente al comando bash " echo -n " que genera una línea sin la nueva línea. En el lote de XP, esto se logra usando " set /p " (pida al usuario que responda con un mensaje) con la entrada vacía de la siguiente manera:

<nul (set /p junk=Hello) echo. again.

dará salida a la cadena "Hola otra vez". sin intercalar línea nueva.

Ese truco (y el uso de CTRL-H, el carácter de retroceso se puede ver en el siguiente script de prueba que comienza (uno después del otro) una subtarea de 10 segundos con un tiempo de espera de 20 segundos y un subtítulo de 15 segundos tarea con un tiempo de espera de 10 segundos.

La secuencia de comandos de carga útil es creada por la secuencia de comandos en ejecución real y su único requisito es que haga el trabajo que tiene que hacer y luego elimine un archivo de marca cuando finalice, para que la función de monitor pueda detectarlo.

Tenga en cuenta que las cadenas ^ H en este script son en realidad caracteres CTRL-H, el ^ | es dos caracteres separados utilizados para escapar del símbolo de la tubería.

@echo off :: Localise environment. setlocal enableextensions enabledelayedexpansion :: Specify directories. Your current working directory is used :: to create temporary files tmp_*.* set wkdir=%~dp0% set wkdir=%wkdir:~0,-1% :: First pass, 10-second task with 20-second timeout. del "%wkdir%/tmp_*.*" 2>nul echo >>"%wkdir%/tmp_payload.cmd" ping 127.0.0.1 -n 11 ^>nul echo >>"%wkdir%/tmp_payload.cmd" del "%wkdir%/tmp_payload.flg" call :monitor "%wkdir%/tmp_payload.cmd" "%wkdir%/tmp_payload.flg" 20 :: Second pass, 15-second task with 10-second timeout. del "%wkdir%/tmp_*.*" 2>nul: echo >>"%wkdir%/tmp_payload.cmd" ping 127.0.0.1 -n 16 ^>nul echo >>"%wkdir%/tmp_payload.cmd" del "%wkdir%/tmp_payload.flg" call :monitor "%wkdir%/tmp_payload.cmd" "%wkdir%/tmp_payload.flg" 10 goto :final :monitor :: Create flag file and start the payload minimized. echo >>%2 dummy start /min cmd.exe /c "%1" :: Start monitoring. :: i is the indicator (0=|,1=/,2=-,3=/). :: m is the number of seconds left before timeout. set i=0 set m=%3 <nul (set /p z=Waiting for child to finish: ^|) :: Loop here awaiting completion. :loop :: Wait one second. ping 127.0.0.1 -n 2 >nul :: Update counters and output progress indicator. set /a "i = i + 1" set /a "m = m - 1" if %i% equ 4 set i=0 if %i% equ 0 <nul (set /p z=^H^|) if %i% equ 1 <nul (set /p z=^H/) if %i% equ 2 <nul (set /p z=^H-) if %i% equ 3 <nul (set /p z=^H/) :: End conditions, complete or timeout. if not exist %2 ( echo. echo. Complete. goto :final ) if %m% leq 0 ( echo. echo. *** ERROR: Timed-out waiting for child. goto :final ) goto :loop :final endlocal

Me gustaría mostrar al usuario con un spinner, que algo se hace en segundo plano, pero no sé cómo funciona esto en un archivo por lotes.

¿Alguien tiene una pista?


Puede usar un contador que imprima un carácter diferente de un conjunto determinado (como "/ | / -") y cambie el carácter de acuerdo con "contador módulo 4". De todos modos, no dice en qué idioma está trabajando, por lo que es un poco difícil ser más preciso.

EDITAR: ahora que sabemos en qué entorno estás jugando, diría que el lenguaje BAT / CMD no está a la altura de la tarea ... Recomendaría cualquier lenguaje de scripting, siendo Ruby mi favorito.


Si entiendo tu pregunta, quieres un spinner porque alguna operación que estás realizando lleva tiempo y quieres mostrarle al usuario que algo está sucediendo, ¿no?

En ese caso, hasta donde yo sé, no es posible con los comandos nativos. (Podría ser posible si tuvieras un programa que mostrara un spinner mientras ejecutabas la operación que lleva mucho tiempo)

Y parece que el eco no es compatible con las secuencias de escape ansi (en los viejos tiempos tenías que tener ansi.sys cargada, no sé si aún existe) por lo que no puedes usar ansi para controlar el cursor.


Si no te importa que la pantalla se borre ... prueba esto:

@ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION SET COUNT=1 START CALC :BEGIN CLS IF !COUNT! EQU 1 ECHO / IF !COUNT! EQU 2 ECHO - IF !COUNT! EQU 3 ECHO / IF !COUNT! EQU 4 ECHO - IF !COUNT! EQU 4 ( SET COUNT=1 ) ELSE ( SET /A COUNT+=1 ) PSLIST CALC >nul 2>&1 IF %ERRORLEVEL% EQU 1 GOTO END GOTO BEGIN :END

EDITAR: Esta muestra iniciará la Calculadora y luego mostrará un "control giratorio" hasta que cierre la Calculadora. Uso pslist para verificar la existencia de CALC.EXE. El > nul 2> & 1 redirige STDOUT y STDERR a nul, por lo que no se mostrará nada de PSLIST.


Si te refieres a un script por lotes de Windows, no puedes hacerlo de forma nativa. La instrucción de eco utilizada para imprimir en la consola siempre imprimirá una nueva línea y no podrá mover el cursor.

Es un truco, pero puedes hacerlo con una combinación de VBScript y script por lotes.

Este VBScript imprimirá un retroceso, luego es un argumento:

WScript.StdOut.Write(chr(8) & WScript.Arguments(0))

Coloque esto en un archivo, vbsEcho.vbs , luego llame a este script desde su secuencia de comandos por lotes. El siguiente script por lotes seguirá mostrando el spinner hasta que presione CTRL-C:

@echo off :LOOP cscript //nologo vbsEcho.vbs "/" cscript //nologo vbsEcho.vbs "|" cscript //nologo vbsEcho.vbs "/" cscript //nologo vbsEcho.vbs "-" goto :LOOP

EDITAR: Usando algunas de las ideas de la respuesta de aphoria, este script iniciará la calculadora de Windows y mostrará un spinner hasta que la calculadora se cierre:

@ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION SET COUNT=1 START CALC cscript //nologo vbsEcho.vbs "Calculating: /" :LOOP IF !COUNT! EQU 1 cscript //nologo vbsEcho.vbs "|" IF !COUNT! EQU 2 cscript //nologo vbsEcho.vbs "/" IF !COUNT! EQU 3 cscript //nologo vbsEcho.vbs "-" IF !COUNT! EQU 4 ( cscript //nologo vbsEcho.vbs "/" set COUNT=1 ) else ( set /a COUNT+=1 ) pslist CALC >nul 2>&1 if %ERRORLEVEL% EQU 1 goto :end goto :LOOP :END cscript //nologo vbsEcho.vbs ". Done."


El spinner PUEDE hacerse en secuencia de comandos por lotes, solo necesita algunas variables:

@echo off :spinner set mSpinner=%mSpinner%. if %mSpinner%''==..............................'' set mSpinner=. cls echo %mSpinner% rem Check if the process has finished via WMIC and/or tasklist. goto spinner :exit

Para que el BAT mismo detecte un proceso que se ejecuta / sale. Puede hacerlo a través de la interfaz de la línea de comandos de WMI o del comando de la lista de tareas del cual tengo conocimiento limitado.

Si estuviese de vuelta en los días de DOS, incluso podría hacerlo sin borrar la pantalla ... salvo usar una combinación de caracteres de escape. No sé si todavía es posible en Vista / XP.


: LOOP ECHOX -n "~ r% Processing ..." IF% CTR% EQU 4 SET / A CTR = 0 IF% CTR% == 0 (set / p DOT = ³)


Encuentro que la manera más fácil es actualizar el título, de esa manera no tienes que hacer un CLS todo el tiempo.

El motivo de las dos líneas de ping -n es que es más rápido hacer un doble ping de un segundo cada una, en comparación con un único ping de dos segundos.

Además, para aquellos que no saben, a :: es lo mismo que un REM, excepto que los comentarios se ignoran al comienzo del analizador sintáctico (creo que esta es la palabra correcta) en lugar de al final. En pocas palabras, esa línea se ignora.

:: begin spin.cmd @echo off setlocal set COUNT=0 set MAXCOUNT=10 set SECONDS=1 :LOOP title "/" call :WAIT title "|" call :WAIT title "/" call :WAIT title "-" if /i "%COUNT%" equ "%MAXCOUNT%" goto :EXIT set /a count+=1 echo %COUNT% goto :LOOP :WAIT ping -n %SECONDS% 127.0.0.1 > nul ping -n %SECONDS% 127.0.0.1 > nul goto :EOF :EXIT title FIN! endlocal :: end spin.cmd


paxdiablos tiene una respuesta increíble, pero tener que hacer eco de tus comandos en un archivo de carga útil es molesto. Es difícil de leer y difícil de depurar. Tomé su código y lo modifiqué un poco para mi propio uso:

@echo off :: Localise environment. setlocal enableextensions enabledelayedexpansion set wkdir=%~dp0% set wkdir=%wkdir:~0,-1% set done_flag="%wkdir%/tmp_payload.flg" set timeout=7 :controller IF (%1)==() ( call :monitor step1 "Getting stuff from SourceSafe: " call :monitor step2 "Compiling some PHP stuff: " call :monitor step3 "Finishing up the rest: " ) ELSE ( goto %1 ) goto final :step1 ::ping for 5 seconds ping 127.0.0.1 -n 6 >nul del "%wkdir%/tmp_payload.flg" goto final :step2 ::ping for 10 seconds ping 127.0.0.1 -n 11 >nul del "%wkdir%/tmp_payload.flg" goto final :step3 ::ping for 5 seconds ping 127.0.0.1 -n 6 >nul del "%wkdir%/tmp_payload.flg" goto final :monitor :: Create flag file and start the payload minimized. :: echo the word "dummy" to the flag file (second parameter) echo >>%done_flag% dummy :: start the command defined in the first parameter start /min cmd.exe /c "test2.bat %1" :: Start monitoring. :: i is the indicator (0=|,1=/,2=-,3=/). :: m is the number of seconds left before timeout. set i=0 set m=%timeout% set str=%2 for /f "useback tokens=*" %%a in (''%str%'') do set str=%%~a <nul (set /p z=%str%^|) :: Loop here awaiting completion. :loop :: Wait one second. ping 127.0.0.1 -n 2 >nul :: Update counters and output progress indicator. set /a "i = i + 1" set /a "m = m - 1" if %i% equ 4 set i=0 if %i% equ 0 <nul (set /p z=^|) if %i% equ 1 <nul (set /p z=/) if %i% equ 2 <nul (set /p z=-) if %i% equ 3 <nul (set /p z=/) :: End conditions, complete or timeout. if not exist %done_flag% ( ::echo. echo Complete goto :final ) if %m% leq 0 ( echo. echo. *** ERROR: Timed-out waiting for child. goto :final ) goto :loop :final endlocal


Prueba esto:

@ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION CALL :BACKSPACE $BS SET /A FULL_COUNT=60 SET /A MAX_COUNT=160 SET /A Spin_Delay=50 SET "_MSG=Process running..." SET /A CTR=0 SET /A TCT=0 IF NOT [%1]==[] SET _MSG=%~1 IF NOT [%2]==[] SET /A FULL_COUNT=%2 IF NOT [%3]==[] SET /A SPIN_DELAY=%3 IF %FULL_COUNT% GTR %MAX_COUNT% SET FULL_COUNT=%MAX_COUNT% (SET/P=%_MSG%*)<nul FOR /L %%A IN (1,1,%FULL_COUNT%) DO ( CALL :DELAY %SPIN_DELAY% IF !CTR! EQU 0 (set/p=%$BS%³)<nul IF !CTR! EQU 1 (set/p=%$BS%/)<nul IF !CTR! EQU 2 (set/p=%$BS%Ä)<nul IF !CTR! EQU 3 (set/p=%$BS%/)<nul SET /A CTR=%%A %% 4 ) (SET/P=%$BS%*)<nul ENDLOCAL & EXIT /B %CTR% :BackSpace setlocal for /f %%a in (''"prompt $H$S &echo on &for %%b in (1) do rem"'') do set "Bs=%%a" endlocal&call set %~1=%BS%&exit /b 0 :Delay msec setlocal enableextensions set/a correct=0 set/a msecs=%1+5 if /i %msecs% leq 20 set /a correct-=2 set time1=%time: =% set/a tsecs=%1/1000 2>nul set/a msecs=(%msecs% %% 1000)/10 for /f "tokens=1-4 delims=:." %%a in ("%time1%") do ( set hour1=%%a&set min1=%%b&set sec1=%%c&set "mil1=%%d" ) if /i %hour1:~0,1% equ 0 if /i "%hour1:~1%" neq "" set hour1=%hour1:~1% if /i %min1:~0,1% equ 0 set min1=%min1:~1% if /i %sec1:~0,1% equ 0 set sec1=%sec1:~1% if /i %mil1:~0,1% equ 0 set mil1=%mil1:~1% set/a sec1+=(%hour1%*3600)+(%min1%*60) set/a msecs+=%mil1% set/a tsecs+=(%sec1%+%msecs%/100) set/a msecs=%msecs% %% 100 :: check for midnight crossing if /i %tsecs% geq 86400 set /a tsecs-=86400 set/a hour2=%tsecs% / 3600 set/a min2=(%tsecs%-(%hour2%*3600)) / 60 set/a sec2=(%tsecs%-(%hour2%*3600)) %% 60 set/a err=%msecs% if /i %msecs% neq 0 set /a msecs+=%correct% if /i 1%msecs% lss 20 set msecs=0%msecs% if /i 1%min2% lss 20 set min2=0%min2% if /i 1%sec2% lss 20 set sec2=0%sec2% set time2=%hour2%:%min2%:%sec2%.%msecs% :wait set timen=%time: =% if /i %timen% geq %time2% goto :end goto :wait :end for /f "tokens=2 delims=." %%a in ("%timen%") do set num=%%a if /i %num:~0,1% equ 0 set num=%num:~1% set/a err=(%num%-%err%)*10 endlocal&exit /b %err%


Esta rutina examina el resultado de la lista de tareas para un proceso que START desde cmd.
Pase el nombre del exe como parámetro, por ejemplo
llamada: spinner calc.exe
Informa
Transcurrido: 001 segundos
e incrementa segundos hasta que el proceso exe finaliza.
El mensaje transcurrido de 001 segundos se sobrescribe cada segundo por ECHO.exe -n / r
que echos un cr sin una alimentación de línea.
Echo.exe está disponible en http://www.paulsadowski.com/wsh/cmdprogs.htm

@echo off start calc call :spinner calc.exe pause :spinner SET COUNT=1 :BEGIN set "formattedValue=000000%count%" ECHO.exe -n Elapsed: %formattedValue:~-3% seconds ECHO.exe -n /r %= -n (suppress crlf) /r output a cr =% SET /A COUNT+=1 set EXE=%1 %= search output of tasklist for EXE =% set tl=tasklist /NH /FI "IMAGENAME eq %EXE%" FOR /F %%x IN (''%tl%'') DO IF %%x == %EXE% goto FOUND set result=0 goto FIN :FOUND set result=1 :FIN IF %result% EQU 0 GOTO END PING -n 2 127.0.0.1 > nul %= wait for about 1 second =% GOTO BEGIN :END


iniciar la aplicación, esperar a la carga

@echo off & setlocal enabledelayedexpansion start application.exe :1 for %%a in (^| ^/ ^- ^/ ^| ^/ ^- ^/) do ( for %%b in (^| ^/ ^- ^/ ^| ^/ ^- ^/) do ( for %%c in (^| ^/ ^- ^/ ^| ^/ ^- ^/) do ( cls &echo processing..%%c%%b%%a sleep -m 20 IF EXIST "result file" (exit) ))) goto 1