Refillable lists in batch - list

So. Currently I am working on a game where you create your own nation in Batch. There are bills passed by congress that you can either sign or veto. Once you do so, the bill disappears. After some time a new bill will pop up. The thing is there is a bill limit of 5, meaning that there can only be 5 bills waiting your approval at a time.
Here is the code so far.
:leg
title Borderlines BETA - Legislation
cls
echo =====
echo 1-Legislation (%notify_leg%) ===== 2-Disputes (%notify_disputes%) ===== 3-Mailbox (%notify_mailbox%)
echo =====
echo Legislation
if %notify_leg% GTR 0 (
echo You have new bills from Congress awating your approval!
) else (
echo Its been a slow day in %nation%...
)
echo ---
echo Select a bill...
echo %leg_01%
echo %leg_02%
echo %leg_03%
echo %leg_04%
echo %leg_05%
echo.
echo ---
echo A - Home
echo.
echo ---
set /p leg_choice=""
if %leg_choice%==A goto home
if %leg_choice%==1 goto leg
if %leg_choice%==2 goto disputes
if %leg_choice%==3 goto mail
if %leg_choice% GTR 3 goto bill_%leg_choice%
goto home
Basically %leg_01%, %leg_02%, and so on are the slots. When you create your nation, the bills are assigned. When you pass or veto a bill it removes the notification.
However lets say over time another bill gets added to the list. How can I have it so that once you sign or veto the bill it will remove it from the list, tell the program that a slot is available, and move up the remaining items all the way to the top. This would be essential because there could be, eventually, multiple bills in the game that will show up on that list.
Hope that makes sense ~

Does this suit your needs?
:newleg
if "%~1"=="" exit /b
for /l %%# in (4 -1 1) do (
set /a n=%%#+1
call set leg_0%%n%%=%%leg_0%%#%%
)
set leg_01=%~1
Call with call :newleg This_is_a_new_leg. All values will be shifted downwards, i.e. leg_05 is lost, the value of leg_04 is assigned to leg_05. leg_01 will be redefined as the specified parameter.
If you'd like to avoid quoting values with spaces while calling the function, you can use %* instead.
You can also keep the values of leg_06 and so on by increasing the limit in the for-loop (n-1, in this case "4").
You can delete an item from the list and then shift upwards with this function:
:delleg
if "%~1"=="" exit /b
set leg_0%1=
for /l %%# in (1 1 5) do if not defined leg_0%%# call :dl %%#
exit /b
:dl
set /a n=%1+1
for /l %%# in (%n% 1 6) do (
set /a n=%%#-1
call set leg_0%%n%%=%%leg_0%%#%%
)
exit /b
Call with call :delleg 2 to delete leg_02.

Related

Needing advice on structuring a larger scale batch file game [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 months ago.
Improve this question
So I've started getting familiar with Batch for the last year off and on, all self taught, and I've made a few little dinky projects here and there but I'm wanting to find out the best way to go about expanding my code. Using other programs for inspiration I've learned just the tip of the icebergs for "FOR loops" and using functions and small macro processes. I want to know if there is anything I should do differently in terms of architecture and planning so I can one day make amazing Batch programs like T3RROR (little weird but I'm a big fan and your my batch idol).
Below is my most complex batch code I've written and a template for future games, please add any tip or advice.
#echo off
SETLOCAL EnableDelayedExpansion
title crafting micro
color 2
:://///////////////////////////////////////////////////////////////////////
:pre_start
::initializes at the start of the program
set /a display_message=0
set /a inv_fiber=1
set /a fiber_qty=100
set /a inv_rope=0
set /a rope_qty=0
set /a inv_stick=1
set /a stick_qty=100
set /a inv_stone=1
set /a stone_qty=100
set /a inv_sharpened_stone=0
set /a sharpened_stone_qty=0
set /a inv_spear=0
set /a spear_qty=0
set /a inv_handaxe=0
set /a handaxe_qty=0
set /a inv_hammer=0
set /a hammer_qty=0
:://///////////////////////////////////////////////////////////////////////
:start
cls
echo ----------------------------------------------------
echo Crafting Menu
echo ----------------------------------------------------
echo.
echo Raw materials
echo -------------
if %inv_fiber%==1 echo Fiber: x%fiber_qty%
if %inv_stick%==1 echo Stick: x%stick_qty%
if %inv_stone%==1 echo Stone: x%stone_qty%
echo.
echo Refined Materials
echo -----------------
if %inv_rope%==1 echo Rope: x%rope_qty%
if %inv_sharpened_stone%==1 echo Sharpened Stone: x%sharpened_stone_qty%
echo.
echo Tools
echo -----
if %inv_spear%==1 echo Spear: x%spear_qty%
if %inv_handaxe%==1 echo Handaxe: x%handaxe_qty%
if %inv_hammer%==1 echo Hammer: x%hammer_qty%
::sets visibility
echo.
echo ----------------------------------------------------
echo.
echo What do you wanna craft?
echo 1. Rope (x3 Fiber)
echo 2. Sharpened Stone (x2 Stones)
echo 3. Spear (x1 Rope, x1 Stick, x1 Sharpened Stone )
echo 4. Handaxe (x2 Rope, x2 Stick, x1 Sharpened Stone)
echo 5. Hammer (x2 Rope, x2 Stick, x1 Stone)
echo.
choice /c 12345
echo.
echo.
if %errorlevel%==1 (
set item=Rope
::item being crafted
set /a req1=%fiber_qty%
::1st required item
set /a min1=3
:: minimum amount needed to craft
set /a req2=0
set /a min2=0
set /a req3=0
set /a min3=0
set var1=fiber
::passes a string to be use for a vavriable
set var2=
set var3=
set var4=rope
)
if %errorlevel%==2 (
set item='Sharpened Stone'
set /a req1=%stone_qty%
set /a min1=2
set /a req2=0
set /a min2=0
set /a req3=0
set /a min3=0
set var1=stone
set var2=
set var3=
set var4=sharpened_stone
)
if %errorlevel%==3 (
set item=Spear
set /a req1=%rope_qty%
set /a min1=1
set /a req2=%stick_qty%
set /a min2=1
set /a req3=%sharpened_stone_qty%
set /a min3=1
set var1=rope
set var2=stick
set var3=sharpened_stone
set var4=spear
)
if %errorlevel%==4 (
set item=Handaxe
set /a req1=%rope_qty%
set /a min1=2
set /a req2=%stick_qty%
set /a min2=2
set /a req3=%sharpened_stone_qty%
set /a min3=1
set var1=rope
set var2=stick
set var3=sharpened_stone
set var4=handaxe
)
if %errorlevel%==5 (
set item=Hammer
set /a req1=%rope_qty%
set /a min1=2
set /a req2=%stick_qty%
set /a min2=2
set /a req3=%stone_qty%
set /a min3=1
set var1=rope
set var2=stick
set var3=stone
set var4=hammer
)
::////////////////////////////////////////////////////////////////////////////////////
:craftable_check
if %req1% GEQ %min1% (
if %req2% GEQ %min2% (
if %req3% GEQ %min3% (
::checks minimum requried material inventory for crafting
set /a %var1%_qty=!%var1%_qty!-%min1%
set /a %var2%_qty=!%var2%_qty!-%min2%
set /a %var3%_qty=!%var3%_qty!-%min3%
::uses all the required inventory for crafting
set /a %var4%_qty=!%var4%_qty!+1
::creates the crafted item
set /a inv_%var4%=1
::makes the new item is visible
if %req1% LEQ 0 (
set inv_%var1%=0
)
if %req2% LEQ 0 (
set inv_%var2%=0
)
if %req3% LEQ 0 (
set inv_%var3%=0
)
::makes the items ivisible if there is no inventory
set /a display_message=1
set message='You have successfully created a %item%!'
goto message
)
)
)
set /a display_message=1
set message=You dont have enough material for this
goto message
:://///////////////////////////////////////////////////////////////////////////////////
:message
cls
if %display_message%==1 (
echo %message%
pause
set /a display_message=0
goto start
)
::General Settings ------------------------------------------------------------------------------
#echo off
title Game Template
color 02
cd "%userprofile%\desktop"
::Game Settings ---------------------------------------------------------------------------------
:game_settings
cls
goto welcome
::Welcome Screen --------------------------------------------------------------------------------
:welcome
cls
echo Welcome to this Game!
echo/
echo Please select one of the options below
echo 1. New Game
echo 2. Load Game
echo 3. Credits
choice /c 123
if %errorlevel%==1 goto back_story
if %errorlevel%==2 goto load_game
if %errorlevel%==3 goto credits
goto welcome
::Save Game -------------------------------------------------------------------------------------
:save_game
cls
(
echo %location%
echo %player_name%
)>"GameSave.txt"
echo Game saved...
pause
goto :eof
::Load Game -------------------------------------------------------------------------------------
:load_game
cls
(
set /p location=
set /p player_name=
)<"GameSave.txt"
pause
goto %location%
::Back Story ------------------------------------------------------------------------------------
:back_story
cls
echo Backstory...
pause >nul
goto character_creation
::Character Creation ----------------------------------------------------------------------------
:character_creation
cls
echo What is your name?
set /p player_name=
if /i "%player_name%"=="" (
echo Player name can not be blank.
pause >nul
goto character_creation
)
goto start
::Game Start ------------------------------------------------------------------------------------
:start
cls
set location=start
echo %player_name%
echo %location%
echo/
echo 1. Pause Menu
choice /c 1
if %errorlevel%==1 goto pause_menu
goto start
::Pause Menu ------------------------------------------------------------------------------------
:pause_menu
cls
echo 1. Save Game
echo 2. Return
echo 3. Quit
choice /c 123
if %errorlevel%==1 call :save_game
if %errorlevel%==2 goto %location%
if %errorlevel%==3 goto exit
goto pause_menu
::Credits ---------------------------------------------------------------------------------------
:credits
cls
echo credits...
pause >nul
goto welcome
if %req3% GEQ %min3% (
::checks minimum requried material inventory for crafting
set /a %var1%_qty=!%var1%_qty!-%min1%
won't work properly - :: comments are actually broken labels (labels that cannot be reached with a goto) and break code blocks (parenthesised series of statements)
Reserve a prefix character for any variable that you may want to save to a file for reloading later. EG #
set #>filename
saves all of the variables that start # to the file in the form #whatever=something.
Reload with
for /f "delims=" %%e in (filename) do set "%%e"
Equally, you can set up scenario files by choosing another prefix character.
Clearing the current values of variables-beginning-# is
for/f "delims==" %%e in ('set # 2^>nul') do set "%%e="
which you do just before loading from file.
Use set "var=value" for setting string values - this avoids problems caused by trailing spaces. Don't assign a terminal \, Space or " - build pathnames from the elements - counterintuitively, it is likely to make the process easier. If the syntax set var="value" is used, then the quotes become part of the value assigned.
set up a menu subroutine using choice
:menu
set "choices="
set /a choicecount=0
cls
:menu_next
set /a choicecount+=1
if defined choicetext[%choicecount%] echo %choicecount%. choicetext[%choicecount%]&set "choices=%choices%%choicecount%"
if %choicecount% lss 9 goto menunext
echo Q. Quit
choice /c q%choices% /N /M "%~1"
goto :eof
This way, you can set up the available choices in choicetext[?] (and clear them with
for/f "delims==" %%e in ('set choicetext[ 2^>nul') do set "%%e="
) then display the menu by executing
call :menu "Some message"
When `:menu" returns, you can then
GOTO Someplace%errorlevel%
which will goto someplace2 etc. Note that because q is always the first character of the choices, then q will always return errorlevel 1, hence the label :whatever1 will mean q was pressed. That way, you don't need to alter the quit code should you extend the menu.
(X for eXit works, too.)

Batch File - IF statement issue

Hello to all my fellow StackOverflow members! I am trying to setup a somewhat basic script to help with checking user account details on a domain controller in a domain oriented Corp environment. One of the IT Service managers setup a very watered down script that basically just runs the following command:
net user /domain
I have tried to build a better script since we use this in so many of our customer environments it cuts down on guess work and time overall. The problem is at the end of the script I setup a direct back to the top of the script with a y/n prompt.. however, if you fail to press Y or N (case insensitive) and rather press j or 3 for example the script terminates. I have been extremely unsuccessful in setting up a basic error handling routine that states if the reported value is neither y nor n, echo a simple error string and then repeat the prompt. The following is my code for the setup (I have removed the previously attempts at setting up the looped routine for the y/n values. I have changed the values of the actual paths to each GOTO section so as not to share customer oriented information.
#ECHO OFF
:Start
SET uname=
cls
IF "%userdomain%"=="D1" GOTO 1
IF "%userdomain%"=="D2" GOTO 2
IF "%userdomain%"=="D3" GOTO 3
IF "%userdomain%"=="D4" GOTO 4
:1
ECHO You are on the D1 domain (%userdomain%)
ECHO Usernames should be in the format of firstname.lastname
ECHO.
SET /P uname=Username:
IF "%uname%"=="" GOTO Error
net user %uname% /domain
GOTO Request
:2
ECHO You are on the D2 Domain (%userdomain%)
ECHO Username format varies based on the creation of the ID.
ECHO.
SET /P uname=Username:
IF "%uname%"=="" GOTO Error
net user %uname% /domain
GOTO Request
:3
ECHO You are on the D3 Domain (%userdomain%)
ECHO Usernames are formatted as First Initial Last Name (auser)
ECHO.
SET /P uname=Username:
IF "%uname%"=="" GOTO Error
net user %uname% /domain
GOTO Request
:4
ECHO You are on the D4 Domain (%userdomain%)
ECHO Usernames are formatted as First Initial Last Name (auser)
ECHO.
SET /P uname=Username:
IF "%uname%"=="" GOTO Error
net user %uname% /domain
GOTO Request
:Error
ECHO.
ECHO Username was left blank, please enter a valid username and try again
ECHO.
TIMEOUT /T 5
GOTO Start
:Request
ECHO.
SET /P resp=Do you want to perform another lookup Y/N?
IF /I "%resp%"=="y" GOTO Start
IF /I "%resp%"=="n" exit
In the :Request section above I tried using IF /I NOT and IF NOT /I to begin the statement, as well as using a true false oriented value setting a variable to true, then making the statement say if not y if not n set variable to false, then using if false, repeat the loop, so far hitting any key other than y or n just exits the prompt.
Any help is appreciated, and thanks in advance!
You're using the wrong command, when only known inputs are required, use the choice.exe utility instead:
#ECHO OFF
:Start
CLS
ECHO You are on the D%USERDOMAIN:~-1% domain (%USERDOMAIN%)
ECHO Usernames should be in the format of firstname.lastname
ECHO(
SET "uname="
SET /P "uname=Username: "
IF NOT DEFINED uname GOTO Error
NET USER %uname% /DOMAIN
GOTO Request
:Error
ECHO(
ECHO Username was left blank, please enter a valid username and try again
ECHO(
TIMEOUT /T 5
GOTO Start
:Request
ECHO(
CHOICE /M "Do you want to perform another lookup"
IF NOT ERRORLEVEL 2 GOTO Start
Additional example with message before closing.
#ECHO OFF
:Start
CLS
ECHO You are on the D%USERDOMAIN:~-1% domain (%USERDOMAIN%)
ECHO Usernames should be in the format of firstname.lastname
ECHO(
SET "uname="
SET /P "uname=Username: "
IF NOT DEFINED uname GOTO Error
NET USER %uname% /DOMAIN
GOTO Request
:Error
ECHO(
ECHO Username was left blank, please enter a valid username and try again
ECHO(
TIMEOUT /T 5
GOTO Start
:Request
ECHO(
CHOICE /M "Do you want to perform another lookup"
IF NOT ERRORLEVEL 2 GOTO Start
ECHO(
ECHO Thank you and goodbye.
ECHO Press any key to exit. . .
TIMEOUT /T -1 >NUL

Batch file keeps crashing at if statement

I am making a simple text game. Everything works fine until it gets to the if statement. I do not know what i am doing wrong.
#echo off
title Text Adventures
echo "What is your name?"
set /p name=
echo "That was a bad crash. Are you hurt, %name%?"
echo.
echo Y/N
set /p answer=
if %answer% equ y goto hurt
:hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
Here I have re-written this to be in a form that uses Functions and uses the suggestions I provided to the original post as comments.
You know I assumed incorrectly that you had a purpose to using the labels, but given the way the question has give I think you would do well to not bother with them.
Here is a no-labels version:
#(SETLOCAL
echo off
title Text Adventures
)
CALL :Main
( ENDLOCAL
ECHO. The Script Ended!
PAUSE
EXIT /B
)
:Main
set /p "name=What is Your Name?"
ECHO.
CHOICE /M "That was a bad crash. Are you hurt, %name%?"
If %ERRORLEVEL% equ 1 (
echo.
echo "I see. That's a gnarly gash you've got there!"
) ELSE (
echo.
echo "Oh Good!"
)
PAUSE
GOTO :EOF
Here is the labels version. (I removed the comments explaining how it works and why the code is there so it isn't so cluttered for you.)
#(SETLOCAL
echo off
title Text Adventures
)
CALL :Main
( ENDLOCAL
ECHO. The Script Ended!
PAUSE
EXIT /B
)
:Main
set /p "name=What is Your Name?"
ECHO.
CHOICE /M "That was a bad crash. Are you hurt, %name%?"
If %ERRORLEVEL% equ 1 (
CALL :Hurt
) ELSE (
CALL :NotHurt
)
PAUSE
GOTO :EOF
:Hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
GOTO :EOF
:NotHurt
echo.
echo "Oh Good!"
GOTO :EOF
For this sort of thing I prefer by far using choice, and frequently use my menu macro that returns the selected option as a string in the variable option
below is a shell script that demonstrates the usage of a few macro's I frequently use.
#ECHO Off & Goto :main
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: * Functions * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:+------------------------------------------------------------------------------------------------+:
:ColorString
(For %%C in (%~1)Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31))
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
:ColorMenu
rem Set /A "RR=!random! %%195 + 60","GG=!random! %%195 + 60","BB=!random! %%195 + 60"
rem Set "%~1=%/E%38;2;!RR!;!GG!;!BB!m!%~1!%/E%0m"
Set "rV="& IF "!#A!"=="" (Set #A=32)
(For %%C in ("!%~1!")Do Set "rv=!rV!%/E%!#A!m%%~C%/E%0m"& Set /A "#A+=1"& IF "!#A!"=="37" (Set #A=31)) & Set "%~1=!rV!"
Exit /B 0
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:main * Environment Definition * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Rem /* ensure correct environment for macro definitions */
Endlocal & Setlocal DISABLEdelayedexpansion
:+------------------------------------------------------------------------------------------------+:
For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[")
:+------------------------------------------------------------------------------------------------+:
Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Set "ColLETTERS=Set "Rv="& Set "#A=31" & (For %%A in ("$Str")Do Set "Word=%%~A" & For %%B In (0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z . + - _ [ ] / \ ":")Do Set "Word=!Word:%%~B=%%~B !") & (Call :ColorString "!Word!" & Echo/!rV!)"
Set "ColWORD/S=Set "#A=35"& Set "MSG=$Str" & For %%G in ("!MSG!")Do (For %%v in (%%~G)Do (Set "Rv="&Call :Colorstring "%%~v"& For %%x in (!Rv!)Do (Set "MSG=!MSG:%%~v=%/E%0m%%~x!")))&Echo/!MSG!"
Set "List/D/V=Set "#$L=0"&Set "$$L="&For %%n in (1 2)Do if %%n==2 (For %%G in (!$L!)Do (Set "%%~G" > Nul &Set /A "#$L+=1"))Else Set $L="
Set "Menu=For %%n in (1 2)Do if %%n==2 (!DIV!&Set "CH#=0"&(Set "CHCS="&For %%G in (!Options!)Do For %%i in (!CH#!)Do (Set "CHCS=!CHCS!!ChoList:~%%i,1!"&Set "Opt[!ChoList:~%%i,1!]=%%~G"& Set "Opt=%%~G" &Call :ColorMenu Opt &<Nul Set /P "=[!ChoList:~%%i,1!] !Opt!"&Set /A "CH#+=1"&Echo/))&!DIV!& For /F "Delims=" %%o in ('Choice /N /C:!CHCS!')Do (Set "OPTION=!Opt[%%o]!"))Else Set Options="
Set "ColLINE=For %%n in (1 2)Do if %%n==2 (Echo/!$C!!$Str!%/E%0m)Else Set $Str="
:+------------------------------------------------------------------------------------------------+:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::: * Script Body * :::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Setlocal EnableDelayedExpansion
for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| findstr Columns`) do Set "Console_Width=%%%W"
Set "DIV="&For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"
Set "DIV=Echo/%/E%33m!DIV!%/E%0m"
%List/D/V:$L=Colors%"Red=%/E%31m" "Yellow=%/E%33m" "Green=%/E%32m" "Blue=%/E%34m" "Purple=%/E%35m" "Cyan=%/E%36m" "White=%/E%37m" "Gray=%/E%90m" "Pink=%/E%91m" "Beige=%/E%93m" "Aqua=%/E%94m" "Magenta=%/E%95m" "Teal=%/E%96m" "Off=%/E%0m" "Black=%/E%30m"
%List/D/V:$L=Actions%"Buy a house=Did you win the lotto" "Go for a drive=Start your engines" "Walk on the wild side=Get mauled by a lion" "Run a mile=Fit yet" "flee the realm=fall down a hole" "battle trolls=A losing battle" "puzzle a conundrum=Enigma's Stigmatised" "solve 42=life is meaningless"
%ColLETTERS:$Str=Welcome.%
%ColWORD/S:$Str=Hello there my friend^! How are you today.%
%ColLINE:$C=Teal%What a world we live in^^!
%Menu%"Buy a house" "Go for a drive" "Walk on the wild side" "Run a mile" "flee the realm" "battle trolls" "puzzle a conundrum" "solve 42"
For %%G in ("!Option!")Do Echo/!%%~G!
The menu macro builds a list of choices for each argument it's supplied, using substring modification to iterate over a 36 character choice list to build the final choice options - meaning support for 36 menu options.
Update
An additional example has been added to show a way to use the selection to display output or take actions without requiring conditional testing. Using the List/D/V macro to define values to options, a selected OPTION can be expanded directly. In the example, it's just to display output, however values can be assigned containing simple commands like Set, Goto or call to perform specific actions for the chosen menu option.
I forgot to add pause
#echo off
title Text Adventures
echo "What is your name?"
set /p name=
echo "That was a bad crash. Are you hurt, %name%?"
echo.
echo Y/N
set /p answer=
if %answer% equ y goto hurt
:hurt
echo.
echo "I see. That's a gnarly gash you've got there!"
pause

cmd if script won't work

#echo off
pause
color 0a
mode 1000
set /p apps = where do you want to go to?
echo metrix = 1
echo nothing = 2
pause
if %apps% == 1 goto metrix
if %apps% == 2 goto nothing
:metrix
:start
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random% %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random% %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%
goto start
:nothing
echo nothing
pause
exit
why doesnt it woerk?
I copied it from a tutorial and I have no idea why doesnt it work.
Remove the space before and after "=", in following statement.
set /p apps = where do you want to go to?
Besides CuriousMind's suggestion you should also do the comparison this way:
if "%apps%"=="1" goto metrix
if "%apps%"=="2" goto nothing
Using quotes and removing redundant spaces is safer. You probably also want to write
echo metrix = 1
echo nothing = 2
set /p apps = where do you want to go to?
so that the echos are displayed before the question.

How to ask for batch file user input with a timeout

So I am trying to add a timer to one of my if statements under a set command but I'm not sure what the command would be. The script will launch and wait thirty minutes before it reboots the PC or wait for a users input to input it at that time or cancel it. So I have my two if statements for the "restart now" and "cancel" set but now I need an if statement to have it count down from thirty minutes before it executes my restart command. Also if anyone knows how to add a visual timer on there showing how much time is left that would be a plus. Thanks guys!!!
#Echo off
:START
set /p answer=PC WILL RESTART IN 30 MINUTES, PRESS N TO RESTART NOW OR C TO CANCEL
if "%answer%"=="n" (GOTO Label1)
if "%answer%"=="c" (GOTO Label2)
if "TIMER GOES HERE" "==" (GOTO Label1)
:Label1
shutdown -r -t 60 -f
:Label2
exit
I reccomend using CHOICE.EXE, it comes standard with most versions of Windows (with the exception of Windows NT, 2000 and XP, it used to be downloadable from Microsoft's website, but they seem to have overlooked this* one on their ftp site.) and is simple to use.
#Echo off
:START
set waitMins=30
echo PC WILL RESTART IN %waitMins% MINUTES: Press N to restart [N]ow or C to [C]ancel
:: Calculate Seconds
set /a waitMins=waitMins*60
:: Choices are n and c, default choice is n, timeout = 1800 seconds
choice /c nc /d n /t %waitMins%
:: [N]ow = 1; [C]ancel = 2
goto Label%errorlevel%
:Label1
shutdown -r -t 60 -f
:: Make sure that the process doesn't fall through to Lable2
goto :eof
:Label2
exit
Simply CHOICE.EXE works like this...
choice
...and is the same as...
choice /c yn
...both will display...
[Y,N]?
...and both will wait for the user to press a Y or N.
Choice stores the result in %errorlevel%. Y=1, N=2.
The code I provided takes advantage of the default /D <choice> and timeout /T <seconds> options.
In example...
choice /c yn /d y /t 5
...gives the user a choice of Y or N, will wait for 5 seconds then automaticlly select the default choice of Y, resulting in %ERRORLEVEL%==1.
Another example is...
choice /c abcdef /m "Make a choice. "
...and it displays...
Make a choice. [A,B,C,D,E,F]?
...and...
A = %ERRORLEVEL% = 1
B = %ERRORLEVEL% = 2
C = %ERRORLEVEL% = 3
D = %ERRORLEVEL% = 4
E = %ERRORLEVEL% = 5
F = %ERRORLEVEL% = 6
There is no ERRORLEVEL 0.
For more on the use of choice, type CHOICE /? at the command prompt.
*NOTE The version of CHOICE.EXE I provided a link to uses slightly different commands, but provides the same functionality.
Similar one for hibernate.
#echo off
setlocal enableDelayedExpansion
for /l %%N in (600 -1 1) do (
set /a "min=%%N/60, sec=%%N%%60, n-=1"
if !sec! lss 10 set sec=0!sec!
cls
choice /c:CN1 /n /m "HIBERNATE in !min!:!sec! - Press N to hibernate Now, or C to Cancel. " /t:1 /d:1
if not errorlevel 3 goto :break
)
cls
echo HIBERNATE in 0:00 - Press N to hibernate Now, or C to Cancel.
:break
if errorlevel 2 (%windir%\System32\rundll32.exe powrprof.dll,SetSuspendState Hibernate) else echo Hibernate Canceled
Here is a really simple solution for Vista and Windows 7 that provides the timeout feature, but does not give a visual countdown.
#echo off
choice /c:CN /n /m "PC will restart in 30 minutes. Press N to restart Now, or C to Cancel" /t:1800 /d:N
if errorlevel 2 (shutdown -r -t 60 -f) else echo Restart Canceled
Here is a more complex solution for Vista and Windows 7 that provides a visual countdown, but it clears the console window each second. Also the timing is probably a bit off.
#echo off
setlocal enableDelayedExpansion
for /l %%N in (1800 -1 1) do (
set /a "min=%%N/60, sec=%%N%%60, n-=1"
if !sec! lss 10 set sec=0!sec!
cls
choice /c:CN1 /n /m "PC will restart in !min!:!sec! - Press N to restart Now, or C to Cancel. " /t:1 /d:1
if not errorlevel 3 goto :break
)
cls
echo PC will restart in 0:00 - Press N to restart Now, or C to Cancel.
:break
if errorlevel 2 (shutdown -r -t 60 -f) else echo Restart Canceled
If you need an XP solution then I think you will either need to download a non-native command line tool that asks for input with a timeout feature, or else switch to VBScript or JScript.
EDIT
Both scripts above can be adapted to run on XP by using the CHOICE.EXE download from the Microsoft FTP site that James K provided in his answer.
That version of CHOICE has slightly different syntax.
To adapt my first script, use:
choice /c:CN /n /t:N,1800 "PC will restart in 30 minutes. Press N to restart Now, or C to Cancel"
To adapt my second script, use:
choice /c:CN1 /n /t:1,1 "PC will restart in !min!:!sec! - Press N to restart Now, or C to Cancel. "
EDIT - Here is a crude VBS solution that is compatible with XP
Set objShell = CreateObject("WScript.Shell")
for i = 30 to 1 step -1
if i=1 then unit=" minute" else unit=" minutes"
rtn = objShell.Popup ( _
"The machine would like to Restart."&VbCrLf&VbCrLf& _
"Click OK to restart now"&VbCrLf& _
"Click Cancel or the [X] close button to abort the restart"&VbCrLf& _
"Do nothing and the machine will restart in "&i&unit, _
60, "Restart in "&i&unit, 1+48 _
)
if rtn <> -1 then exit for
next
if rtn <> 2 then objShell.Run "shutdown -r -f"
I think you can provide a more elegant VBS solution using HTA, but that is a lot more work, and I don't really know much about that technology.
I would use this code to make the script pause for a specified number of milliseconds:
PING 1.1.1.1 -n 1 -w <milliseconds> >NUL
This will send out 1 ping to the IP address 1.1.1.1 after <milliseconds> has elapsed. And the output of the ping command will be dismissed to NUL.
I recommend this script by SPC_75
its a .vbs file though, and for hibernate, but its easy to modify for sleep or shutdown.
'//*******************************************
'//hibernate.vbs
'//Purpose: Count Down to action (Hibernate)
'//Tested on Server 2008, Win 7 64bit, and XP
'//Author: SPC_75
'//Revision 1.3
'//Date: 1/09/2011
'//*******************************************
Option Explicit
Dim timeout, objShell, intReturn
Const wshOk = 1
Const wshOkDialog = 0
'Const wshIcon = 16 '/critical
'Const wshIcon = 32 '/question
Const wshIcon = 48 '/exclamation
'Const wshIcon = 64 '/information
timeout = 30 '/Timeout in seconds
Set objShell = CreateObject("Wscript.Shell")
Do Until timeout = 0
timeout = timeout - 1
intReturn = objShell.Popup(vbCrlf &"Hibernation about to initiate. Abort?"&vbCrlf & vbCrlf & vbCrlf & vbCrlf & "Time until hibernation : " & timeout, 1, "Hibernation", wshOkDialog + wshIcon + 4096)
If intReturn = wshOk Then
Wscript.Quit
End If
loop
objShell.Run "powercfg /hibernate on"
objShell.Run "shutdown -h"
objShell.Run "rundll32 powrprof.dll,SetSuspendState Hibernate" '/XP specific Hibernation command
set objShell = nothing
'//EOF
Works perfectly with a warning and timeout.