I have asked other questions about Concatenated commands in DOS, but am obviously not yet that confident with the full bredth of things to take into account.
Can someone take a look at the below code and output on my system and see if they can advise what syntax is wrong (Note, I have broken the lines manually):
%comspec% /v:on /k "(for /f "tokens=2*" %a in ('reg query hkcu\software\microsoft
\windows\currentversion\policies\system /v DisableTaskMgr') do #set DisableTaskMg
r=%b) 2>nul & set DisableTaskMgr& pause & (if defined programfiles^(x86^) (set
"ProgramFiles(x32)=%programfiles(x86)%") else (set "ProgramFiles(x32)=%programfil
es%")) & !ProgramFiles(x32)!\Mozilla\Firefox\Firefox.exe -chrome chrome://browser
/content & echo. & if defined DisableTaskMgr (echo DisableTaskMgr reg key existed
prior to running, and... & (set DisableTaskMgr=%DisableTaskMgr:~2,3% & echo !
DisableTaskMgr! & reg add hkcu\software\microsoft\windows\currentversion\policies
\system /v DisableTaskMgr /t REG_DWORD /d %DisableTaskMgr% & if %DisableTaskMgr%
eql 0 (echo Previous state was Task Manager enabled) else (echo Previous state
was Task Manager DISabled))) else (echo DisableTaskMgr reg key DID NOT exist pri
or to running & reg delete hkcu\software\microsoft\windows\currentversion\polici
es\system /v DisableTaskMgr /f)"
.
I have tried cutting out parts of the code to fix individual parts, but my attempts at trial and error prove that I don't have much of an idea of what is wrong, and that I am not going to get this solved on my own very fast :(
Your IF comparison operator is wrong. You have eql - it should be equ.
I have no idea if that is your only problem - you have a horrific maintenance issue with that beast of a statement.
You might be better off creating a batch file with the same logic but formatted nicely. You can then simply call the batch file instead of trying to embed the entire complex process as one single complex command.
I can see your problem right here! It's your code! *grin*
Seriously though, even if you intend to maintain that mess, I recommend that split it up into it's constituent components for debugging purposes. You can even avoid the sometimes mysterious block errors by putting what is inside () blocks into separate subroutines. By turning this sort of thing...
if statement (
code block 1
code block 1
code block 1
code block 1
) else if (
code block 2
code block 2
code block 2
code block 2
)
...into this sort of thing:
if statement (
call :CodeBlock1
) else if (
call :CodeBlock2
)
goto :eof
:CodeBlock1
code
code
code
code
goto :eof
:CodeBlock2
code
code
code
code
goto :eof
Trying to debug that as a single line means keeping the whole thing, and how it interacts, constantly in mind. And basically having to guess at which similar looking bit of code actually created the error you're trying to fix.
I've personally wasted a good bit of time trying to fix perfectly good code, while not realizing that the error that I was looking at was actually further down in the code block.
After you've found and fixed your errors you can jam it all back into a single line again if you like. Overcoming a challenge does not necessarily mean doing it the hardest way possible. Overcoming a challenge the easiest way is also, by definition, overcoming a challenge.
Related
Bit of a weird one. I've been messing around with windows batch and time comparisons to schedule a task. Now I know there's a million better ways to do it, but our work machines are pretty locked down, so a batch script seems like the easiest way to actually achieve what I needed without some crazy workaround. I'm also well aware that the idea behind this is pretty gross. I'm not looking for perfection here, I'm just looking for it to work.
Basically at 17:00 on the 23rd November, I needed to move a file from one place to another. Problem is that I wouldn't actually be physically present at that time due to some other commitments, so I figured a batch script that was stuck in a loop of nothing until a certain date/time would work. So I cobbled together the following quickly the night before:
:dateloop
if %date% LSS 23/11/2019 goto dateloop
:timeloop
if %time% LSS 17:00 goto timeloop
<xcopy operation goes here>
And ran it overnight. So imagine my surprise when I came to my machine the next morning to check my emails and noticed that the file had been moved. Thankfully I was able to revert the file and rescheduled my day to do it manually.
I ran some tests last night, making sure that the script didn't exit upon completion so I could read the echo output. And it turns out that it was all running fine until 2:00, when the script decided "yes, this is after 17:00".
I could test it again tonight, and I do plan to, with the time format written out the long way (17:00:00:00) but I was wondering if anyone could confirm before I do, as that's a good while away, if this is the cause of my problem?
If you type IF /? at the command prompt, the help text will include this:
If Command Extensions are enabled IF changes as follows:
IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command
where compare-op may be one of:
EQU - equal
NEQ - not equal
LSS - less than
LEQ - less than or equal
GTR - greater than
GEQ - greater than or equal
and the /I switch, if specified, says to do case insensitive string
compares. The /I switch can also be used on the string1==string2 form
of IF. These comparisons are generic, in that if both string1 and
string2 are both comprised of all numeric digits, then the strings are
converted to numbers and a numeric comparison is performed.
As you can see, comparison is on strings unless the strings to compare contain only numeric digits. As time contains the non-numeric characters ":" and ".", the time is treated as a string, and of course "2" comes after the "1" from "17:00".
However, with the command echo [%time%] you'll notice that if the time is less than 10, it adds a space at the front. Therefore, you can get correct results with a string comparison as long as you take the space into account. So replace your problematic statement with the following one:
if "%time%" LSS "17:00" goto timeloop
That should fix it.
If compares strings alphabetically or numbers.
You need to rework your code and compare times as numbers. So you also need a reliable way to get date parts as numbers - date and time variables are not suitable because they can be in different formats depending on your settings.
Try this instead:
#echo off
::GOTO comment macro
set "[:=goto :]%%"
::brackets comment macros
set "[=rem/||(" & set "]=)"
for /f %%# in ('wMIC Path Win32_LocalTime Get /Format:value') do #for /f %%# in ("%%#") do #set %%#
%[:%
echo %day%
echo %DayOfWeek%
echo %hour%
echo %minute%
echo %month%
echo %quarter%
echo %second%
echo %weekinmonth%
echo %year%
%:]%
:dateloop
if %year%%month%%day% LSS 20191132 goto dateloop
:timeloop
if %hour%%minute% LSS 1700 goto :timeloop
i am trying to code a simple script in batch that can find and replace a line
so far, I've found a snippet that works perfectly fine for my purpose the only problem is that it removes empty lines
and i can't figure out why!!
I've tried to add another if statement in this for loop but I fail
also I found that there is a bat called JREPL, i tried to run few simple commands from the docs and i failed again XD
here is the snippet:
:Variables
set InputFile=t.txt
set OutputFile=t-new.txt
set _strFind= old "data"
set _strInsert= new "data";
:Replace
>"%OutputFile%" (
for /f "usebackq delims=" %%A in ("%InputFile%") do (
if "%%A" equ "%_strFind%" (echo %_strInsert%) else (echo %%A)
)
)
i was expecting that this snippet won't remove my empty lines
and i can't figure out why
I am posting this without testing, as I do not have the environment to test as we speak.
But to explain your issue, cmd will ommit empty lines as it is built that way. It is the same as setting a variable to nothing and expecting it to return a result, so we simply assign values to each line by sort of simulating a detection of line breaks (Don't know exactly how to explain that one) but nevertheless, we will add some additional characters to the lines to ensure we get line breaks, the just get rid of them once we have them, So here goes:
#echo off
setlocal enabledelayedexpansion
set inputfile=t.txt
set outputfile=t-new.txt
set _strfind=old "data"
set _strinsert=new "data";
for /f "tokens=*" %%a in ('type "%inputfile%" ^| find /v /n "" ^& break ^> "%inputfile%"') do (
set "str=%%a"
set "str=!str:*]=!"
if "!str!"=="%_strfind%" set "str=%_strinsert%"
>>%outputfile% echo(!str!
)
That should send to output file.. You can however make the output file the same as the input as it would then be the same as replacing the text inline in the original file. Once I am able to test, I will fix the answer if there are any issues with it.
As a side note, be careful of where you have additional whitespace in your variables you set. For instance:
set a = b
has 2 issues, the variable, containing a space after a will be created with the space. So it will be seen as:
%a %
The aftermath of this is that the value of the variable will start with a leading space, so when you expected b as the value, it in fact became b
Then lastly, it is alsways a good idea to enclose your variables with double quotes, simply again to eliminate whitespace, because:
set a=b
Even though you cannot see it with your naked eyes, contains a space at the end, so doing a direct match like:
if "b"=="b"
Will result in a false statement as in fact we have:
if "b"=="b "
So the correct statement would be to set variables as:
set "a=b"
if "%a%"=="b"
which will be a perfect match.
Note I posted this from my phone, so any spelling, grammar and code issues I will resolved as I go though my answer.
…and one way using JREPL
JRepl "old \qdata\q" "new \qdata\q;" /I /XSEQ /F "t.txt" /O "t-new.txt"
I'm trying to take some user input defined variables to decide whether or not to enter the loop and execute a copy and rename followed by deletion of the original file as it will no longer be needed.
set /p multiTune="Does your tune file need to be shared with multiple
Element sequences? (y/n) "
Echo Multi Tune is %multiTune%
if "%multiTune%"=="y" (set /p tuneCount="How many sequences will need to share your tune file? ")
Echo Tune count is %tuneCount%
pause
if "%multiTune%"=="y" (SET /p tuneName="Enter the file letter/number combination for the R quant of your tune file. ") else (#ECHO The user specified there is no need for a second tune.)
Echo Tune Name is %tuneName%
pause
if "%multiTune%"=="y" (SET /a tuneCount+=1) else(set /a tuneCount-=tuneCount)
Echo Tune count is now %tuneCount%
pause
:loop
if "%tuneCount%"=="0" goto exitloop
Set /p seqNumber="Enter the number for one of the sequences."
copy %tuneName%.D.pdf "S%seqNumber%-TUN1_%tuneName%.D.pdf"
echo %tuneName%.D.pdf renamed to S%seqNumber%-TUN1_%tuneName%.D.pdf
pause
Set /a tuneCount-=1
if "%tuneCount%"=="1" DEL "%tuneName%.D.pdf"
if "%tuneCount%"==1 goto exitloop
Echo %tuneCount%
pause
goto loop
:exitloop
All of the echos and pauses are just for testing purposes to make sure I have the correct values in my variables.
The batch file runs fine with the variables containing the correct strings and values up until the line:
if "%multiTune%"=="y" (SET /a tuneCount+=1) else(set /a tuneCount-=tuneCount)
The file says something is unexpected and closes at this point so i havent gotten a chance to figure out if the looped portion even works. The point of the +1 is so that it enters the loop and executes the commands until it gets to 1 and skips the loop if it equals 0.
I read a bunch of information about setlocal delayedexpansion and using !'s around variables instead of %'s. I'm not sure how to implement this or if this applies to my problem at all. I know there is probably an easier way to do the if statements but I'm a novice and that was the easiest way for me to understand it as I've been learning on the fly through trial and error, and everything you see is the results of a single day of learning.
Any help would be much appreciated. I tried to be as detailed as possible about what it is I'm trying to do but if you have any questions I will do my best to answer.
I really think you are making the things so MUCH complicated...
Have a corrected piece of the code you provided us (Note: I did not touch the loop subroutine to be on-topic):
#echo off
choice /m "Does your tune file need to be shared with multiple element sequences? (y/n) " /C:yn /N
rem Echo Multi Tune is %errorlevel%
rem If errorlevel equals to 1 user input is "Y", it is 2 it is "N". (I commented the "echo" command as it changes the errorlevel value).
if errorlevel 2 goto question_N
if errorlevel 1 goto question_Y
:question_Y
set /p tuneCount="How many sequences will need to share your tune file? "
set /p tuneName="Enter the file letter/number combination for the R quant of your tune file. "
SET /a "tuneCount+=1"
goto loop
:question_N
set /p tuneCount="How many sequences will need to share your tune file? "
ECHO The user specified there is no need for a second tune.
set /a "tuneCount-=tuneCount"
goto loop
:loop
rem [Code you provided above]
I hope you are fine with this, testing it and it works!
I'm trying to handle missing label errors in a batch file (Windows 10). My batch file currently uses a GOTO based on a passed parameter like this:
MYSCRIPT.bat choice1
I'm trying to do something simple with a simple syntax so that you don't have to include complex menus or lists. I hoped to do something simple in the batch file such as:
GOTO %1%
The problem occurs when the choice is misspelled, missing (not found.) I tried some of the examples for similar handling that I found on this site, but I either have the wrong situation or just don't quite understand how to apply it.
I'm sure that at least one person will scold me for not doing it in PowerShell or VBasic or something else. So I will go ahead and apologize in advance. Frankly, I don't really know how to do what I want to do in any of those. (Some will quip that I don't know how to do it in BATCH either otherwise I wouldn't be asking for help.)
I tried using a "FOR" to parse the file for an instance of the label, and also an "IF ERRORLEVEL 1" but it seems that it's not branching where it needs to go. For instance, if the label is found, go there; if not, go back to the beginning to give an opportunity to input something else.
Thanks in advance for any ideas that might be offered.
There is no way to handle this error and continue with goto command; just with call:
#echo off
setlocal EnableDelayedExpansion
call :%1 2>NUL
if errorlevel 1 echo Error: label "%1" does not exist
goto :EOF
:one
echo Section one
exit /B
:two
echo Section two
exit /B
I'm doing a project to help myself learn batch a little better. I have code which is meant to be a "UI" of sorts.
The snippet I have an issue with is this:
:install_check
if exist UI (
echo UI is already installed; reinstall?
CHOICE
if Errorlevel 1 goto :del
if Errorlevel 2 goto :return
cls && goto :install_check
)
goto :install_yes
I know the naming conventions and some of the coding stuff isn't perfect, but I really see no reason why every time it runs it goes to :del no matter what I type in for choice.
I've changed the choice switches and moved it around to be all in one line but it still doesn't want to work. The if that it is nested in is meant to check if a file is present on the computer, so it is a requirement but also may be the issue?
I tried looking around on this site but nothing will help my issue, any help is gladly accepted!!
Check the errorlevels in reverse-order.
if errorlevel n
means if errorlevel is n or greater
hence, errorlevel 2 will be interpreted as true for if errorlevel 1
As a solution has already been determined, the following example, (using your existing label names), restructures your code a little:
:install_check
ClS
If Not Exist "UI" GoTo install_yes
Choice /M "UI is already installed; reinstall"
If Errorlevel 2 GoTo return
GoTo del
If the next line/label in your code is :del, you may also remove line six.If the name UI belonged to a directory instead of a file then you'd change the third line to If Not Exist "UI\" GoTo install_yes.
ERRORLEVEL doesn't update inside control blocks like IF statements unless you use !ERRORLEVEL! instead of %ERRORLEVEL% and use this command at the start of your code: setlocal ENABLEDELAYEDEXPANSION
see http://batcheero.blogspot.ca/2007/06/how-to-enabledelayedexpansion.html