so I'm writing batch and come up with the ( was unexpected error after setting the first variable. I want a batch file to start with just setting the color. (I named it edmond)
this is my code
#echo off
SETLOCAL
title Edmond
goto :Check
:Prompt
set /p action=What shall I do for you master?
:Check
if not defined action goto :Prompt
echo %action%
pause
if /i %%action == color (
echo stuff
:cl
set /p BC=What Should the background color be?
set /p FC=and the foreground color?
if %BC%==Black set BC1=0
if %BC%==Blue set BC1=1
if %BC%==Green set BC1=2
if %BC%==Aqua set BC1=3
if %BC%==Red set BC1=4
if %BC%==Purple set BC1=5
if %BC%==Yellow set BC1=6
if %BC%==White set BC1=7
if %BC%==Gray set BC1=8
if %BC%==LBlue set BC1=9
if %BC%==LGreen set BC1=a
if %BC%==LAqua set BC1=b
if %BC%==LRed set BC1=c
if %BC%==LPurple set BC1=d
if %BC%==LYellow set BC1=e
if %BC%==LWhite (
set BC1=f
) else (
echo I'm sorry, I didn't exactly understand that.
echo By any chance could you say it again?
goto cl
)
if %FC%==Black set FC1=0
if %FC%==Blue set FC1=1
if %FC%==Green set FC1=2
if %FC%==Aqua set FC1=3
if %FC%==Red set FC1=4
if %FC%==Purple set FC1=5
if %FC%==Yellow set FC1=6
if %FC%==White set FC1=7
if %FC%==Gray set FC1=8
if %FC%==LBlue set FC1=9
if %FC%==LGreen set FC1=a
if %FC%==LAqua set FC1=b
if %FC%==LRed set FC1=c
if %FC%==LPurple set FC1=d
if %FC%==LYellow set FC1=e
if %FC%==LWhite (
set FC1=f
) else (
echo I'm sorry, I didn't exactly understand that.
)
echo Applying changes.
ping localhost -n 2 >nul
color %FC%%BC%
) else (
echo I'm sorry, I didn't exactly understand that.
)
pause
exit
after the set /p action=what shall I do for you master? it says ( was unexpected and then shuts down (I got the ( was unexpected by printing screen before it closes) can someone help? thanks (in advance)
if /i %%action == color (
should be
if /i %action% == color (
or better
if /i "%action%"=="color" (
since you have uncontrolled input that may contain spaces or other separators.
Your upcoming problems are many-fold.
You can't use a label in a (block statement - a series of parenthesised statements)
You need to
setlocal enabledelayedexpansion
then use !var! in place of %var% withing a block statement to access the value of any ordinary environment variable changed or established within the block.
Very much truncated revised structure:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:Prompt
set /p action=What shall I do for you master?
:Check
if not defined action goto :Prompt
echo %action%
if /i "%action%"=="color" GOTO setcolor
echo I'm sorry, I didn't exactly understand that.
goto Prompt
:setcolor
echo stuff
:cl
set /p BC=What Should the background color be?
set /p FC=and the foreground color?
:: This forces BC1 & FC1 to be undefined
SET "BC1="
SET "FC1="
if /i "%BC%"=="Black" set BC1=0
if /i "%BC%"=="Blue" set BC1=1
:: Your job to fill in the rest
IF NOT DEFINED BC1 (
echo I'm sorry, I didn't exactly understand that.
echo By any chance could you say it again?
goto cl
)
if /i "%FC%"=="Yellow" set FC1=6
:: Your job to fill in the rest
IF NOT DEFINED BC1 (
echo I'm sorry, I didn't exactly understand that.
rem I suppose you really want to re-enter at this point.
rem note that you need to use REM within a block, not ::-style comments.
goto cl
)
echo Applying changes.
ping localhost -n 2 >NUL
:: Best to use FC1 and BC1 here, else you'll try to execute "color YellowBlack"
:: And it's likely you have them reversed.
color %FC1%%BC1%
GOTO :EOF
Related
I come to find some guidance on accomplishing the following:
I have a variable with content like this:
varname = asdfiuytgy12$gggsy22.oihbcxew
or
varname = oiujedc$thisisit.oiju
which $ and . are exactly my partters and I need to get what is within them so gggsy22 or thisisit.
I need to use batch to create a simple bat file. I hope someone can provide some guidance.
Edit - (from comment section)
Actually a friend of mine helped and it did work but with a quite amount of lines:
Set "sstr=$"
SET stemp=%nameVar%&SET pos=0
:loop
SET /a pos+=1
echo %stemp%|FINDSTR /b /c:"%sstr%" >NUL
IF ERRORLEVEL 1 (
SET stemp=%stemp:~1%
IF DEFINED stemp GOTO loop
SET pos=0
)
Set "pos1=%pos%"
Set "sstr=."
SET stemp=%nameVar%&SET pos=0
:loop
SET /a pos+=1
echo %stemp%|FINDSTR /b /c:"%sstr%" >NUL
IF ERRORLEVEL 1 (
SET stemp=%stemp:~1%
IF DEFINED stemp GOTO loop
SET pos=0
)
Set "pos2=%pos%"
set /a "pos2=%pos2%-%pos1%-1"
call set env=%%nameVar:~%pos1%,%pos2%%%
#echo off
set "varname=asdfiuytgy12$gggsy22.oihbcxew"
for /f "tokens=2 delims=$." %%a in ("%varname%") do set "sub=%%a"
The following works in nearly any situation. The only thing that could break the code is if the string contains a quote " followed by a poison character like &, |, etc.
#echo off
setlocal
set "str=oiujedc$thisisit.oiju"
:: Verify string exists and has the proper format
echo "%str%"|findstr "\$.*\." >nul || (echo Value not found & exit /b)
:: Extract the value
:: The extra "x" is needed in case there is no character between $ and .,
:: in which case the result should be No Value (result variable not defined)
for /f "delims=." %%A in ("x%str:*$=%") do set "val=%%A"
set "val=%val:~1%"
:: Show the result
echo value = "%val%"
A bullet proof variant can be made by incorporating delayed expansion.
I have to make batch file, that, when run, will give me options to run Install files. I need to make it multiple choice menu.
I made bit of research and found code, that is multiple choice menu, that asks users input. Forgot link, sorry.
But here is my problem. I want menu to have Check boxes (Tick boxes) that, when ticked install these programs.
Is there any tutorial on how to do it? Or, if that even possible?
It's not clickable, but this could be what you want:
#echo off
setlocal EnableDelayedExpansion
set "getKeyMacro=powershell -noprofile "^
while (-not (37..40+13).contains($x)) {^
$x = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown').VirtualKeyCode^
}^
if ($x -eq 13) {^
'enter'^
}^
('left','up','right','down')[$x - 37]^
""
set "num=0"
for %%a in ("Install thing 1"
"Do thing 2"
"Execute thing 3"
"Run thing 4"
"Test thing 5") do (
set /A num+=1
set "option!num!=0"
set "option!num!name=%%~a"
)
set "maxOptions=%num%"
set "selected=1"
:select
cls
echo use ^<right^> arrow to continue, ^<up^> and ^<down^> to select, and ^<enter^> to toggle
FOR /L %%G IN (1,1,%maxOptions%) DO (
set "display=[ ]"
if !option%%G! equ 1 set "display=[x]"
if %%G equ !selected! set "display=^>!display!"
echo !display! !option%%Gname!
)
FOR /F "delims==" %%G IN ('%getKeyMacro%') DO set "key=%%G"
if "%key%"=="up" set /a "selected-=1"
if "%key%"=="down" set /a "selected+=1"
if %selected% lss 1 set "selected=1"
if %selected% gtr %maxOptions% set "selected=!%maxOptions%!"
if "%key%"=="enter" goto toggle
if "%key%"=="right" goto OK
goto select
:toggle
set /a "option%selected%+=1"
set /a "option%selected%=!option%selected%!%%2"
goto select
:OK
FOR /L %%G IN (1,1,%maxOptions%) DO (
if !option%%G! equ 1 (
call :logic "%%G"
)
)
pause
goto :eof
:logic
set "install=%~1"
echo executing %install%
Put the installing logic where echo executing %install% is, for example if "%install%"=="1" start "" "somefileToInstall"
DOS Batch - Menus is a good tutorial that you can create an advanced dynamic menu
Those are some examples where i learned from it to create easily a menu like that :
Sound in batch?
How to check and correct user input when he omit the extension .exe to kill the process?
I am trying to make a batch roguelike but I am running in to three main problems. First of all my message system is not working. Second there is a glitch where if i try to move somewhere where I can't the choice statement keeps writing the W, S, A, and D's at the bottom. Third and most importantly there is a very annoying flashing of the screen. I tried to minimize the time it takes to load but to no avail. Here is my code:
#echo off
setlocal enableextensions
mode con: cols=54 lines=30
set num=1
set nextVar=1
set oldVar=103
set message=a
cls
echo Loading...
:startup
if not %num%==1001 (
set b%num%=.
set /a num = %num% + 1
goto startup
)
cls
set b103=#
goto update
:update
choice /c wsad /n /m ""
if %errorlevel%==1 set /a nextVar = %oldVar% - 50
if %errorlevel%==2 set /a nextVar = %oldVar% + 50
if %errorlevel%==3 set /a nextVar = %oldVar% - 1
if %errorlevel%==4 set /a nextVar = %oldVar% + 1
if defined b%nextVar% (
set b%nextVar%=#
set b%oldVar%=.
set oldVar=%nextVar%
set message="a"
goto display
)
set message="You can not move there."
goto update
:display
set ln1=%b1%%b2%%b3%...
set ln2=%b51%%b52%%b53%...
set ln3=%b101%%b102%...
...
...
...
set ln8=%b351%%b352%...
set ln18=%b851%%b852%%b853%
set ln19=%b901%%b902%%b903%%b904%...
set ln20=%b951%%b952%%b953%%b954%%b955%%b956%...%b1000%
cls
if not "%message%"=="a" (
echo %message%
goto next
)
echo.
:next
echo.
echo %ln1%
echo %ln2%
echo %ln3%
echo %ln4%
echo %ln5%
echo %ln6%
echo %ln7%
echo %ln8%
echo %ln9%
echo %ln10%
echo %ln11%
echo %ln12%
echo %ln13%
echo %ln14%
echo %ln15%
echo %ln16%
echo %ln17%
echo %ln18%
echo %ln19%
echo %ln20%
echo.
goto update
I had to ... some sections to save space. If anyone can solve these problems in particularity the screen flashing that would be super helpful. Also if anyone has ideas on generation NetHack like dungeons that would also be appreciated. Thank you.
So problems 1 and 2 are related.
First of all my message system is not working. Second there is a glitch where if i try to move somewhere where I can't the choice statement keeps writing the W, S, A, and D's at the bottom.
Change the error goto statement for the update section. You want to go to the display section so the screen is redrawn (removing the old used choice prompt) and the error message is displayed.
set message="You can not move there."
goto display
Problem 3 is a bit more difficult due to the nature of batch.
Third and most importantly there is a very annoying flashing of the screen.
The flashing is caused primarily because of one command. The cls command. Instead of just redrawing the screen it is first causing the screen to turn black before the new output is drawn causing the flicker.
Step 1: Remove the cls command. This means that you will have to output 30 lines each time to fill the screen.
Reducing the flicker even more will require a bigger overhaul on your script. Instead of echoing each line use the natural ability of the command window to wrap lines to draw the whole screen. This will reduce the amount of echo calls to a couple. Your canvas is set to 54 x 30 so that equals 1620 characters to fill the whole screen at one time.
Step 2: Output the entire screen with a single or as few calls as possible to prevent drawing/scrolling delay and use the natural line wrapping ability of the console window.
Here is an example I put together to illustrate this second step. Let me know if you have any questions.
#echo off
( if "%~1"=="" start "" /HIGH %0 1 & exit /b 1 )
setlocal enabledelayedexpansion
mode con: cols=80 lines=25
set "mark=0"
set "switch=0"
:next
if %mark% geq 920 set "mark=0" & if %switch% equ 0 ( set "switch=1" ) else set "switch=0"
set top=........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
set bot=........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
if %switch% equ 0 set top=!top:~0,%mark%!^|!top:~%mark%!
if %switch% equ 1 set bot=!bot:~0,%mark%!^|!bot:~%mark%!
goto display
:display
echo %mark%
set /p "=%top:~0,920%" <nul
set /p "=%bot:~0,920%" <nul
ping 192.0.2.2 -n 1 -w 200 >nul
set /a mark+=1
goto next
Step 3: An additional step that helps would be to increase the processes priority level. I have also added this to my example script above on the second line.
How can I prompt users for an answer, suggesting something they can edit?
I know how to make a q&a like:
1. The sky is:
The user put the answer and:
echo For you the sky is %var%
But i want something like:
1. The sky is: Blue
echo For you the sky is Blue
But the user can change it
1. The sky is: Green
echo For you the sky is Green
I don't know if i was clear, tell me if not.
Thanks
Initialize the variable before with a color:
#echo off&setlocal
set "color=Blue"
set/p "color=For you the sky is %color% (hit enter for o.k. or type in other color): "
echo For you the sky is %color%
You can use WScript.Shell's SendKeys method through JScript or VBScript to simulate keypresses. Give this a shot. I think it does what you're looking for. It will send uneditable 1. The sky is: then simulate the user keystrokes of Blue. The user is then free either just to hit Enter, or he can Backspace to erase "Blue" and replace it whatever he wishes.
Save this with a .bat extension and run it.
#if (#a==#b) #end /*
:: batch portion
#echo off
setlocal
set /p "=1. The sky is: "<NUL
call :sendkeys Blue
set /p "sky="
echo For you the sky is %sky%. Press any key to exit.
pause >NUL
exit /b
:sendkeys <string>
cscript /nologo /e:jscript "%~f0" "%~1"
goto :EOF
:: JScript portion */
var sh = new ActiveXObject("WScript.Shell");
sh.SendKeys(WSH.Arguments(0));
set x=blue
set y=
set /p "y=The sky is [%x%] "
if not defined y set y=%x%
echo For your the sky is %y%
If user input is empty, the predefined %x% is copied to the outputvariable %y%
As other answers said, you must need a third party utility to solve this problem. For example, I used my GetKey.exe and Show.exe auxiliary programs to write ReadLine.bat, a subroutine that simulate SET /P command, that is, it read characters until Enter key is pressed and delete the last character with BackSpace key. We may modify such routine in order to provide an initial value for the input variable:
#echo off
rem Read a variable with an initialized value
rem Antonio Perez Ayala
set Bell=7
set BackSpace=8
set Enter=13
set Space=32
:ReadInitVar var="prompt" ["initial value"]
rem %1 %2 %3
setlocal EnableDelayedExpansion
Show %2
set len=0
if "%~3" equ "" (
set %1=
) else (
Show %3
set "%1=%~3"
for /L %%i in (0,1,80) do if "!%1:~%%i,1!" neq "" set /A len+=1
)
:nextKey
GetKey
set key=%errorlevel%
if %key% geq %Space% (
rem Ascii character: insert it
Show %key%
for /F "delims=" %%a in ('Show %key%') do set "%1=!%1!%%a"
set /A len+=1
) else if %key% equ %BackSpace% (
rem Backspace: delete last character
if defined %1 (
Show %BackSpace% %Space% %BackSpace%
set "%1=!%1:~0,-1!"
set /A len-=1
) else (
rem Empty value
Show %Bell%
)
)
if %key% neq %Enter% goto nextKey
echo/
for /F "delims=" %%a in ("!%1!") do endlocal & set %1=%%a
exit /B
This way, you may use this line to solve your problem:
call :ReadInitVar color="For you the sky is " "Blue"
You may download Getkey.exe and Show.exe auxiliary programs, and review the original ReadLine.bat subroutine, from this site: Advanced Batch features via auxiliary .exe programs.
There is also another subroutine similar to ReadInitVar.bat above, but that display the user input in a different color field by using ColorShow.exe auxiliary program instead of Show.exe. You may review it here: http://www.dostips.com/forum/viewtopic.php?f=3&t=4198&p=23426#p23426
I'm being driven crazy by a stupidly simple problem that is eating up my time. I just want to append strings separated by comma, but the comma doesn't get appended. Below is my batch file snippet:
set MissingParams=
set SwitchURL=
set TrustStore=
if 0%SwitchURL%==0 (set MissingParams=SwitchURL)
if 0%TrustStore%==0 (
if not 0%MissingParams%==0 (
set MissingParams=%MissingParams%,
)
set MissingParams=%MissingParams%TrustStore
)
After runnin this script when I echo %MisingParams%, the expected value is SwitchURL,TrustStore but it simply prints
SwitchURLTrustStore.
D:\deleteme>echo %MissingParams%
SwitchURLTrustStore
For debugging, when I introduced some echo statements in the batch file, the results are even more bizzare:
set MissingParams=
if 0%SwitchURL%==0 (set MissingParams=SwitchURL)
if 0%TrustStore%==0 (
if not 0%MissingParams%==0 (
echo MissingParams=%MissingParams%
set MissingParams=%MissingParams%,
echo MissingParams=%MissingParams%
)
set MissingParams=%MissingParams%TrustStore
echo MissingParams=%MissingParams%
)
When I run the above script it prints
MissingParams=SwitchURL
MissingParams=SwitchURL
MissingParams=SwitchURL
And when I echo the value from the command prompt, as before I get SwitchURLTrustStore
D:\deleteme>echo %MissingParams%
SwitchURLTrustStore
Does anyone have any ideas? This is frustrating me to no end.
This is the standard parenthesis/delayedExpansion problem.
The simple rule is %var% are expanded before a parenthesis block is executed(while parsing).
If you need the var-expansion later, you should use the delayed expansion.
Explained in set /?
setlocal EnableDelayedExpansion
set MissingParams=
set SwitchURL=
set TrustStore=
if 0!SwitchURL!==0 (set MissingParams=SwitchURL)
if 0!TrustStore!==0 (
if not 0!MissingParams!==0 (
set MissingParams=!MissingParams!,
)
set MissingParams=!MissingParams!TrustStore
)
Sort of looks like a scoping problem. I was able to work around this by branching with a goto which works. Here's my version with extra debug crap:
#echo off
set MissingParams=
set SwitchURL=
set TrustStore=
if "%SwitchURL%"=="" (set MissingParams=SwitchURL)
echo MissingParams1 is %MissingParams%
if "%TrustStore%" EQU "" (GOTO :BRANCH1)
:RESUME
echo MissingParams3 is %MissingParams%
set MissingParams=%MissingParams%TrustStore
echo MissingParams4 is %MissingParams%
)
echo MissingParamsF is %MissingParams%
GOTO :eof
:BRANCH1
if "%MissingParams%" NEQ "" (set MissingParams=%MissingParams%,)
GOTO RESUME