I have problem about IF ELSE in Command Batch script...
In Notepad:
Code:
:CHECKACCOUNT
if /I "%user%"=="insertusername" ( GOTO :ACCOUNT ) ELSE ( GOTO :CHECKPASSACCT )
:CHECKPASSACCT
if /I "%pass%"=="insertpassword" ( GOTO :ACCOUNT ) ELSE ( GOTO :COUNTER )
In COMMAND:
Code:
( was unexpected at this time.
FULL Script Code:
#echo off
::SETTINGS:::::::::::::::::::::::
set filetxt =userpass.txt
set log=logfile.log
set timer=900
::set default = true
::set user = 0
::set pass = 0
:::::::::::::::::::::::::::::::::
:STARTER
ECHO.>>%log%
ECHO ========START========>>%log%
SetLocal EnableDelayedExpansion
Set n=
Set _InputFile=%filetxt%
For /F "tokens=*" %%I IN (%_InputFile%) DO (
Set /a n+=1
Set acct!n!=%%I
)
set router_ip=%acct1%
set user=%acct2%
set pass=%acct3%
GOTO :CHECKFILE1
:CHECKFILE1
CLS
IF EXIST curl.exe ( GOTO :CHECKFILE2 ) else (
ECHO ERROR: curl.exe was not found.>>%log%
ECHO ERROR: curl.exe was not found.
ECHO.
ECHO.
GOTO :PAUSEEXIT
)
:CHECKFILE2
CLS
IF EXIST sleep.exe ( GOTO :CHECKACCOUNT ) else (
ECHO ERROR: sleep.exe was not found.>>%log%
ECHO ERROR: sleep.exe was not found.
ECHO.
ECHO.
GOTO :PAUSEEXIT
)
:CHECKACCOUNT
if /I "%user%"=="insertusername" GOTO ACCOUNT
GOTO CHECKPASSACCT
:CHECKPASSACCT
if /I "%pass%"=="insertpassword" GOTO ACCOUNT
GOTO COUNTER
:ACCOUNT
CLS
::if %default% = true ( GOTO :COUNTER ) ELSE (
ECHO To edit/change USERNAME and PASSWORD... Please type: OPTION
ECHO.
SET /P user="Please enter the username of your Router:"
IF /I %user%==OPTION ( Goto :EDITBAT )
CLS
ECHO To edit/change USERNAME and PASSWORD... Please type: OPTION
ECHO.
SET /P pass="Please enter the password of your Router:"
IF /I %pass%==OPTION ( Goto :EDITBAT )
CLS
set /a i = 1
GOTO :CHECKACCOUNT
::)
:EDITBAT
start /WAIT notepad %filetxt%
set router_ip=%acct1%
set user=%acct2%
set pass=%acct3%
GOTO :CHECKACCOUNT
:COUNTER
IF %i%==0 ( GOTO :RESETROUTER ) ELSE (
ECHO WAIT %i% seconds...
sleep 1
set /a i = i - 1
CLS
GOTO :COUNTER
)
:RESETROUTER
CLS
ECHO READY to RESET....
ECHO Preparing....
sleep 2
sleep 2
CLS
ECHO Processing....
sleep 5
sleep 2
CLS
ECHO Success....
sleep 5
set /a i = %timer%
CLS
GOTO :COUNTER
:PAUSEEXIT
PAUSE
:EXIT
ECHO.>>%log%
ECHO ========END OF LOG FILE========>>%log%
Your error as seen comes from wrong formatting. Don't put it all on 1 line. Instead use this:
if /I "%user%"=="insertusername" (
GOTO :ACCOUNT
) ELSE (
GOTO :CHECKPASSACCT
)
The deeper, underlying reason is: goto :somewhere command needs to be terminated by a newline.
You can simplify this down to:
:CHECKACCOUNT
if /I "%user%"=="insertusername" GOTO ACCOUNT
GOTO CHECKPASSACCT
:CHECKPASSACCT
if /I "%pass%"=="insertpassword" GOTO ACCOUNT
GOTO COUNTER
The ELSE statements aren't needed. Since the IF block will jump somewhere else, placing the second GOTO on the next line or in an ELSE block should be equivalent.
Also, you need the leading colon when defining a GOTO target but not when referring to the target name inside the GOTO statement itself.
The problem has nothing to do with the shown code!
The problem is at
:COUNTER
IF %i%==0 ( GOTO :RESETROUTER ) ELSE (
As the variable i isn't defined, the line will be expanded to
IF ==0 ( GOTO :RESETROUTER ) ELSE (
That is an invalid expression.
To find such simple syntax fails, you should enable debugging with ECHO ON.
You don't need to use the parentheses. You're basically telling the system
"if %user% is insertusername (" and it's asking "what is the '(' supposed to do?"
Related
I have fully working batch file, that I use to copy n then run BCU utility on remote computer, with variable that is set in the beginning %MyPC% and then used across whole script.
My question is, is it possible to use list with computer names, instead of single one?
I tried to use set and for, with no success.
#echo off
echo.
set instpath = %~s0..
cls
:input
for /f %%a in (zarizeni.txt) do set MyPC=%MyPC% %%a
cls
mkdir \\%MyPC%\c$\Tempbios
copy BCU.EXE \\%MyPC%\C$\Tempbios
copy psexec.EXE \\%MyPC%\C$\Tempbios
echo Soubory zkopirovany /pokud nevidis 0 ci chybu
#echo off
title HP BIOS Tool by JN
:home
cls
echo.
echo VYBER U CEHO ZJISTUJES USB BOOT ENABLE/DISABLE
echo ==================================================
echo.
echo 1) Notebook info
echo 2) PC info
echo 3) Nejsem si jist
echo 4) Kompletni log
echo 5) Ulozit log
echo 6) Exit
echo.
echo ==================================================
echo.
set /p web=Zadej volbu a potvrd:
if "%web%"=="1" goto 1
if "%web%"=="2" goto 2
if "%web%"=="3" goto 3
if "%web%"=="4" goto 4
if "%web%"=="5" goto 5
if "%web%"=="6" exit
goto home
Choice /C 12345 /M "USB/STORAGE BOOT INFO - Notebook[1] nebo PC[2] | Nejsem si jist [3] Kompletni BIOS log [4] | Ulozeni logu [5] ?
If Errorlevel 5 Goto 5
If Errorlevel 4 Goto 4
If Errorlevel 3 Goto 3
If Errorlevel 2 Goto 2
If ErrorLevel 1 Goto 1
Goto End
:5
cls
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getconfig
Goto End
:4
cls
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /get >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
Goto End
:3
cls
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getvalue:"USB Storage Boot" >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getvalue:"USB device Boot" >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getvalue:"Removable Media Boot" >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
Goto End
:2
cls
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getvalue:"Removable Media Boot" >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
Goto End
:1
cls
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getvalue:"USB Storage Boot" >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
psexec.exe \\%MyPC% C:\Tempbios\BCU.exe /getvalue:"USB device Boot" >> "\\czcscdeploy31\Kopirovani\HPBIOS\%MyPC%.txt"
:End
pause
echo : LOG je ulozen na \\czcscdeploy31\Kopirovani\HPBIOS\%.txt
start \\czcscdeploy31\Kopirovani\HPBIOS\
echo : Opravdu chcete po sobe zamest stopy?
del \\%MyPC%\C$\Tempbios
rd \\%MyPC%\C$\Tempbios
I use the following function in a lot of my VBA projects. I initially added the reference to Windows Script Host Object model to take advantage of Intellisense, but then switched to late binding so I didn't have to reference a bunch of stuff.
Private Function RunCMD(ByVal strCMD As String) As String
'Runs the provided command
Dim oShell As Object 'New WshShell
Dim cmd As Object 'WshExec
Dim x As Integer
Const WshRunning = 0
On Error GoTo wshError
x = 0
RunCMD = "Error"
Set oShell = CreateObject("Wscript.Shell")
Set cmd = oShell.Exec(strCMD)
'Debug.Print strCMD
'Stop
Do While cmd.Status = WshRunning
Sleep 100 'for 1/10th of a second
x = x + 1
If x > 1200 Then 'We've waited 2 minutes so kill it
cmd.Terminate
MsgBox "Error: Timed Out", vbCritical, "Timed Out"
End If
Loop
RunCMD = cmd.StdOut.ReadAll & cmd.StdErr.ReadAll
Set oShell = Nothing
Set cmd = Nothing
Exit Function
wshError:
On Error Resume Next
RunCMD = cmd.StdErr.ReadAll
Resume Next
End Function
It works great when you do something like
RunCMD("ping www.bing.com") or
RunCMD("winrs -r:" & strHost & " reg query hklm\system\currentcontrolset\services\cdrom /v start")
However RunCMD("Dir c:\config* /a:-d /b /d /s") fails, and cmd.StdErr.ReadAll gives an Object Variable or With Block not set error. Even a simple RunCMD("Dir") fails.
Why does DIR make the WScript shell crap out? More importantly, how can I use CMD's DIR function (not VBA's DIR function!) to get a list of files that match a search pattern?
Does it work if you preface your dir command with "cmd /c " and wrap your DOS command in double quotes, like
RunCmd("cmd /c ""DIR""")
or
RunCmd("cmd /c ""Dir c:\config* /a:-d /b /d /s""")
I'm trying to create a batch file that checks if
the directory C:\Pswrd.Zask,
the user name file C:\Pswrd.Zask\Username.Zask,
and the password file C:\Pswrd.Zask\Password.Zask
all exist.
The batch processing should continue on PasswordScreen if the two files in the directory exist.
But batch processing should continue on CreatePasswordScreen if they don't exist all.
The create CreatePasswordScreen block asks for user input. That input is then stored into a file named Password.Zask & Username.Zask inside the folder C:\Pswrd.Zask.
On second run of the program, the program checks existence of that folder, the user name file and the password file, and then sets the user name & password from the two files in C:\Pswrd.Zask to variables right before the PasswordScreen block which will be used to determine if the password is correct or not.
The problem is that I cannot get the password and user name to store correctly in the batch file as a variable without the batch process ultimately coming to a end for an unknown reason.
Did I miss use a command?
The problem should be right under then line that says :UsernameExist.
#echo off
color 0a
if not exist "C:\Pswrd.Zask\" (
mkdir "C:\Pswrd.Zask\"
if "!errorlevel!" EQU "0" (
goto DirectoryExist
) else (
echo Created the folder "C:\Pswrd.Zask"
)
) else (
goto DirectoryExist
)
:DirectoryExist
if exist C:\Pswrd.Zask\Password.Zask (
goto PasswordExist
) else (
goto CreatePasswordScreen
)
:PasswordExist
if exist C:\Pswrd.Zask\Username.Zask (
goto UsernameExist
) else (
goto CreatePasswordScreen
)
:UsernameExist
for /f "Delims=" %%A in (C:\Pswrd.Zask\Password.Zask) do (
set CHECKPASSWORD=%%A
for /f "Delims=" %%B in (C:\Pswrd.Zask\Username.Zask) do (
set CHECKUSERNAME=%%B
goto PasswordScreen
:CreatePasswordScreen
cls
echo Create a password.
echo.
set /p "CREATEPASSWORD= Enter password : "
set /p "CREATEUSERNAME= Enter username : "
echo %CREATEPASSWORD% >> C:\Pswrd.Zask\Password.Zask
attrib C:\Pswrd.Zask\Password.Zask -s -h & echo Password Created!
echo %CREATEUSERNAME% >> C:\Pswrd.Zask\Username.Zask
attrib C:\Pswrd.Zask\Username.Zask -s -h & echo Username Created!
echo.
echo Loading...
timeout /5
:PasswordScreen
color 0a
cls
echo Existing User Account.
echo.
set /p "PASSWORD= Enter Password : "
set /p "USERNAME= Enter Username : "
if %PASSWORD%==%CHECKPASSWORD% goto Operation1True
if not %PASSWORD%==%CHECKPASSWORD% goto OperationFalse
:Operation1True
if %PASSWORD%==%CHECKPASSWORD% goto Operation2True
if not %PASSWORD%==%CHECKPASSWORD% goto OperationFalse
:OperationFalse
color 0c
echo Password Incorrect!
timeout /10
goto PasswordScreen
:Operation2True
cls
echo Password Correct!
pause
I figured out the solution, i chanced it to the following.
#echo off
color 0a
if not exist "C:\Pswrd.Zask\" (
mkdir "C:\Pswrd.Zask\"
if "!errorlevel!" EQU "0" (
goto DirectoryExist
) else (
echo Created the folder "C:\Pswrd.Zask" & timeout /t 5
)
) else (
goto DirectoryExist
)
:DirectoryExist
if exist C:\Pswrd.Zask\Password.Zask (
goto PasswordExist
) else (
goto CreatePasswordScreen
)
:PasswordExist
if exist C:\Pswrd.Zask\Username.Zask (
goto UsernameExist
) else (
goto CreatePasswordScreen
)
:UsernameExist
for /f "Delims=" %%A in (C:\Pswrd.Zask\Password.Zask) do (
set CHECKPASSWORD=%%A
)
for /f "Delims=" %%B in (C:\Pswrd.Zask\Username.Zask) do (
set CHECKUSERNAME=%%B
)
goto PasswordScreen
:CreatePasswordScreen
cls
echo Create a password.
echo.
set /p "CREATEPASSWORD= Enter password : "
set /p "CREATEUSERNAME= Enter username : "
echo %CREATEPASSWORD% >> C:\Pswrd.Zask\Password.Zask
attrib C:\Pswrd.Zask\Password.Zask +s +h & echo Password Created!
echo %CREATEUSERNAME% >> C:\Pswrd.Zask\Username.Zask
attrib C:\Pswrd.Zask\Username.Zask +s +h & echo Username Created!
start %~n0%~x0
exit
:PasswordScreen
color 0a
cls
echo Existing User Account.
echo.
set /p "PASSWORD= Enter Password : "
set /p "USERNAME= Enter Username : "
if %PASSWORD%==%CHECKPASSWORD% (
goto Operation1True
) else (
goto OperationFalse
)
:Operation1True
if %USERNAME%==%CHECKUSERNAME% (
goto Operation2True
) else (
goto OperationFalse
)
:OperationFalse
color 0c
echo Password Incorrect!
timeout /t 10
goto PasswordScreen
:Operation2True
cls
echo Password Correct!
echo.
pause
I am working on a database using a bat file an my variables are not expanding the right way.
Edit:
I have tried the above and have had no such luck.
This is all of the code necessary to show:
set n=0
:1
echo.
set /p fname=Enter First Name:
set /p lname=Enter Last Name:
set /p val%n%=Enter E-mail:
set /p num%n%=Enter Phone Number:
set /p var%n%=Enter Service Number:
set /p dvice%n%=Enter Device:
set /p dserv%n%=Enter Date Serviced:
set /p summ%n%=Enter Summary of Service:
#echo set var%n%=!var%n%! > "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set val%n%=!val%n%! >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set fname=%fname% >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set lname=%lname% >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set dvice%n%=!dvice%n%! >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set dserv%n%=!dserv%n%! >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set summ%n%=!summ%n%! >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set num%n%=!num%n%! >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
#echo set n=%n% >> "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
echo.
echo The data has been stored!
echo.
pause > nul
goto start
:2
echo.
echo LAST NAME IS CASE SENSITIVE!
set /p lname=Please enter last name:
echo.
if /i not exist "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat" (goto Error)
call "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
echo First Name: %fname%
echo Last Name: %lname%
echo Device: !%dvice%%n%!
echo Date of Service: !dserv%n%!
echo.
echo E-Mail: !val%n%!
echo Phone: !num%n%!
echo.
echo Summary:
echo.
echo !summ%n%!
echo.
pause > nul
goto start
This is all I have to work with. The %lname%.bat stores variables as var0="value of variable" The problem is that it is not reading var0. It reads !var 0!.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a n=0
:: call "C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat"
:start
call :plname
echo First Name: %fname%
echo Last Name: %lname%
echo Device: !%dvice%%n%!
echo Date of Service: !dserv%n%!
echo.
echo E-Mail: !val%n%!
echo Phone: !num%n%!
echo.
echo Summary:
echo.
echo !summ%n%!
echo.
SET /a n+=1
IF %n% lss 2 goto START
GOTO :EOF
:plname
SET "fname=First name read"
SET "lname=Last name read"
SET "dvice0=Device zero"
SET "dvice1=Device one"
SET "dserv0=Date zero"
SET "dserv1=Date one"
SET "val0=Email zero"
SET "val1=Email one"
SET "num0=Phone zero"
SET "num1=Phone one"
SET "summ0=Summary zero"
SET "summ1=Summary one"
GOTO :EOF
This batch proves that your code does work. The problem is with your %lname%.bat which you haven't posted. Surely you don't set up a different %lname%.bat for each customer?
No harm in posting some real sample data - just change the names to protect the guilty. Modify the real names to "Brown" or "Green" or "Robinson." No-one appears to use those names any more - they're obviously fake.
When calling the script, a new instance of cmd is running. The variables set are only available to that instance.
set filepath=C:\Documents and Settings\Administrator\Desktop\My Personal Files\Computer Refresh\Database\%lname%.bat
for /f "delims=" %%a in (%filepath%) do %%a
This will loop through each line of %lname%.bat and run that line as a command - if all of the lines in %lname%.bat are those set commands, this should work.
I'm trying to figure how to return multiple variables, in a rather dynamic fashion where I just maintain a list of variable names and then do the ENDLOCAL "export" with a loop, but it seems the !%%V! expansion in the inner FOR loop isn't expanding soon enough or so.
Is there something I'm missing or is there another way to accomplish this?
Example code:
SETLOCAL EnableExtensions EnableDelayedExpansion
[...]
SET "RETURN=FOO BAR"
[...]
SET "RETURN=%RETURN% BAZ"
[...]
:END
:: "Export" %FOO%, %BAR%, and %BAZ% to calling context.
ENDLOCAL & (
FOR %%N IN (%RETURN%) DO (
FOR /f %%V in ("%%N") DO SET %%N=!%%V!
)
)
EXIT /B
Thank you for any help.
Here is a return routine for preserving variables across scope. Just call the return routine with the variables names as parameters and then call endlocal %return%.
Routine:
:return [Variables...]
setlocal enabledelayedexpansion
set "return="
:_return
if "%~1"=="" endlocal & exit /b 1
if not defined %~1 goto __return
set "%~1=!%~1:"=""!"
set "%~1=!%~1:^=^^!"
set "%~1=!%~1:<=^<!"
set "%~1=!%~1:>=^>!"
set "%~1=!%~1:&=^&!"
set "%~1=!%~1:|=^|!"
:__return
set "return=!return!^&set ""%~1=!%~1!"""
if not "%~2"=="" shift & goto _return
setlocal disabledelayedexpansion
set "return=%return:!=^^^^^^^!%"
endlocal & endlocal & set "return=%return:""="%"
exit /b 0
Usage:
call :return foo bar baz
endlocal %return%
Example:
Only variable a will be preserved outside the scope.
#echo off
setlocal
echo Inside
set "a=1"
set "b=2"
echo(%a%
echo(%b%
call :return a
endlocal %return%
echo Outside
echo(%a%
echo(%b%
exit /b 0
:return [Variables...]
setlocal enabledelayedexpansion
set "return="
:_return
if "%~1"=="" endlocal & exit /b 1
if not defined %~1 goto __return
set "%~1=!%~1:"=""!"
set "%~1=!%~1:^=^^!"
set "%~1=!%~1:<=^<!"
set "%~1=!%~1:>=^>!"
set "%~1=!%~1:&=^&!"
set "%~1=!%~1:|=^|!"
:__return
set "return=!return!^&set ""%~1=!%~1!"""
if not "%~2"=="" shift & goto _return
setlocal disabledelayedexpansion
set "return=%return:!=^^^^^^^!%"
endlocal & endlocal & set "return=%return:""="%"
exit /b 0
Problem in your code
As for why your code is not working as you expect, is because the variable must be expanded before the endlocal command is run. Read this excellent SO post about host the command line parses batch scripts: Answer: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Update
Added support for the following special characters | & < > " ^ !
All special characters supported
Return empty variables as well
https://raw2.github.com/DavidRuhmann/BAT/master/SO21736349891976.bat
:: "Export" %FOO%, %BAR%, and %BAZ% to calling context.
for %%a in ("endlocal" "FOO=%FOO%" "BAR=%BAR%" "BAZ=%BAZ%") do (
if %%a equ "endlocal" (endlocal) else set %%a
)
exit /B
How about
#ECHO OFF
SETLOCAL
FOR %%i IN (foo bar baz) DO SET $%%i=value:%%i
ECHO == initial values ===
SET $
SET "RETURN=$FOO $BAR"
CALL :demo
ECHO == after CALL modifying %return% ===
SET $
FOR %%i IN (foo bar baz) DO SET $%%i=value:%%i
ECHO == initial values ===
SET $
SET "RETURN=%RETURN% $BAZ"
CALL :demo
ECHO == after CALL modifying %return% ===
SET $
GOTO :eof
:demo
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%i IN (foo bar baz) DO SET $%%i=modified:%%i
SET "$retvals="
FOR %%N IN (%RETURN%) DO SET "$retvals=!$retvals!^&set %%N=%%%%N%%"
CALL SET "$retvals=%$retvals%"
:: "Export" %FOO%, %BAR%, and %BAZ% to calling context.
endlocal%$retvals%
EXIT /B
GOTO :EOF
Yielding
== initial values ===
$bar=value:bar
$baz=value:baz
$foo=value:foo
== after CALL modifying $FOO $BAR ===
$bar=modified:bar
$baz=value:baz
$foo=modified:foo
== initial values ===
$bar=value:bar
$baz=value:baz
$foo=value:foo
== after CALL modifying $FOO $BAR $BAZ ===
$bar=modified:bar
$baz=modified:baz
$foo=modified:foo
(I just changed the varnames for convenience of display using set)