How to make bat file listing with options to choose - windows

I want to make a bat file that list all of the files in a specific directory, and add numbers at the beginning of the every one of the listed items. This numbers need to be a selectable options.
Example:
I have a folder with 5 files in it, aaa.exe, bbb.exe, ccc.exe, ddd.exe, eee.exe. When i run bat file i need to see
aaa.exe
bbb.exe
ccc.exe
ddd.exe
eee.exe
So now if i wana run 5-th exe i need to press 5, than press enter and that 5th exe will now start.
I allredy find how to list all of the items in folder with this code
REM -start "c:\windows\system32" notepad.exe
for /r %%i in (*) do echo %%i
pause
exit
but i can't figure out how to add numbers in front of the text and make that numbers to be a selectable options.
Edit---
Now im getting
ERROR: Duplicate choices are not allowed. running '""' is not
recognized as an internal or external command, operable program or
batch file.
when i'm trying to run this loop for a second time.
This is code that i wrote:
#ECHO OFF
setlocal enabledelayedexpansion
REM ---Prompt part
:choise
SET /P AREYOUSURE=Install programs (Y/[N])?
IF /I "%AREYOUSURE%" EQU "Y" GOTO :chooseInstall
IF /I "%AREYOUSURE%" EQU "N" GOTO :nope
REM --Cheking for Y or N
GOTO :choise
:nope
echo "Ok. Have a nice daty / night"
pause
exit
:chooseInstall
echo Wich program do you wana install ?
echo.
echo 1. 7Zip
echo 2. CPU Z
echo.
SET /P AREYOUSURE=Choosing:
IF /I "%AREYOUSURE%" EQU "1" set "pathToSoft=C:\Users\usr\Desktop\hello"
IF /I "%AREYOUSURE%" EQU "2" set "pathToSoft=C:\Users\usr\Desktop\bye"
echo.
echo.
echo %pathToSoft%
echo.
echo.
REM ---Installs
echo "Wich file to install"
cd %pathToSoft%
echo.
echo.
REM --Loops that scan files
set /A counter=0
for /R %%i in (*) do (
if not "%%~nxi" == "%~nx0" (
set /A counter+=1
echo !counter!: %%~nxi
set exe[!counter!]=%%i
set choice=!choice!!counter!
)
)
if %counter% LSS 10 (
choice /C %choice% /M "Choose: "
set EXENUM=!ERRORLEVEL!
) else set /P EXENUM="enter exe number: "
set EXECUTABLE=!exe[%EXENUM%]!
echo running %EXECUTABLE%
call "%EXECUTABLE%"
echo.
echo.
echo.
:installmore
SET /P INSTALLMORE=Do you wana install somthing else (Y/[N])?
IF /I "%INSTALLMORE%" EQU "Y" GOTO :chooseInstall
IF /I "%INSTALLMORE%" EQU "N" GOTO :nope

count the executables and associate them with the counter, creating kind of "array" variables (filter out the current batch script)
build the choice list at the same time
after the loop, use choice if no more than 9 choices, else use a classical interactive set
retrieve the user selection and call the executable/batch file
(you have to enable delayedexpansion to be able to use % and ! env. var separators & instant evaluation within the loop)
can be done like this:
#echo off
setlocal enabledelayedexpansion
set /A counter=0
set choice=
for /R %%i in (*) do (
if not "%%~nxi" == "%~nx0" (
set /A counter+=1
echo !counter!: %%~nxi
set exe[!counter!]=%%i
set choice=!choice!!counter!
)
)
if %counter% LSS 10 (
choice /C %choice% /M "type exe number"
set EXENUM=!ERRORLEVEL!
) else set /P EXENUM="enter exe number: "
set EXECUTABLE=!exe[%EXENUM%]!
echo running %EXECUTABLE%
call "%EXECUTABLE%"

Related

Batch File to execute all .exe in a folder with count

I have quite a few exe files, I want to run them with a single batch file. As far as I understand, these two codes work for me;
for %%a in ("\*.exe") do start "" "%%\~fa"
for %%i in (\*.exe) do start "" /b "%%i"
But that cmd screen closes when all files are run. What I want is this: That cmd screen will not close when the process is finished and will show me the result (counting if possible), a code that can count how many of these .exe files work and how many fail.
So for example;
87 files blocked
13 files could not be blocked
Something like this? Is this possible?
Maybe you can get an inspiration from this batch below. It works through program exit code. It spawns all executable, wait for their completion, then count how much failed / succeeded.
It should also work with well-designed GUI program, not only command-line based ones.
It's a rough/basic answer, you may need to refine it according to your exact needs.
#echo off
setlocal enableextensions enabledelayedexpansion
REM Use marker files for getting results.
set OK_EXT=.SUCCESS
set FAIL_EXT=.FAILURE
REM Purge all possible marker files.
del /q *!OK_EXT! *!FAIL_EXT! > NUL 2>&1
set /a count=0
REM Parse all executables
for %%E in (*.exe) do (
echo Launching: %%~nxE
REM Create two marker files for each executable.
echo.>%%~nE!OK_EXT!
echo.>%%~nE!FAIL_EXT!
REM Start the executable, delete the WRONG marker.
REM I would have prefered to use "touch" to create the good one instead, but not standard on Windows.
start %comspec% /C "%%~nxE && ( del /q %%~nE!FAIL_EXT! ) || ( del /q %%~nE!OK_EXT! )"
set /a count +=1
)
REM Now, "count" contains the number of executables launched.
echo All processes launched.
echo.
:loop
echo Waiting for results...
set /a curr=0
REM Simply count the number of marker files. Must be equal to "count" when everything is finished.
for /F "usebackq tokens=*" %%C in (`dir /b *!OK_EXT! *!FAIL_EXT!`) do (
set /A curr+=1
)
if !curr! GTR !count! (
set /a curr-=!count!
echo Still !curr! processes running...
timeout /t 2
goto :loop
)
echo All results found.
echo.
echo Parsing results...
set /a ok_exe=0
set ok_exe_list=
set /a fail_exe=0
set fail_exe_list=
REM Parse all marker files.
for /F "usebackq tokens=*" %%C in (`dir /b *!OK_EXT! *!FAIL_EXT!`) do (
REM And set counters + list according to the marker file type (OK or FAILED).
if /I "%%~xC"=="!OK_EXT!" (
set /A ok_exe+=1
set ok_exe_list=!ok_exe_list! %%~nC
) else (
set /A fail_exe+=1
set fail_exe_list=!fail_exe_list! %%~nC
)
)
REM Simple display.
echo Programs without error: !ok_exe!/!count!
echo !ok_exe_list!
echo.
echo Programs with error: !fail_exe!/!count!
echo !fail_exe_list!
echo.
goto :eof

Issue with "findstr" using Batch

Below, I wrote some code. It detects if a Micro-SD card is inserted into the computer and if so, it will ask to enter your pin. After you enter the pin, it will look through the card for a text file that contains a list of pins.
:start
cls
echo.
echo.
if exist E:\ (
goto enterPin
) else (
echo INSERT YOUR CARD
)
timeout 1 >nul
goto start
:enterPin
echo Enter Account Pin: %chip%
set /p pin=": "
:: Finding the specified pin
findstr /m "%pin%" E:\Chip\CardInfo.txt >Nul
if %errorlevel%==0 (
echo Pin "%pin%" is valid
timeout 1 >nul
goto account
)
if %errorlevel%==1 (
echo Pin "%pin%" is invalid
pause
goto start
)
:account
cls
:: Finds the name of the account owner and continues
setlocal enableextensions disabledelayedexpansion
for /F "tokens=2 delims=/" %%a in ('findstr /I "%pin%/" E:\Chip\CardInfo.txt') do set "user=%%a"
for /F "tokens=3 delims=/" %%b in ('findstr /I "%pin%/%user%/" E:\Chip\CardInfo.txt') do set "balance=%%b"
echo.
echo.
echo Welcome, %user%.
echo.
echo ACCOUNT BALANCE: $%balance%
echo.
echo 1=Deposit / 2=Withdraw / 3=Exit / 4=Refresh
choice /c 1234 >nul
if %ERRORLEVEL% EQU 1 goto deposit
if %ERRORLEVEL% EQU 2 goto withdraw
if %ERRORLEVEL% EQU 3 exit
if %ERRORLEVEL% EQU 4 goto account
:deposit
echo.
echo.
set /p add="Money to Deposit: "
set /a moneytoadd=%balance%+%add%
call jrepl "%pin%/%user%/%balance%" "%pin%/%user%/%moneytoadd%" /f E:\Chip\CardInfo.txt /o -
goto account
:withdraw
echo.
echo.
set /p sub="Money to Withdraw: "
set /a moneytosub=%balance%-%sub%
call jrepl "%pin%/%user%/%balance%" "%pin%/%user%/%moneytosub%" /f
E:\Chip\CardInfo.txt /o -
goto account
endlocal
Here's when the issue comes in. A pin consists of 4 numeric characters (ex. 1234), but if there's two pins with the same characters (ex. 1234, 6543), it will say the pin is valid. So for example, if I type 4, it will just look for just the number 4 in the file. And will say the pin is valid. Even though, just the number 4 is not an existing pin. My guess is that it's a flaw with "findstr". But I'm not sure.
Contents of "CardInfo.txt":
1234/Test User/1000
6543/Another Test User/2000
use REGEX (using <StartOfLine><PIN></>):
findstr /m "^%pin%/" E:\Chip\CardInfo.txt >Nul
where ^ is "Start of Line".
Here is what exactly does what you want:
#echo off
::add your path below
for /f %%a in (file.txt) do (
call :funch %%a
)
:funch
set input=%1
set "modifiedinput=%input:~0,4%"
set /p pin=Enter Account Pin:
if %modifiedinput% equ %pin% ( goto authentication_passed) else ( goto authentication_failed)
:authentication_passed
echo auth passed
rem your code
pause >nul
exit
:authentication_failed
echo auth failed
goto funch
it will read the input from file and then extract first four characters which in your case is the pin.
I rewrote the entire batch file to be more fail safe on execution:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem endlocal is executed implicitly by cmd.exe on exiting batch file processing.
:Begin
cls
echo\
echo\
if exist E:\ goto enterPin
echo INSERT YOUR CARD
%SystemRoot%\System32\timeout.exe /T 1 >nul
goto Begin
:enterPin
set "pin="
set /p pin="Enter account pin for %chip%: "
if not defined pin goto enterPin
set "pin=%pin:"=%"
if not defined pin goto enterPin
for /F delims^=01234567890^ eol^= %%I in ("%pin%") do goto enterPin
rem Finding the specified pin.
%SystemRoot%\System32\findstr.exe /B /L /M /C:"%pin%/" E:\Chip\CardInfo.txt >Nul
if errorlevel 1 (
echo Pin "%pin%" is invalid.
pause
goto Begin
)
echo Pin "%pin%" is valid.
%SystemRoot%\System32\timeout.exe /T 1 >nul
:account
cls
rem Finds the name of the account owner and continues
for /F "tokens=2,3 delims=/" %%I in ('%SystemRoot%\System32\findstr.exe /B /L /C:"%pin%/" E:\Chip\CardInfo.txt') do set "user=%%I" & set "balance=%%J"
echo/
echo/
echo Welcome, %user%.
echo/
echo ACCOUNT BALANCE: $%balance%
echo/
echo 1=Deposit / 2=Withdraw / 3=Exit / 4=Refresh
%SystemRoot%\System32\choice.exe /c 1234 >nul
if not errorlevel 1 goto account
if errorlevel 4 goto account
if errorlevel 3 exit /B
if errorlevel 2 goto withdraw
:deposit
echo/
echo/
set "add="
set /P "add=Money to deposit: "
set /A moneytoadd=balance + add
call "%~dp0jrepl.bat" "%pin%/%user%/%balance%" "%pin%/%user%/%moneytoadd%" /L /f E:\Chip\CardInfo.txt /o -
goto account
:withdraw
echo/
echo/
set "sub="
set /P "sub=Money to withdraw: "
set /A moneytosub=balance - sub
call "%dp0jrepl.bat" "%pin%/%user%/%balance%" "%pin%/%user%/%moneytosub%" /L /f E:\Chip\CardInfo.txt /o -
goto account
Issues fixed with this code:
There is the command START. For that reason it is not advisable to use the string start as label although it is possible.
It is advisable to avoid an IF (...) ELSE (...) condition if a simple IF condition with GOTO can be used too.
The usage of full qualified file names wherever possible avoids a batch file not running as expected on environment variables PATH (too often) or PATHEXT (rarely) are corrupted on the userĀ“s machine.
A user has the freedom to enter on a prompt done with set /P really anything from nothing to something resulting in further processing in a syntax error with an immediate exit of batch file execution on code not being prepared for any user input. For that reason the first set /P prompt is improved and validates if the user entered a string consisting only of digits.
The usage of FINDSTR is done with additional options to find the pin only at beginning of a line case-sensitive with a literal search and the next character must be a slash character.
The recommended syntax for ERRORLEVEL evaluation is used in the code.
The arithmetic expressions are written using the recommended syntax to work even if the user enters nothing or a string which cannot be converted to an integer number at all.
The command EXIT is used with option /B to just exit the processing of the batch file and not the entire command process.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
choice /?
cls /?
echo /?
findstr /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
timeout /?
Useful pages regarding to the improvements on code:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
Syntax error in one of two almost-identical batch scripts: ")" cannot be processed syntactically here
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/
Single line with multiple commands using Windows batch file
Safe number comparison in Windows batch file

Batch: How to scroll through files to read to a variable?

I'm trying to have it scroll through a directory and present a new variable when the user replies "N". I have it all figured out except how to go to the next variable.
cd "C:\Test"
for /r %%F in (*) do SET Show=%%~NF
echo %Show%
echo.
SET /P Continue=Continue?(Y/N)
if /I "%Continue%" EQU "y" goto :Run
if /I "%Continue%" EQU "n" goto :Start
If you're looking to scroll the directory and prompt the user the file name and have them choose to choose it or continue, then bellow should help you.
Firstly, we can use dir /b /a:d to display only directories (folders) in the the current directory. By using a code block ( & ) we can put batch script inside the for loop. For your sake, we can use the CHOICE command to prompt to continue the loop or to save current folder to string and do something with it.
ScrollTreeWithPrompt.bat:
#echo off
setlocal EnableDelayedExpansion
Rem | Configuration
Set "MainDir=C:\Test"
Rem | Get Each Project Folder
for /f "tokens=*" %%A in ('dir "!MainDir!\" /b /a:d') do (
Cls
Echo Current Folder: %%A
echo(
CHOICE /M "Continue?"
Rem | Check for "N" - If so Set String & goto
IF "!ERRORLEVEL!"=="2" (
Set "Choice=%%A"
GOTO Run
)
)
Rem | No Further Results
Cls
Echo Warning: No further folders found.
pause>NUL
goto :EOF
:Run
Cls
echo Currently selected: !MainDir!\!Choice!
pause>NUL
goto :EOF
I have left a few Rem comments in the script to help you along. For any more help on the commands, type the following into a command prompt:
choice /?
set /?
for /?
goto /?
Is this what you need:
For /R "C:\Test" %%A In (*) Do (Choice /M "%%~nA"
If Not ErrorLevel 2 (Set "Show=%%~nA" & GoTo Run))
Exit /B
:Run
Echo Running against %Show%
Pause
Alternatively, should you wish to return to the loop after running against the file name, then use Call instead of GoTo:
For /R "C:\Test" %%A In (*) Do (Choice /M "%%~nA"
If Not ErrorLevel 2 Call :Run "%%~nA")
Exit /B
:Run
Set "Show=%~1"
Echo Running against %Show%
Pause

using for loop and windows tasklist cmd i am trying to open several programs from a batch file which are not already running

My code below doesn't work
echo will now go ahead and load the essential programs needed for
project: %project%
set "programlistopen=sublime_text.exe xampp-control.exe"
for /f "delims=" %%j in (%programlistopen%) do (
if %%j=="sublime_text"(set pathtopen=%defaultpath%\Sublime_Text&&set
dirpath="%workdirectory%\%project%") else
if %%j=="xampp-control.exe"(set pathtopen=%xampp%\&&set dirpath=)
tasklist /FI "IMAGENAME eq %%j" 2>NUL | find /I /N "%%j">NUL
if "%ERRORLEVEL%"=="1" goto notstartedsublimetext
if "%ERRORLEVEL%"=="0" goto startedsublimetext
:notstartedsublimetext
Echo started %%j at %time%
pause
start /d "%pathtopen%" %%j %dirpath%
:startedsublimetext
echo %%j is already running......
)
I would suggest possibly changing the structure to this:
#Echo Off
For %%A In ("C:\Program Files\SomeName\madeup.exe"
"C:\Users\Vibrations\Portables\Some Name\dummy.exe"
"C:\Windows\built-in.exe"
) Do TaskList|FindStr/BRIC:"%%~nxA\>">Nul&&(Echo %%~nxA already running
)||(Start "" "%%~A"&Echo Started %%~nxA at %TIME%)
Pause
Just list the full paths to the executables you want to check/start similarly to the three I've used as an example
Edit
As a result of the latest comment, here is an example of what I assume you're trying to do by way of your modification, (replace from line 6):
)||(If "%%~nxA"=="sublime_text.exe" (Start "" "%%~A" "%workdirectory%\%project%"
) Else Start "" "%%~A"
Echo Started %%~nxA at %TIME%)
Pause
#echo off
setlocal
#rem Variables to be set.
#rem changedir is an optional pushd on each call of :notstarted.
#rem startdir is passed to the /d argument in the start command.
#rem programpath is the path to the program executable.
#rem args are any arguments to pass to the program executable.
#rem Variables are undefined at start of loop.
echo will now go ahead and load the essential programs needed for project: %project%
set "programlistopen=wordpad.exe notepad.exe"
for %%j in (%programlistopen%) do (
for %%B in (changedir startdir programpath args) do set "%%~B="
if "%%~j" == "wordpad.exe" (
set "changedir=%userprofile%"
set "startdir=%cd%"
set "programpath=C:\Program Files\Windows NT\Accessories"
) else if "%%~j" == "notepad.exe" (
rem Nothing to set. Just start notepad.exe.
)
tasklist /FI "IMAGENAME eq %%~j" 2>NUL | find /I /N "%%~j" >NUL
if errorlevel 1 (
call :notstarted "%%~j"
) else call :started "%%~j"
)
exit /b
:notstarted
setlocal
echo started "%~1" at %time%
set "cli=start """
if defined startdir set "cli=%cli% /d "%startdir%""
if defined programpath (
set "cli=%cli% "%programpath%\%~1""
) else set "cli=%cli% "%~1""
if defined args set "cli=%cli% %args%"
if defined changedir pushd "%changedir%"
echo %cli%
%cli%
if defined changedir popd
exit /b
:started
echo "%%~1" is already running......
exit /b
Your code has many unknowns so I have done an example which you
can adapt to your needs.
I chose some simple programs like notepad and wordpad to test with.
Variables for use are commented at the top of the script. These
variables are undefined at start of each loop so you do not need
to undefined them and just use the variables that you want to set
with each program.
The errorlevel of tasklist is checked and will call the name of
the label required. This allows the call to return back to the
position of the caller so the loop can continue.
The :notstarted label will bulid the command line (cli) with
each of the defined variables that are relevent to the cli. The
optional pushd and popd was added just for an unusual use.

Use a Batch File to list files and allow the user to select which file to pass to an executable

I have a batch file that will display all files in a folder and allow the user to select a file by number and pass it to an executable. Everything works, however, I am trying to make this a click-and-forget type of batch file. In other words, I would also like the user to be able to select a number that would pass all files, one at a time, to said executable. My current code is as follows:
#ECHO OFF
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%f IN (*.txt) DO (
SET file!index!=%%f
ECHO !index! - %%f
SET /A index=!index!+1
)
SETLOCAL DISABLEDELAYEDEXPANSION
SET /P selection="select file by number:"
SET file%selection% >nul 2>&1
IF ERRORLEVEL 1 (
ECHO invalid number selected
EXIT /B 1
)
CALL :RESOLVE %%file%selection%%%
CSCRIPT //NoLogo //B C:\FCLoader\sendkeys.vbs
Z:\executable.exe %file_name%
GOTO :EOF
:RESOLVE
SET file_name=%1
GOTO :EOF
The CSCRIPT line is there to pass keystrokes from a vbs file to enter username, password, and a database name to the executable. This works fine. The executable works fine too if I just want to run it once against one file. Below is an example of what the batch looks like after running:
1 - file.txt
2 - file2.txt
3 - file3.txt
select file by number:
What I would like is for it to look like this:
1 - file.txt
2 - file2.txt
3 - file3.txt
4 - All
select file by number:
I would like for the user to be able to select 4 - All, and have it run the executable for every file, one at a time. When the first run through completes, it will call the executable again and so on...It will also need to run the vbs script before the executable is run in order for the credentials to be passed as stated above.
I have used the extent of my knowledge in Batch Files and now need help.
Try this code:
#ECHO OFF
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%f IN (*.*) DO (
SET file!index!=%%f
ECHO !index! - %%f
SET /A index=!index!+1
)
echo/!Index! - All
SETLOCAL DISABLEDELAYEDEXPANSION
SET /P selection="select file by number: "
if "%selection%" equ "%index%" goto allFiles
SET file%selection% >nul 2>&1
IF ERRORLEVEL 1 (
ECHO invalid number selected
EXIT /B 1
)
CALL :RESOLVE %%file%selection%%%
CSCRIPT //NoLogo //B C:\FCLoader\sendkeys.vbs
Z:\executable.exe "%file_name%"
GOTO :EOF
:RESOLVE
SET file_name=%1
GOTO :EOF
:allFiles
FOR %%f IN (*.txt) DO (
CSCRIPT //NoLogo //B C:\FCLoader\sendkeys.vbs
Z:\executable.exe "%%f"
)
goto :EOF
Pick a file from a numbered list 1 to [a lot]!
This uses the choice command if less than 10 files (max files > 9999?? untested)
Files are numbered starting at 1 (not 0) - so 1-9.
Choice has timeout and default - but if more than 9 files no timeout
If more than 9 files and user presses ENTER key it uses the default value
Files are listed in date/time order - most recent first
A path and wildcard filter (* or ?) can be set for the dir command.
It could be adapted to run ALL as requested?
#echo off
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
mode con: cols=185 lines=90
COLOR 1F
set MYPATH="G:\Downloads\*.iso"
set DEFAULT=1
set TIMEOUT=3
:GETISO
echo.
echo ISO FILES IN %MYPATH%
echo.
set count=1
set choose=
for /f "tokens=*" %%i in ('dir %MYPATH% /b/a-d/od/t:c') do (echo !count! %%i & set choose=!choose!!count!& set /A count=!count!+1)
echo.
set /a count=%count%-1
if %count%==0 echo NO FILES FOUND! & goto :EOF
if %count% LSS 10 CHOICE /C "%choose%" /N /M "SELECT DESIRED ISO (1-%count%) : " /T %TIMEOUT% /D %DEFAULT%
if %count% LSS 10 set /A ask=%errorlevel%+0
if %count% GEQ 10 (
set ask=%DEFAULT%
set /P ask="SELECT DESIRED ISO (1-%count%) : "
set /A ask=%ask+0
)
if "%ask%"=="" echo INPUT ERROR! & goto :GETISO
if "%ask%"=="0" echo INPUT ERROR! & goto :GETISO
if %ask% GTR %count% echo ERROR - NUMBER TO BIG! & goto :GETISO
set count=1
for /f "tokens=*" %%i in ('dir %MYPATH% /b/a-d/od/t:c') do (
if !count!==%ask% set FILE=%%i
set /A count=!count!+1
)
echo.
echo FILE=%ask% %FILE%

Resources