Spinner until process is finished

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Matt Williamson
Posts: 82
Joined: 30 Dec 2013 10:16
Location: United States by the big waterfall

Spinner until process is finished

#1 Post by Matt Williamson » 12 Mar 2015 13:11

I'm trying to get a busy spinner to run for the duration of a program installation process but the following code should demonstrate what I'm trying to do. I'm missing something simple but I can't figure out what.

Code: Select all

   @echo off
   setlocal

   start "" notepad.exe
   call :Spinner notepad.exe
   ping localhost -n 10>nul
   taskkill /IM notepad.exe
   exit /b

   :Spinner
   @echo off
   setlocal EnableDelayedExpansion
   for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

   for /f %%a in ('tasklist /V /FI "Imagename eq %~1" /FO CSV /NH^|find /i "%~1"') do (
         if not errorlevel 1 (
            set /a "spinner=(spinner + 1) %% 4"
            set "spinChars=\|/-"
            <nul set /p ".=Please wait.. !spinChars:~%spinner%,1!!CR!"
            ping localhost -n 1 > nul
         )   
   )
   exit /b

Squashman
Expert
Posts: 4488
Joined: 23 Dec 2011 13:59

Re: Spinner until process is finished

#2 Post by Squashman » 12 Mar 2015 13:34

You are inside a code block. You can't do variable expansion like that.

aGerman
Expert
Posts: 4743
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Spinner until process is finished

#3 Post by aGerman » 12 Mar 2015 16:05

Squashman is right. You can use an additional loop to expand the spinner variable. Although this is not sufficient in your case because you also have to run the spinner asynchronously. Otherwise your 10 second delay will not be executed before Notepad was closed manually.
Try

Code: Select all

@echo off &setlocal
if /i "%~1"=="Spinner" call :Spinner %2

start "" notepad.exe
start "" /b cmd /c "%~fs0 Spinner notepad.exe"
>nul ping -n 10 localhost
taskkill /IM notepad.exe
exit /b

:Spinner
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z %~fs0 nul') do set "CR=%%a"
set "spinChars=\|/-"
set /a "spinner=0"
for /l %%i in () do (
  tasklist /nh /fi "imagename eq %~1" | >nul findstr /bic:"%~1 "
  if errorlevel 1 exit
  set /a "spinner=(spinner + 1) %% 4"
  for %%j in (!spinner!) do <nul set /p "=Please wait... !spinChars:~%%j,1!!CR!"
)

Regards
aGerman

Matt Williamson
Posts: 82
Joined: 30 Dec 2013 10:16
Location: United States by the big waterfall

Re: Spinner until process is finished

#4 Post by Matt Williamson » 13 Mar 2015 05:56

Thank you very much aGerman. This is better but it causes an annoying screen flash on each iteration of the loop. At least on this XP pro box I'm stuck with for a few more weeks. Is there any way around that? I was thinking of moving the code outside of the code block how squashman suggested. Kind of like this:

Code: Select all

@echo off
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set "exe=notepad.exe"
start "" %exe%
for /f %%a in (
   'tasklist /V /FI "Imagename eq %exe%" /FO CSV /NH^|find /i "%exe%"') do (
   if not errorlevel 1
   call :Spinner %exe%
   ping localhost -n 10>nul
   taskkill /IM %exe%
)

exit /b

:Spinner
set /a "spinner=(spinner + 1) %% 4"
set "spinChars=\|/-"
<nul set /p ".=Please wait.. !spinChars:~%spinner%,1!!CR!"
ping localhost -n 1 > nul
exit /b


but this isn't working either.

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: Spinner until process is finished

#5 Post by carlos » 13 Mar 2015 07:08

see this:

Code: Select all

@echo off
if "%~1" equ "start_spinner" Goto :Spinner
setlocal EnableDelayedExpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set "exe=notepad.exe"
start "" %exe% 2>nul
if not errorlevel 1 (
set /a "spinner=0"
set /a "spinner_cnt=0"
call :spinner
taskkill /IM "%exe%" >nul 2>&1
)

exit /b

:Spinner
set /a "spinner=(spinner + 1) %% 4"
set "spinChars=\|/-"
<nul set /p ".=Please wait.. !spinChars:~%spinner%,1!!CR!"
ping -l 0 -n 1 -w 1000 1.0.0.0 >nul
set /a "spinner_cnt+=1"
if %spinner_cnt% lss 10  goto :Spinner
exit /b


Matt Williamson
Posts: 82
Joined: 30 Dec 2013 10:16
Location: United States by the big waterfall

Re: Spinner until process is finished

#6 Post by Matt Williamson » 13 Mar 2015 07:37

Hi Carlos. Thank you for your reply. This code works the way I want it to but the spinner is slow. Is there any way to speed it up a bit? I tried changing nearly all of the values in the ping and the loop but to no avail. It could just be my computer too. How does it run for you? Thank you very much!

-Matt

Matt Williamson
Posts: 82
Joined: 30 Dec 2013 10:16
Location: United States by the big waterfall

Re: Spinner until process is finished

#7 Post by Matt Williamson » 13 Mar 2015 14:30

Aacini answered this on SO. Here is the code.

Code: Select all

@Echo off
setLocal EnableDelayedExpansion

For /f %%a in ('copy /Z "%~dpf0" nul') Do set "CR=%%a"
Set "busy=|/-\"
Set n=0
set "exe=notepad.exe"
start "" %exe%

::BUSY SPINNER
:loop
tasklist /FI "Imagename eq %exe%" /FO CSV /NH 2>NUL | find /i "%exe%" > NUL
if errorlevel 1 goto endProg
   set /A "n=(n+1)%%4"
   set /P "=Calculating !busy:~%n%,1!!CR!" < NUL
   PING -n 1 127.0.0.1 > NUL
goto :Loop

:endProg
echo JRE installed.

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: Spinner until process is finished

#8 Post by carlos » 13 Mar 2015 15:43

see this, i use a file like for signal a event. I coded this quickly, you can review it.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

Set "arg1=%~1"
Set "arg2=%~2"

if "!arg1!" equ "start_spinner" (
  Del /F /Q /A "!Temp!\!event_name!" >Nul 2>&1
  If Defined arg2 Goto :Spinner_Init
)

set "exe=notepad.exe"
start "" %exe% 2>nul

If ErrorLevel 1 (
Echo Error
Exit
)

Set "random="
Set "event_name=%random%.evt"

Start /B "" "%~f0" start_spinner !event_name!

Rem wait 10 seconds
Waitfor.exe /t 10 %random% >nul 2>&1
If ErrorLevel 9009 Ping.exe -l 0 -n 1 -w 10000 1.0.0.0 >nul

taskkill /IM "%exe%" >nul 2>&1

Echo Bye>"!Temp!\!event_name!"

Exit /B

:Spinner_Init
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set "spinChars=\|/-"
set /a "spinner=0"
:Spinner
set /a "spinner=(spinner + 1) %% 4"
<nul set /p ".=Please wait.. !spinChars:~%spinner%,1!!CR!"
If Exist "!Temp!\!arg2!" (
Del /F /Q /A "!Temp!\!arg2!" >Nul 2>&1
Exit
)
Goto :Spinner


carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: Spinner until process is finished

#9 Post by carlos » 13 Mar 2015 16:16

I m thinking and you not need wait the 10 seconds, launch the asynchronus spinner with the start command like my previous code, the launch "%exe%" without start, the code will stop until that process end, the sign the event creating the file in temp folder like my previous code and that will stop the spinner. You dont need ping or waitfor and tasklist.

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: Spinner until process is finished

#10 Post by carlos » 14 Mar 2015 15:09

See this next code, the spinner will stop when notepad is closed.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

Set "arg1=%~1"
Set "arg2=%~2"

if "!arg1!" equ "start_spinner" (
  If Defined arg2 Goto :Spinner_Init
)

Set "random="
Set "event_name=%random%.evt"
Start /B "" "%~f0" start_spinner !event_name!

set "exe=notepad.exe"
"%exe%"
rem stop the spinner
echo Bye>"!Temp!\!event_name!"

Exit /B

:Spinner_Init
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set "spinChars=\|/-"
set /a "spinner=0"
Del /F /Q /A "!Temp!\!arg2!" >Nul 2>&1
:Spinner
set /a "spinner=(spinner + 1) %% 4"
<nul set /p ".=Please wait.. !spinChars:~%spinner%,1!!CR!"
If Exist "!Temp!\!arg2!" (
Del /F /Q /A "!Temp!\!arg2!" >Nul 2>&1
Exit
)
Goto :Spinner


Post Reply