I would like to know why do I get an error("( was not expected at this time") in this script.
for /f "delims=" %%t in (%cd%\Multitool\Multitool.txt) do (
set /p username=
set /p password=
set /p created=
)
if %created%==accountcreated ( goto CONTINUE ) else ( goto CREATE )
I have those lines of codes wich always get me an error: "( was not expected" at this time.
In my program I want to know if the user created an account already...
When the user creates an account I echo this in %cd%\Multitool\Multitool.txt :
(
echo %username%
echo %password%
echo accountcreated
) > %cd%\Multitool\Multitool.txt
So can you tell me why I get that error and how to correct it please?
Sorry for my bad english im french...
#ECHO OFF
SETLOCAL enabledelayedexpansion
:: set up logfile and password
SET "logfile=U:\q28542185.txt"
SET "password=dummypassword"
SET "myusername=dummyusername"
:: Dummy log entry
(
echo %myusername%
echo %password%
echo accountcreated
) > %logfile%
:: This is just to ensure the three variables are empty
FOR %%t IN (myusername password created) DO SET "%%t="
for /f "delims=" %%t in (%logfile%) do (
SET "myusername=!password!"
SET "password=!created!"
SET "created=%%t"
)
if %created%==accountcreated ( goto CONTINUE ) else ( goto CREATE )
:continue
ECHO got to continue
GOTO :eof
:create
ECHO got to create
GOTO :EOF
I used a file named q28542185.txt to receive the log information for my testing.
Note that username is a magic variable initialised by the syste, so I don't like changing it, so I've substituted myusername.
The first part sets up a dummy log file for testing.
The replacement for loop reads the log file and "ripples" the lines through the variablenames using the delayedexpansion facility, so that the variables are set in appropriate sequence.
Note that if created contains Spaces then your if statement should be modified to
if "%created%"=="accountcreated" ....
to allow correct parsing sequence IF token operator token
Related
In attempting a proof of concept, we a script run by our desk for the creation of user home directories, group membership, profile, set home directory, etc.
I'd like to add a section that checks whether the account has the lastLogonTimeStamp (LLTS) value set in AD. I'm able query the user in AD. What I'm unable to figure out is how to parse out and run separate steps in the .cmd file whether there's a value in the LLTS attribute vs no value. I don't need to look at the age, just whether it's there or not. I believe my issue is that I'm getting a string returned when I'm trying to compare a value, and if the LLTS isn't present, I'm not sure if it's a zero value or a null value.
I understand there may be better ways to do this using PS or VBS, but we're not at that point of converting our scripts, but we'd like to try an figure out this piece.
Here's what I have so far as a POC / test.
#echo off
:START
cls
echo Enter EMP ID
set /p EMPID=
SetLocal EnableDelayedExpansion
set count=0
:: queries for the existence of the lastLogonTimeStamp value
for /F "delims=" %%a in ('dsquery * domainroot -filter "(&(objectCategory=Person)(objectClass=User)(samaccountname=%empid%))" -attr lastLogonTimeStamp') do (
set LLTS=%%a
set /a count=!count! + 1
if %%a GTR 1 GOTO COMPARE
)
:COMPARE
echo.
echo OLD-LLTS=%LLTS%
set MODLLTS=%LLTS: =%
echo MOD-LLTS=%MODLLTS%
IF %MODLLTS% GTR 1 GOTO HAS
:HASNOT
:: Run these commands if the lastLogonTimeStamp is not present
ECHO Has NO previous Logon info.
pause
GOTO END
:HAS
:: Run these commands if the lastLogonTimeStamp is present, regardless of value.
ECHO Has previous Logon info.
w32tm.exe /ntte %MODLLTS%
pause
GOTO END
:END
EXIT
Here's example output with a user has previously logged in:
administrator
lastLogonTimeStamp
131545455582093968
Here's example output with a user who's never logged in:
guest
lastLogonTimeStamp
Note:There's an empty linebelow the attribute name for the guest that's not showing in the preview.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q47309403.txt"
SET "filename2=%sourcedir%\q47309403_2.txt"
FOR %%a IN (logonname logonjunktext logontimestamp) DO SET "%%a="
FOR /f "usebackqdelims= " %%a IN ("%filename1%") DO (
IF DEFINED logonname (
IF DEFINED logonjunktext (
SET "logontimestamp=%%a"
) ELSE (
SET "logonjunktext=%%a"
)
) ELSE (
SET "logonname=%%a"
)
)
:done1
ECHO name=%logonname% junk text=%logonjunktext% timestamp=%logontimestamp%
FOR %%a IN (logonname logonjunktext logontimestamp) DO SET "%%a="
FOR /f "usebackqdelims= " %%a IN ("%filename2%") DO (
IF DEFINED logonname (
IF DEFINED logonjunktext (
SET "logontimestamp=%%a"
) ELSE (
SET "logonjunktext=%%a"
)
) ELSE (
SET "logonname=%%a"
)
)
:done2
ECHO name=%logonname% junk text=%logonjunktext% timestamp=%logontimestamp%
GOTO :EOF
I used files named q47309403.txt, q47309403_2.txt containing your data for my testing. Obviously, replace such with your dsquery command.
The code is simply the same, repeated for each file for demo purposes.
The data reported in the variables should enable you to derive any consequential actions, if your report on the dsquery output is representative.
Operation is simply clear three variables, then accumulate each depending on the defined state for the variable.
I'm trying to make a reminder system within batch in which there are different lines of reminders. My batch program will write to different lines in a .txt file, but it isn't working. Could you please help and try to find the issues?
#echo off
echo Enter slot # for reminder
set /p n=
cls
echo Please type in the assignment name
set /p a=
echo ----------------------------------
echo Please type in the class
set /p c=
echo ----------------------------------
echo Please type in the date due
set /p d=
cls
if %n%==1 goto l1
if %n%==2 goto l2
if %n%==3 goto l3
if %n%==4 goto l4
if %n%==5 goto l5
if %n%==6 goto l6
:l1
echo Reminder for %c% Homework! %a%,%d% > Reminder.txt
:end
:l2
echo Reminder for %c% Homework! %a%,%d% >> Reminder.txt
:end
:l3
echo Reminder for %c% Homework! %a%,%d% >>> Reminder.txt
:end
:l4
echo Reminder for %c% Homework! %a%,%d% >>>> Reminder.txt
:end
:l5
echo Reminder for %c% Homework! %a%,%d% >>>>> Reminder.txt
:end
:l6
echo Reminder for %c% Homework! %a%,%d% >>>>>> Reminder.txt
:end
Hints to fix what you've got:
The > character won't let you write to specific lines, and there's no native support in Windows batch to do such a thing.
There are two operators that use the > character: >, which redirects output to a file (replacing any existing content), and >>, which appends (adds to the end of) a file.
You've got multiple instances of :end, but that's invalid. :end is a label, which is a unique reference to that point in the code. When you add more than one, some get ignored and you get undefined behaviors, which is bad.
It looks like you're trying to use :end to exit. Use goto :EOF for that. It jumps to the built-in label :EOF, short for End Of File.
You need to handle the case where n is none of the predefined values. Currently if someone entered 7 for n, your program would get to the logic after :l1 and run it, which is wrong. Put a goto :EOF there just in case.
How to approach solving this type of issue with batch:
The only way I can think of off the top of my head to modify a specific line is to iterate through all lines using a for /f loop, rewriting each line (to a temporary file) until you encounter the one you want to change, then write your new content instead of the existing content. Then when you're done iterating, you can replace the original file with that temporary file.
You would have to do this each time you wanted to change a new line. Batch is a really simple language that doesn't have useful constructs like arrays, or the many external tools that a shell scripting language like Bash would have. It's also got some really unsophisticated runtime evaluation.
Here's a partial solution that you can combine with a few lines from your code above to achieve what you want. It prompts you for a line number, then puts the content of the newContent variable (replace with your implementation) into the file at the specified line:
REM suppresses the echo of the commands in the program
#ECHO OFF
REM sets a feature that overcomes some of the weak runtime evaluation limitations that batch has
setlocal ENABLEDELAYEDEXPANSION
REM The name of your file
set fname=file.txt
REM If our file doesn't already exist, make a new one with 6 empty lines since that's all we want for now.
if EXIST "%fname%" goto alreadyExists
for /l %%b in (1,1,6) do echo.>>"%fname%"
:alreadyExists
REM The name of a temp file
set tfile=f2.txt
REM A counter to track the line number
set counter=0
REM Input to get the line number you wish to replace
set /p replacementLine=Type the line number that should be replaced:
REM The content that goes on the replaced line
set newContent=New entry
REM Read the file, iterate through all lines.
for /f "tokens=*" %%a in (file.txt) do (
REM Add one to the counter
set /a counter=!counter!+1
REM Use the redirect '>' operator for the first line
if "!counter!"=="1" (
if "!counter!"=="%replacementLine%" (
REM We're on the line we wish to replace, so use the replacement line content
echo.%newContent% >f2.txt
) else (
REM We're NOT on the line we wish to replace, so use the original line content
echo.%%a >f2.txt
)
) else (
REM else for lines other than the first, use the append redirect '>>'
if "!counter!"=="%replacementLine%" (
REM We're on the line we wish to replace, so use the replacement line content
echo.%newContent% >>f2.txt
) else (
REM We're NOT on the line we wish to replace, so use the original line content
echo.%%a >>f2.txt
)
)
)
REM Delete the original file
del "%fname%"
REM Replace it with the modified copy
ren "%tfile%" "%fname%"
You can replace a few lines at the top get the functionality you want.
you can't write to a specific line in a file with batch. Instead you have to rewrite the complete file.
Steps: a) read the file. b) change the desired line. c) (over)write the file with the new data.
#echo off
setlocal enabledelayedexpansion
if not exist reminder.txt call :InitFile :: create the file, if it doesn't exist
set /p "n=Enter slot # for reminder: "
set /p "a=type in the assignment name: "
set /p "c=type in the class: "
set /p "d=type in the date due: "
cls
call :ReadFile
set "_Line[%n%]=Reminder for %c% Homework: %a%,%d%"
call :WriteFile
type Reminder.txt
goto :eof
:ReadFile
set x=0
for /f "delims=" %%i in (reminder.txt) do (
set /a x+=1
set "_Line[!x!]=%%i"
)
goto :eof
:WriteFile
set x=0
(for /f "tokens=2 delims==" %%i in ('set _Line[') do echo %%i)>Reminder.txt
goto :eof
:InitFile
(for /l %%i in (1,1,6) do echo Reminder %%i [empty])>Reminder.txt
goto :eof
(Note: this would make trouble with more than 9 lines because of the alphabetical sorting with set _line[, but as you need only 6 lines, this should not be a problem for you)
Note: your input shouldn't contain !
I'm trying to make a short BAT file and I'm having trouble with one of its functions. I've tried a number of different ways to do this and none of them seem to work, but being a beginner at this I can't figure out the problem. Basically, the script, as it runs, is supposed to check if a certain .BAT file exists, and if it does, the script asks if the user wants to run it. If the user indicates Y, the other BAT is called and then the original script proceeds. If the user indicates N, the script is supposed to proceed without calling the other BAT. So far the script always notices and asks about the file, but choosing Y at the prompt never works. I'm sure the solution is obvious, but it's escaping me. Here's the code:
SET /P kmname=Enter database name:
:kmstart
IF EXIST C:\Visual\area\%kmname%\%kmname%.flt (
ECHO %kmname%.flt found, will now create %kmname%.ive.
CD C:\Visual\area\%kmname%\
IF EXIST Preprocess.bat (
SET /P kmpreproc=Found Preprocess.bat. Do you want to run it now?
IF /I "%kmpreproc%" EQU "Y" (
GOTO PREPROC
) ELSE (
GOTO CONTINUE
)
)
GOTO CONTINUE
) ELSE (
ECHO C:\Visual\area\%kmname%\%kmname%.flt does not exist. Try again.
SET /P kmname=Enter database name:
GOTO kmstart
)
:PREPROC
ECHO Running Preprocess.bat.
:CONTINUE
ECHO Continuing process.
PAUSE
The problem is your variables are being evaluated before they enter the if's, which means cmd won't see any changes until they have ended.
This is causing problems for you as your variables kmpreproc and, depending on the first if result, kmname change within the if blocks.
The fix (presuming the rest of your code is working) is to enable delayed expansion and use delayed expansion instead of normal expansion, by changing the %'s to ! on your variables.
setlocal enabledelayedexpansion
SET /P kmname=Enter database name:
:kmstart
IF EXIST C:\Visual\area\!kmname!\!kmname!.flt (
ECHO !kmname!.flt found, will now create !kmname!.ive.
CD C:\Visual\area\!kmname!\
IF EXIST Preprocess.bat (
SET /P kmpreproc=Found Preprocess.bat. Do you want to run it now?
IF /I "!kmpreproc!" EQU "Y" (
GOTO PREPROC
) ELSE (
GOTO CONTINUE
)
)
GOTO CONTINUE
) ELSE (
ECHO C:\Visual\area\!kmname!\!kmname!.flt does not exist. Try again.
SET /P kmname=Enter database name:
GOTO kmstart
)
:PREPROC
ECHO Running Preprocess.bat.
:CONTINUE
ECHO Continuing process.
PAUSE
Here is below my corrected and tided up code :
#echo off
SET /P kmname=Enter database name:
:kmstart
IF EXIST C:\Visual\area\%kmname%\%kmname%.flt (
ECHO %kmname%.flt found, will now create %kmname%.ive.
CD C:\Visual\area\%kmname%\
IF EXIST Preprocess.bat (
SET /P kmpreproc=Found Preprocess.bat. Do you want to run it now?
IF /I "%kmpreproc%"=="Y" (
GOTO PREPROC
)
GOTO CONTINUE
)
)
ECHO C:\Visual\area\%kmname%\%kmname%.flt does not exist. Try again.
SET /P kmname=Enter database name:
GOTO kmstart
:PREPROC
ECHO Running Preprocess.bat.
call "cmd /c start Preprocess.bat"
pause
:CONTINUE
ECHO Continuing process.
PAUSE
If it doesn't work try writting setlocal EnableDelayedExpansion under #echo off and replacing all % with ! .
The code is as follows,
#echo off
if not exist c:\Locker (
cd/
md Locker
cd windows\system32
echo Set the password for your locker:-
set /p pass=
echo %pass%>text.txt
) else (
echo Folder is created
)
Here, suppose of I set pass = 12345, the text file does not hold any such value
If once again I run my program and set pass=abcde, then the text file shows the value
as "1234".
Kindly give me the reason behind this and what to do to avoid this??
Thanks in advance.........
you need SETLOCAL ENABLEDELAYEDEXPANSION as you are using a variable set in parentheses context :
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
if not exist c:\Locker (
cd/
md Locker
cd windows\system32
echo Set the password for your locker:-
set /p pass=
echo !pass!>text.txt
) else (
echo Folder is created
)
ENDLOCAL
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