This question already has an answer here:
Variables are not behaving as expected
(1 answer)
Closed 23 days ago.
I made a batch script that asks the user if they want to do something and they either provide y/n. If the user provides "y" it'll move forward, if they provide "n" the script will exit. Sometimes when providing "y" the script exits anyway. I don't know how to fix this because I haven't seen anyone else with this issue. Here is my script:
#echo off
:check_connection
cls
echo Checking for internet connection...
ping -n 1 google.com >nul 2>&1
if not %errorlevel% == 0 (
echo No internet connection detected. Waiting 15 seconds before trying again.
timeout /t 15 >nul 2>&1
goto check_connection
) else (
echo Internet connection detected. Proceeding with script.
)
:check_nodejs
echo Checking if Node.js is installed...
where npm >nul 2>&1
if %errorlevel% == 0 (
echo Node.js is already installed.
goto check_replugged
) else (
echo Node.js is not installed on this system.
set /p install="Do you want to install it now? (y/n) "
if /i "%install%" == "y" (
goto install_nodejs
) else (
echo Exiting script.
goto :eof
)
)
:install_nodejs
echo Downloading Node.js installer...
bitsadmin /transfer "nodejs_installer" /download /priority high "https://nodejs.org/dist/v18.13.0/node-v18.13.0-x64.msi" "%temp%\node-v18.13.0-x64.msi"
echo Installing Node.js...
start "" /wait msiexec /i "%temp%\node-v18.13.0-x64.msi" /qn
if %ERRORLEVEL% == 0 (
echo Node.js installation successful.
goto check_nodejs
) else (
echo Node.js installation failed. Exiting script.
start "" "https://nodejs.org/en/download/"
goto :eof
)
:check_replugged
echo Checking if replugged is installed...
cd %userprofile%\replugged
if not exist "%userprofile%\replugged" (
set /p install="replugged is not installed on this system. Do you want to install it now? (y/n) "
if /i "%install%" == "y" (
goto install_replugged
) else (
echo Exiting script.
goto :eof
)
) else (
echo replugged is already installed.
goto check_discord
)
:install_replugged
echo Installing replugged...
cd %userprofile%
if not exist "%userprofile%\replugged" (
git clone https://github.com/replugged-org/replugged
)
cd replugged pnpm i && pnpm build
if not %errorlevel% == 0 (
echo Failed to install replugged. Exiting script.
goto :eof
) else (
echo replugged installation successful.
goto check_discord
)
:check_discord
set /p discordversion="Which discord version you want to install replugged on? (stable,ptb,canary,development) [stable]: " /t 20
if "%discordversion%" == "" (set discordversion=stable)
if /i "%discordversion%" == "stable" (
echo Stopping Discord process...
taskkill /f /im discord.exe >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to stop Discord process.
)
) else if /i "%discordversion%" == "ptb" (
echo Stopping DiscordPTB process...
taskkill /f /im discordptb.exe >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to stop DiscordPTB process.
)
) else if /i "%discordversion%" == "canary" (
echo Stopping DiscordCanary process...
taskkill /f /im discordcanary.exe >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to stop DiscordCanary process.
)
) else if /i "%discordversion%" == "development" (
echo Stopping DiscordDevelopment process...
taskkill /f /im discorddevelopment.exe >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to stop DiscordDevelopment process.
)
) else (
echo Invalid input. Exiting script.
goto :eof
)
echo Installing pnpm...
call npm i -g pnpm >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to install pnpm.
)
echo Changing to %userprofile%\replugged directory...
PUSHD %userprofile%\replugged >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to change to %userprofile%\replugged directory.
)
echo Updating global git configuration...
call git config --global --add safe.directory %userprofile%\replugged >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to update global git configuration.
)
echo Pulling latest changes from Git repository...
call git pull >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to pull latest changes from Git repository.
)
echo Unplugging %discordversion%...
call pnpm run unplug %discordversion% >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to unplug %discordversion%.
)
echo Installing dependencies...
call pnpm i >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to install dependencies.
)
echo Building project...
call pnpm run build >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to build project.
)
echo Plugging %discordversion%...
call pnpm run plug %discordversion% >nul 2>&1
if not %errorlevel% == 0 (
echo Failed to plug %discordversion%.
)
echo Launching %discordversion% update process...
if /i "%discordversion%" == "stable" (
START "" "%localappdata%\Discord\Update.exe" --processStart discord.exe
) else if /i "%discordversion%" == "ptb" (
START "" "%localappdata%\DiscordPTB\Update.exe" --processStart discordptb.exe
) else if /i "%discordversion%" == "canary" (
START "" "%localappdata%\DiscordCanary\Update.exe" --processStart discordcanary.exe
) else if /i "%discordversion%" == "development" (
START "" "%localappdata%\DiscordDevelopment\Update.exe" --processStart discorddevelopment.exe
)
echo Restoring original current directory...
POPD
echo Done.
It happens with all inputs hence why I've provided the entire thing
I've tried changing the input to accept both "y " and "y" but neither work.
Few issues:
if %errorlevel% == 0 (
echo Node.js is already installed.
goto check_replugged
) else (
echo Node.js is not installed on this system.
set /p install="Do you want to install it now? (y/n) "
if /i "%install%" == "y" (
goto install_nodejs
) else (
echo Exiting script.
goto :eof
)
)
If errorlevel is 0, the code will goto a label, so the else clause is not required.
Try using
if %errorlevel% == 0 (
echo Node.js is already installed.
goto check_replugged
)
echo Node.js is not installed on this system.
set /p install="Do you want to install it now? (y/n) "
if /i "%install%" == "y" (
goto install_nodejs
)
echo Exiting script.
goto :eof
Next, it's usual practice to add a
setlocal
command directly after the #echo off. The effect is that any changes made to the environment variables made by the script are undone when the script ends. Without that mechanism, you would need to manually reset the variables changed, or initialise the variables you want to use. If you don't reset/initialise the variables, then they retain their values from the previous run, until they are specifically altered.
Next, SET /P "var=Prompt" does not change var if Enter alone is pressed. Consequently, if var is originally empty, it remains empty. Hence, it's advisable that you set the variable used first (sometimes useful to set it to a value to be used by default so the user just needs to press Enter to use the default value)
Finally, your code uses set /p to alter a variable's value within a code block (parenthesised sequence of commands).
Whereas removing the else clauses will make this observation largely redundant for the current code, you need to know about the delayed expansion trap
Within a block statement, 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, not as it may be changed within the (block).
Related
I am currently facing an issue when trying to echo some text in color with a batch script.
My issue only happens when I try to echo in color after another command (git command here) depending on the status code of the previous command : with && or ||.
Example:
#echo off
cls
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
echo %ESC%[92mGreen%ESC%[0m
echo %ESC%[91mRed%ESC%[0m
echo %ESC%[92mGreen%ESC%[0m && echo %ESC%[91mRed%ESC%[0m
git pull || echo %ESC%[92mGreen%ESC%[0m && echo %ESC%[91mRed%ESC%[0m
pause
As you can see, echo in color doesn't work anymore after my git pull command. This will be the same if I use && instead of || and if git pull returns success.
Any idea ?
Thanks.
Just call labels and have the colors referenced inside the labels:
#echo off
cls
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
call :green
call :red
git pull && call :green || call :red
goto :eof
:green
echo %ESC%[92mSuccess%ESC%[0m
goto :eof
:red
echo %ESC%[91mFailed%ESC%[0m
goto :eof
And the result:
Note the sequence of the conditional operators are:
command && errorlevel is 0 || errorlevel is larger than 0
in other words, command and if successful or if not successful
I want to add multiple lines to the hosts file if they're not existing. My code works great but I want to do it for a list of 30 entries and thats where I don't know how to handle it. I thought about a list and a for-loop but I don't know how.
#ECHO OFF
ECHO Checking administrator right.
OPENFILES >NUL 2>&1
IF %ERRORLEVEL% EQU 0 (
ECHO Administrator right detected.
ECHO.
ECHO Hosts file : %WINDIR%\system32\drivers\etc\hosts
ECHO.
SETLOCAL ENABLEDELAYEDEXPANSION
SET BLOCKLINE=127.0.0.1 example.com
ECHO Checking : !BLOCKLINE!
FIND /C /I "!BLOCKLINE!" "%WINDIR%\system32\drivers\etc\hosts" >NUL 2>NUL
IF !ERRORLEVEL! NEQ 0 (
ECHO Line not found, adding to the hosts file.
ECHO !BLOCKLINE!>>%WINDIR%\system32\drivers\etc\hosts
) ELSE (
ECHO Line found.
)
ECHO.
ENDLOCAL
ECHO Patching is completed.
ECHO Check hosts file if you want to see the result.
ECHO.
) ELSE (
ECHO Administrator right not detected.
ECHO You need admin right to use this hosts patch!
ECHO.
)
PAUSE
A basic for loop will suffice.
Define the lines to test in the loop set
For %%L in (
"127.0.0.1 example1"
"127.0.0.30 example30"
) Do (
ECHO Checking : %%~L
FIND /C /I "%%~L" "%WINDIR%\system32\drivers\etc\hosts" >NUL 2>NUL
IF !ERRORLEVEL! NEQ 0 (
ECHO Line not found, adding to the hosts file.
>>"%WINDIR%\system32\drivers\etc\hosts" ECHO %%~L
) ELSE (
ECHO Line found.
)
)
I am struggling with how to make the Energy-Reporter program save dates and rename the files. I am new to Batch programing. I started to learn this language when my OEMCreate DELL Latitude E5500 battery died after about a year. I am attempting to make a program that allows me to monitor and save battery statistic reports to my computer. I am hoping to add the ability to graph battery degradation over time. I attached the current code below. I need to figure out how to make a CMD based File manager.
#echo OFF
TITLE Energy-Reporter
set CUR_YYYY=%date:~10,4%
set CUR_MM=%date:~4,2%
set CUR_DD=%date:~7,2%
set CUR_HH=%time:~0,2%
if %CUR_HH% lss 10 (
set CUR_HH=0%time:~1,1%
set CUR_AP="AM"
)
if %CUR_HH% GEQ 12 (
set CUR_HH=CUR_HH-12
set CUR_AP="PM"
)
set CUR_NN=%time:~3,2%
set CUR_SS=%time:~6,2%
set CUR_MS=%time:~9,2%
set SUBFILENAME="%CUR_MM%-%CUR_DD%-%CUR_YYYY%_At_%CUR_HH%-%CUR_NN%-%CUR_SS% %CUR_AP%"
:: BatchGotAdmin
:-------------------------------------
REM --> Check for permissions
IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" (
>nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system"
) ELSE (
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
)
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params= %*
echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params:"=""%", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"
exit /B
:gotAdmin
pushd "%CD%"
CD /D "%~dp0"
:--------------------------------------
IF EXIST "C:\Program Files\Energy-Report\." (
ECHO DIRECTIORY FOUND
) else (
ECHO CREATING "C:\Program Files\Energy-Report\"
mkdir "C:\Program Files\Energy-Report\"
)
COLOR F4
:USER_SELECTER
CLS
ECHO ===============================================================
ECHO Battery logger
ECHO ===============================================================
ECHO Select an option:
Choice /C codq /N /M "[C]reate power log | [O]pen report | [D]elete log | [Q]uit"
If ErrorLevel 4 GoTo :EOF
If ErrorLevel 3 GoTo DELETE_LOG
If ErrorLevel 2 GoTo SAVED_LOGS
If ErrorLevel 1 GOTO REPORT_DATA
PAUSE
GOTO USER_SELECTER
:REPORT_DATA
cd "C:\Program Files\Energy-Report\"
powercfg -energy
REN "Energy-Report.html" "energy-report_%SUBFILENAME%.html"
PAUSE
GOTO USER_SELECTER
:SAVED_LOGS
cd "C:\Program Files\Energy-Report\"
DIR
PAUSE
GOTO USER_SELECTER
:DELETE_LOG
SET /P Entry_name=log to be erased
DELETE "C:\%Program Files%\Energy-Report\%Entry_name%"
PAUSE
GOTO USER_SELECTER
I have uploaded all of the previous versions of the code to my website for those who are interested in the code development.
If I do not get a chance to update the stack overflow version, The latest version is available by running the code snippet.
<embed style="width:100%;height:100%;"src="https://theelectronichandbook.tech/code/downloads/battery-logger-for-windows/latestcode.php?FRAME=iframe"></embed>
can you help me please?
This piece of script is not running and i can't figure why.
#echo off
ver | findstr /i "5\.1\."
if %ERRORLEVEL% EQU 0 (
set os_ver="xp"
)
ver | findstr /i "6\.1\." > nul
if %ERRORLEVEL% EQU 0 (
set os_ver="7"
)
if %os_ver% == "xp" (
set os_bits="32"
)
if %os_ver% == "7" (
if %PROCESSOR_ARCHITECTURE% == "x86" (
set os_bits="32"
) else (
set os_bits="64"
)
echo %os_bits%
)
pause
it doesn't echo anything despite "ECHO IS DEACTIVATED" or "ECHO IS ACTIVATED"
update:
I posted the entire code, beacause people are saying that it is working
Update2:
I'm on a Windows 7 64 bits
The batch script appears to work fine. It will not echo if your machine is not Windows 7 though.
Try the following:
#echo off
set os_ver="unknown!"
set os_bits="unknown!"
ver | findstr "5\.1" > nul
if %ERRORLEVEL% EQU 0 (
set os_ver="xp"
)
ver | findstr "6\.1" > nul
if %ERRORLEVEL% EQU 0 (
set os_ver="7"
)
if %os_ver% == "xp" (
set os_bits="32"
)
if %os_ver% == "7" (
if %PROCESSOR_ARCHITECTURE% == "x86" (
set os_bits="32"
) else (
set os_bits="64"
)
)
echo os_ver = %os_ver%
echo os_bits = %os_bits%
pause
Update: commenter eryksun has provided the correct reason why this code works while the ops does not even though he is on Windows7. (Good catch)
In the OP's version echo %os_bits% is executed within the same command that sets os_bits. At the time the command is parsed and dispatched os_bits doesn't exist (unless it was already set), so it's just executing echo, which prints whether echo is on or off. – eryksun
Try this:
#echo off
setlocal
if "%PROCESSOR_ARCHITECTURE%" equ "x86" (
set os_bits="32"
) else (
set os_bits="64"
)
echo %os_bits%
I have two cmd files.
child.cmd:
#echo off
exit 1
parent.cmd:
#echo off
cmd /C child.cmd
if %errorlevel% EQU 0 (
echo OK
) else (
echo ERROR
)
If to run parent.cmd, then ERROR will be printed.
But if a little change parent.cmd, then OK will be printed:
#echo off
if "YES" EQU "YES" (
cmd /C child.cmd
if %errorlevel% EQU 0 (
echo OK
) else (
echo ERROR
)
)
Why OK is printed in the second example?
inside a code block you need delayed expansion to access %variables%:
#echo off &setlocal enabledelayedexpansion
if !errorlevel! EQU 0 (
You can also use this syntax without delayed expansion:
if errorlevel 1 if not errorlevel 2 ( echo error )