Best way to simulate a CMD prompt from a .bat script - batch-file

So basically, I have a script we use out on the field to do various functions. Part of the script will include a 'Debug Terminal' (For setting and checking variables, running functions directly etc.). I ran into some problems initially with echo and set commands (echo Hi would result in Hi is not recognized..; set would not process).
Here's what I wound up with:
:DebugConsole
%title%Debug Console %end%
:DebugConsoleTop
echo.
echo Enter a command or type 'exit' to finish.
set /p ConsoleInput=
if "%ConsoleInput%"=="exit" (
goto DebugConsoleEnd
)
:if set used
if "%ConsoleInput:~0,3%"=="set" (
echo %ConsoleInput%> "%datapath%\debugcmd.txt"
set /p ConsoleOutput=<"%datapath%\debugcmd.txt"
del /f "%datapath%\debugcmd.txt"
) else (
:if echo
if "%ConsoleInput:~0,4%"=="echo" (
set "echofix=echo echo"
::set ConsoleInput=%ConsoleInput:%echofix%=%
call set ConsoleInput=%%ConsoleInput:echo=%echofix%%%
%ConsoleInput%
goto DebugConsoleTop
)
:all else
FOR /F "delims=" %%i IN ('%ConsoleInput%') DO (
SET ConsoleOutput=%%i
echo %ConsoleOutput%
pause
)
)
%ConsoleOutput%
goto DebugConsoleTop
:DebugConsoleEnd
cls
exit /b
The problem I'm facing now is that you can not echo variables correctly. If I input "set var=test" and then "echo %var%" the output is "%var%" and not "test". However, if I input "%var%" i receive "test is not recognized.."

Related

How to "hide" a text from Batch-File?

I want to know if there any solution to this:
Main.bat:
#echo off
goto 'input'
: 'input'
cls
set "inp="
set /p inp=What would you like to do?
set firstresponse=%inp:~0,5%
if %firstresponse%==help goto 'help'
pause
if /I %firstresponse%==check set firstresponse=dir && set
executeparttwo=%inp:~5%
if /I %firstresponse%==remov goto 'remove'
%firstresponse%%executeparttwo%
pause
goto 'input'
: 'remove'
set "firstresponse=" && set firstresponse=%inp:~0,6%
if /I %firstresponse%==remove set firstresponse=del
set executeparttwo=%inp:~6%
%firstresponse%%executeparttwo%
pause
goto 'input'
: 'help'
cls
echo Check = Dir in regular command prompt, checks a directory.
echo Remove = del in regular command prompt, deletes something.
pause
goto 'input'
if the User typed an invalid command, it will show like what CMD does ( 'command' is not recongnized...)
What i want to do is to replace the CMD invalid command text to my own one like "command" is an invalid command, but to do that i need to "hide" the CMD one (because if the user typed a invalid command it will not show him a "custom message")
I tried to use some Batch plugins like batbox, CursorPos etc... To replace the cursor position but i didn't get what i wanted. So if anyone have a solution i will be very appreciated!
Have a nice day, and thanks for reading!
Your splitting the command and parameters is not ideal, there is a much easier and safer way. Also, the method of an own subroutine for each command is suboptimal (especially, when you add more and more commands).
#echo off
call :commandlist REM build translation table
:input
REM get input line:
set /p "commandline=Enter Command: "
REM split to command and parameters
for /f "tokens=1,*" %%a in ("%commandline%") do (
set "command=_%%a"
set "params=%%b"
)
REM check for valid command:
set _|findstr /bi "%command%=" >nul || (
echo invalid command: '%command:~1%'.
goto :input
)
REM execute the command:
call %%%command%%% %params%
goto :input
:Commandlist
set "_check=dir /b"
set "_remove=del"
set "_help=:help"
set "_where=call echo %%cd%%"
set "_change=cd"
set "_apt-get=:apt"
set "_bye=exit /b" 'secret' exit command ;)
goto :eof
:help
echo Check = Dir in regular command prompt, checks a directory.
echo Remove = del in regular command prompt, deletes something.
echo Where = echo %%cd%% in regular command prompt, print working folder.
echo Change = cd in regular command prompt, change working folder
goto :eof
:apt
if /i "%~1" == "update" echo updating... & goto :eof
if /i "%~1" == "whatever" echo whatevering... & goto :eof
echo invalid command: '%command:~1% %1'
goto :eof
(Note to experienced batch users: yes I know there is a possibility for some "code injection")

display a variable like %%i in for statements in variable? batch

How do I use a variable like %%i in a permanent variable?
(I don't really know the correct terms, so I hope anyone can figure out what I mean)
This is the code I am using:
#echo off
color 0f
goto number
:number
title number
cls
echo number of options?
set /p num=
goto option
:option
for /l %%i in (1,1,%num%) do (
cls
echo Name nr. %%i
echo Enter a option
set /p n%%i=
echo %%i = %n%%i% >> log.txt
)
goto select
:select
cls
echo %n2%
pause >nul
the "%n2%" works for whatever you put in second, but when I try to print it into a file ( echo %%i = %n%%i% >> log.txt ) it doesn't work.
I know the "%n%%i%" is not correct, But I don't really know what to actually put there.
:option
for /l %%i in (1,1,%num%) do (
cls
echo Name nr. %%i
echo Enter an option
set /p option%%i=
)
goto select
:select
set option>log.txt
cls
echo %option2%
You may like to consider this.
The command
set option
will show every environment variable that starts option in the format option1=Gido, which is why I changed n to option (there are other variables set that start n)

Making a batch file do something once

I'm making a game and I want a personalized username option that only appears once.
Here is an example:
#echo off
:onetime
echo please enter a username
echo.
set /p newuser=%newuser%:
echo %newuser%> cfg.txt
goto menu
:menu
for /f "tokens=* delims=" %%x in (cfg.txt) do echo %%x
cls
...
I'm trying to figure out how to make :onetime happen once, so that it sends the username to cfg.txt
Anyone know how?
I have cleaned up your code and provided a completed working script, and noted where you will put your game code.
Although Delayed expansion is not needed for this code, I have placed it in the script as you had it in your original script.
Please be mindful of the variable names I have chosen as they are used in several locations.
I have tried to comment the code with info on what it is doing, and I would be happen to explain further if needed.
I'd like to actually play your game when you are completed with it, if I may. :)
Hope that helps.
Ben
BPG.cmd
REM Script: BPG.cmd
REM Version: 1.0
REM Description: Game to play about Monsters.
Rem Notes: Currently Implementing Menu System.
Rem Sets up Variables and checks if the script needs to be re-called.
#(
SETLOCAL ENABLEDelayedExpansion
echo off
SET "eLvl=0"
SET "ScriptFolder=%~dp0"
SET "Log=%~dpn0.log"
SET "ConfigFile=%~dpn0_cfg.txt"
IF /I "%~1" NEQ "MAX" (
ENDLOCAL
ECHO.Game not started Maximized, Opening in a New Window by Running: Start "BPG 1 A Batch of Monsters" /MAX "%~dpnx0" MAX
Start "BPG 1 A Batch of Monsters" /MAX "%~dpnx0" MAX
EXIT /b %eLvl%
)
COLOR 2
)
REM Calls Main Function.
CALL :Main
REM Ends the script.
(
ENDLOCAL
EXIT /b %eLvl%
)
REM Main Function, most of your coding goes here, and this function calls sub functions.
:Main
Rem Check if Config file exists, if it does not, then call the New User Function.
IF NOT EXIST "%ConfigFile%" (
CALL :NewUser
)
Rem Load Username from Config file.
FOR /F "Tokens=*" %%A IN ('Type "%ConfigFile%"') DO (
SET "_UserName=%%~A"
)
Rem Call Menu System
CALL :Menu
REM Based off the option chosen Either Start a new Game or Skip to the End.
REM ECHO.CALL %_Menu_Choice%
CALL %_Menu_Choice%
GOTO :EOF
:NewUser
SETLOCAL
REM Get the Username Input
SET /P "_User=Please Enter a Username: "
REM Output the Username to the config file, overwriting all the file contents:
echo.%_User%>"%ConfigFile%"
ENDLOCAL
GOTO :EOF
:Menu
SETLOCAL
REM Output the Config file contents:
Type "%ConfigFile%"
REM Clear the screen
cls
echo ______ _______ _______
echo I ___ \ I ____ I I ____ \
echo I I I II I II I I \/
echo I I__/ / I I____II I I
echo I __ I I _____I I I ____
echo I I \ \ I I I I \_ I
echo I I___I II I I I___I I
echo I______/ I_/ I_______I A BATCH OF MONSTERS
echo.
echo.
echo 1) Begin
echo.
echo 2) Exit
echo.
set /p "_Choice=%_UserName%, Enter a Number: "
(
REM End the local variable Space, and Set return variables based on the choice, or re-draw the menu.
ENDLOCAL
IF /I "%_Choice%" EQU "1" (
REM ECHO.%_Choice% EQU 1
SET "_Menu_Choice=:Begin_Game"
) ELSE (
IF /I "%_Choice%" EQU "2" (
REM ECHO.%_Choice% EQU 2
SET "_Menu_Choice=GOTO :EOF"
) ELSE (
ECHO.%_Choice% Not Valid!
PAUSE
GOTO :Menu
)
)
)
goto :EOF
:Begin_Game
REM All the remaining code for your game should probably go here.
GOTO :EOF
try checking file existence :
#echo off
:onetime
setlocal enableDelayedExpansion
if not exist "cfg.txt" (
echo please enter a username
echo.
set /p newuser=%newuser%:
echo !newuser!> cfg.txt
goto menu
)
:menu
for /f "tokens=* delims=" %%x in (cfg.txt) do echo %%x
cls

Batch || I am having problems loading variables from txt file

I am having problems reading from text files.
When I try to load in variables from text files, they just return blank, but when I 'type' them, they return perfectly normal.
The code I use to read and save the files (basecd is the directory of the bat file):
:loadGame
cls
echo Saves:
cd Data\Saves\
dir /a:d /b
echo[
cd %~dp0
echo %~dp0
set /p filename=Name of save file:
echo[
if "%filename%" EQU "" (
echo File does not exist...
pause
goto menuLoop
)
if exist "Data/Saves/%filename%" (
cd %basecd%Data\Saves\%filename%\
echo %basecd%Data\Saves\%filename%\
echo Loading File...
set /p name=<%basecd%Data\Saves\%filename%\name.txt
set /p race=<%basecd%Data\Saves\%filename%\race.txt
set /p hair=<%basecd%Data\Saves\%filename%\hair.txt
set /p eyes=<%basecd%Data\Saves\%filename%\eyes.txt
set /p area=<%basecd%Data\Saves\%filename%\area.txt
set /p quest_starter=<%basecd%Data\Saves\%filename%\quest_starter.txt
type %basecd%Data\Saves\%filename%\area.txt
echo %name%
echo %quest_starter%
echo %area%
echo File loaded
pause
goto mainLoop
)
echo File does not exist...
pause
goto menuLoop
This is the code that I use to write to the files, but I can see on my computer that the files are in the folder and are not empty.
:event_generic_save_game
cls
echo Save file name:
:saveloop
set /p filename=
if "%filename%" EQU "" (
echo File name is invalid!
goto saveloop
)
if exist "Data\Saves\%filename%" (
echo Save file already exists.
set /p input=Overwrite? y/n
if "%input%" EQU "n" (
echo Save canceled
set /p buffer=
cls
goto mainLoop
)
)
echo saving game '%filename%'...
if exist "Data\Saves\%filename%" (
del Data\Saves\%filename%
)
mkdir Data\Saves\%filename%
echo %area%>Data\Saves\%filename%/area.txt
echo %hair%>Data\Saves\%filename%/hair.txt
echo %eyes%>Data\Saves\%filename%/eyes.txt
echo %race%>Data\Saves\%filename%/race.txt
echo %name%>Data\Saves\%filename%/name.txt
echo %quest_starter%>Data\Saves\%filename%/quest_starter.txt
echo Game saved
pause
cls
goto mainLoop
'set /p buffer=' Is a stand in for 'pause'
Please help, I have been ruminating on this for days and I can't get over it.
Thank you for reading
Please note that \ is the path-separator in batch, and / introduces swiches. Sometimes batch does the translation. Not always....
This has nothing to do with your apparent problem. Please see endless items on SO about delayed expansion
Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed - the same thing applies to a FOR ... DO (block).
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered.
In your case, you are varying the values within the block, hence you see the original values, not the altered values.
Tip for game-generation:
If you reserve a character as a prefix for variables-you-want-to-save (eg all variables I want to save/reload start with #) then all you need to save a game is
set #>"mygamefile.txt"
and all you need to reload a game is
for /f "usebackqdelims=" %%a in ("mygamefile.txt") do set "%%a"
To zap all # variables (useful before reloading a game) use
for /f "delims==" %%a in ('set # 2^>nul') do set "%%a="

How to find a certain word in a file without using ERRORLEVEL (batch)

I can use ERRORLEVEL, but tried and with a loop it failed.
I am writing a batch "shell."
Since I have tried and tried, I am finally asking for help.
The reason I don't want to use errorlevel is because the loop.
(FULL) SHELL
#set /p build=<"C:\Users\%username%\Desktop\WellOS2\WellOS\Build".txt
#title WellOS V.%build%
#echo off
goto boot
:register
cls
echo You are registering...
echo If this is an error press CTRL + C NOW...
pause
cls
set /p user= Enter your username:
set /p passwordreg= Enter your password:
mkdir "C:\Users\%username%\Desktop\WellOS2\Users\%user%"
mkdir "C:\Users\%username%\Desktop\WellOS2\Users\%user%\Documents"
echo %passwordreg% >"C:\Users\%username%\Desktop\WellOS2\Users\%user%\password".txt
echo 2 >"C:\Users\%username%\Desktop\WellOS2\OSfiles\bootset".txt
echo Your done.
pause
goto welloslog
:booterror
echo Sorry the boot file has an error. Check the user manual for BOOT$
pause
:boot
set /p boot=<"C:\Users\%username%\Desktop\WellOS2\OSfiles\bootset".txt
if %boot% == 1 goto register
if %boot% == 2 goto welloslog
goto booterror
cls
:ERROR
cls
echo ----------ERROR-------------------
echo %error%
pause
goto %back%
:welloslog
cls
echo Welcome to WellOS2!
echo ----------------LOGIN-------------
set /p user= Username:
if exist "C:\Users\%username%\Desktop\WellOS2\Users\%user%" goto pass
set error= Sorry that account doesn't exist.
set back=welloslog
goto welloslogerror
:pass
set /p password=<"C:\Users\%username%\Desktop\WellOS2\Users\%user%\password".txt
set /p passwordlog= Password:
if /i %passwordlog% == %password% goto wellos
set error= Sorry! wrong password.
set back= welloslog
goto error
:wellos
cls
:wellosnocls
echo --------------MAIN---------------
echo type help for help
set /p command= #:
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.sys" set type=sys
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.pro" set type=pro
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.sys" goto po
if exist "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.pro" goto po
set error= !Unreconized program/system program!
set back=wellos
goto error
:po
set lines=0
echo --------------%command%.%type%---------------
:porep
set /a lines=%lines% + 1
set /p "code="<"C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%".wellcode
if "%code%"=="GOWELL" goto wellosnocls
findstr /I /L "if" "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%.wellcode"
:skip
call %code%
goto porep
::Tools
:iftl
%code%
goto porep
PROGRAM OPENER (What I am talking about, and having problems with...)
:po
set lines=0
echo --------------%command%.%type%---------------
:porep
set /a lines=%lines% + 1
set /p "code="<"C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%".wellcode
if "%code%"=="GOWELL" goto wellosnocls
findstr /I /L "if" "C:\Users\%username%\Desktop\WellOS2\Programdata\%command%.%type%\%command%.%type%-%lines%.wellcode" goto iftl
:skip
call %code%
goto porep
::Tools
:iftl
%code%
goto porep
findstr "targetstring" datafilename >flagfilename
for %%a in (flagfilename) do if %%~za==0 echo not found
for %%a in (flagfilename) do if %%~za neq 0 echo found
beyond that, your question is too vague.
The following command returns all lines of a text file textfile.txt that contain the word word (remove the /I switch if you want the search to be case-sensitive):
findstr /I /L "word" "textfile.txt"
With for /F you can capture the output and test whether it is empty, as the loop does not iterate if no match is encountered:
set "FOUND="
for /F "delims=" %%F in ('
findstr /I /L "word" "textfile.txt"
') do (
set "FOUND=Yes"
)
if defined FOUND (
echo One or more matches found.
rem do something...
) else (
echo No match found.
rem do something else...
)
Type for /? and if /? in command prompt to get details about the used commands.
There is also a way to use ErrorLevel implicitly, meaning you do not have to query its value by something like %ErrorLevel%, !ErrorLevel! or if ErrorLevel, namely when using conditional command separators:
the && separator executes the following command only in case the previous one succeeded, that is, it returned an ErrorLevel of 0; (findstr returns 0 in case a match is encountered;)
the || separator executes the following command only in case the previous one failed, that is, it returned an ErrorLevel other than 0; (findstr returns a non-zero ErrorLevel in case no match is encountered;)
The following line of code demonstrates the usage:
findstr /I /L "word" "textfile.txt" && (echo One or more matches found.) || echo (No match found.)

Resources