Batch script not running - windows

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%

Related

Batch - Variable giving different outputs at ECHO and IF

I am currently implementing a postprocess in batch, and after some changes a few code snipplets simply don't work anymore....
What I am trying to do:
#echo off & setlocal
ECHO %netUse% //For debugging!
IF NOT "%netUse%" == "" ( //Double checking if Variable is set
IF %netUse% EQU 1 (
IF %netUsePW% EQU 1 (
NET USE %netUseLetter% %netPath% %pw% /user:%netUser%
)
IF %netUsePW% EQU 0 (
NET USE %netUseLetter% %netPath%
)
)
)
When I run that code, this is the output:
C:\Program Files (x86)\ID GmbH\PRODETTE\DAX\ISDN>ECHO 0
0 <--- That's right! It is set to ZERO via a "configuration" Batch
"1" kann syntaktisch an dieser Stelle nicht verarbeitet werden. <-- ???
C:\Program Files (x86)\ID GmbH\PRODETTE\DAX\ISDN> IF EQU 1 ( <-- Why isn't it comparing the variable?
And just for completionists sake, I am loading all of these variables form another batch file, "Settings.bat"
I am running that file via
CALL :postCopySettings.bat
contents:
SET netUse=0
SET netUsePW=
SET netUseLetter=
SET netPath=
SET netUser=
SET pw=
SET configLoaded=1
(Since netUse is 0, I don't need to populate the other variables... right?)
TL:DR: Batch doesn't work, but I don't know why.
The problem is that variable netUsePW is not set.
When netUse is set to 0, and netUsePW, netUseLetter, netUsePath, pw are all empty, your code...:
#echo off & setlocal
ECHO %netUse%
IF NOT "%netUse%" == "" (
IF %netUse% EQU 1 (
IF %netUsePW% EQU 1 (
NET USE %netUseLetter% %netPath% %pw% /user:%netUser%
)
IF %netUsePW% EQU 0 (
NET USE %netUseLetter% %netPath%
)
)
)
...expands to...:
#echo off & setlocal
ECHO 0
IF NOT "0" == "" (
IF 0 EQU 1 (
IF EQU 1 (
NET USE /user:0
)
IF EQU 0 (
NET USE
)
)
)
As you can see, there are two syntax issues, which cause the error:
IF EQU 1
IF EQU 0
Although netUse is set to 0 and you therefore expect the statements after IF %netUse% EQU 1 not to be executed, they are still parsed, because the entire code block is parsed before any commands are executed.
To overcome this, there are several ways:
Preset variables with non-empty values:
#echo off & setlocal
ECHO %netUse%
IF "%netUse%" == "" (set "netUse=-1" & set "setUsePW=-1")
IF NOT "%netUse%" == "" (
IF %netUse% EQU 1 (
IF %netUsePW% EQU 1 (
NET USE %netUseLetter% %netPath% %pw% /user:%netUser%
)
IF %netUsePW% EQU 0 (
NET USE %netUseLetter% %netPath%
)
)
)
Avoid code blocks by changing the logic a bit and using goto:
#echo off & setlocal
ECHO %netUse%
IF "%netUse%" == "" goto :SKIP
IF %netUse% NEQ 1 goto :SKIP
IF %netUsePW% EQU 1 (
NET USE %netUseLetter% %netPath% %pw% /user:%netUser%
)
IF %netUsePW% EQU 0 (
NET USE %netUseLetter% %netPath%
)
:SKIP
Avoid code blocks by moving some code into subroutines and using call to call them:
#echo off & setlocal
ECHO %netUse%
IF NOT "%netUse%" == "" call :TEST "%netUse%" "%netUsePW%" "%netUseLetter%" "%netPath%" "%pw%"
exit /B
:TEST
IF %~1 EQU 1 call :TESTPW "%~1" "%~2" "%~3" "%~4" "%~5"
exit /B
:TESTPW
IF %~2 EQU 1 (
NET USE %~3 %~4 %~5 /user:%~1
)
IF %~2 EQU 0 (
NET USE %~3 %~4
)
exit /B
Enable and apply delayed expansion to do the variable expansion during execution rather than while parsing:
#echo off & setlocal EnableDelayedExpansion
ECHO %netUse%
IF NOT "%netUse%" == "" (
IF !netUse! EQU 1 (
IF !netUsePW! EQU 1 (
NET USE %netUseLetter% %netPath% %pw% /user:!netUser!
)
IF !netUsePW! EQU 0 (
NET USE %netUseLetter% %netPath%
)
)
)
IF NOT "%netUse%" == "" ( //Double checking if Variable is set
IF %netUse% EQU 1 (
IF %netUsePW% EQU 1 (
No point in testing "netuse" then complaining that "netusePW" is not set.

How do i check if input is any integer?

Simply asked, I need to check if a variable is numerical. I'm aware of the ability of:
set /a variable1=%variable%
setting non numerical strings to 0, but i need to be able to have 0 as an intiger as well as negative numbers.
This will be run very often, so a fast script is preferred. I've tried to echo the variable into a .txt, and use a for loop to scan through and return an error if anything other than 0-9 is detected, but the script is excessively long running, and frankly is a mess.
You could do something to this affect. Remove all numbers. If anything is left over it is not an integer. Not saying this is perfect but it is a step in the right direction.
set "tempvar="
FOR /F "tokens=* delims=-0123456789" %%G IN ("%variable1%") DO SET "tempvar=%%G"
IF DEFINED tempvar echo NOT AN INTEGER
As mentioned in question17584282
The easiest for digits should be:
IF %1 NEQ +%1 echo Notnumeric!
If negative numbers (hyphen) are also to be considered, this will work
SET number=%1
if %1 EQU +%1 echo positive number
if %1==-%number:-=% echo negative number
Learned from https://www.itprotoday.com/compute-engines/jsi-tip-9692-how-can-batch-script-determine-if-variable-or-parameter-integer
#echo off
:isInterer input [returnVar]
setlocal enableDelayedexpansion
set "input=%~1"
if "!input:~0,1!" equ "-" (
set "input=!input:~1!"
) else (
if "!input:~0,1!" equ "+" set "input=!input:~1!"
)
for %%# in (1 2 3 4 5 6 7 8 9 0) do (
if not "!input!" == "" (
set "input=!input:%%#=!"
)
)
if "!input!" equ "" (
set result=true
) else (
set result=false
)
endlocal & if "%~2" neq "" (set %~2=%result%) else echo %result%
try this.Some special symbols like ! and ^ could cause trouble though.
You can also use findstr:
#echo off
:isIntererFindstr input [returnVar]
setlocal enableDelayedexpansion
set "input=%~1"
if "!input:~0,1!" equ "-" (
set "input=!input:~1!"
) else (
if "!input:~0,1!" equ "+" set "input=!input:~1!"
)
echo !input!|findstr /r "[^0-9]" >nul 2>&1
if %errorlevel% equ 0 (
set result=false
) else (
set result=true
)
endlocal & if "%~2" neq "" (set %~2=%result%) else echo %result%

Equal variables - Batch

So, I've the following batch script:
#echo off
set /p name=
rem a random number, don't care about it.
set complete_name=%name%.Creepy
Goto STEP1
:STEP1
echo %complete_name%|findstr /C:"9000" >nul 2>&1
if not errorlevel 1 (
goto 9000
) else (
GOTO CHECK2
)
:CHECK2
echo %complete_name%|findstr /C:"930" >nul 2>&1
if not errorlevel 1 (
goto 930
) else (
GOTO CHECK3
)
:CHECK3
echo %complete_name%|findstr /C:"310" >nul 2>&1
if not errorlevel 1 (
goto 310
) else (
ECHO PROBLEM
)
:9000
ECHO 9000
PAUSE
:930
ECHO 930
PAUSE
:310
ECHO 310
PAUSE
I want it to check if "9000" is in the variable or not, same for "930" and "310". And if none of these numbers are in the variable Echo problem. But everytime i run this script it goes to ECHO PROBLEM even if 9000/920/310 is in %complete_name%. So, is this the right way to check if a variable is in another one or there is an easier way to do it?
So I've tried this code:
#echo off
set name=310
set complete_name=%name%.Creepy
Goto STEP1
:STEP1
setlocal
if "%complete_name:9000=%"=="%complete_name%" (
if "%complete_name:930=%"=="%complete_name%" (
if "%complete_name:310=%"=="%complete_name%" (
echo PROBLEM
) else (
goto 9000
)
) else (
goto 930
)
) else (
goto 310
)
goto :eof
but I'm stuck at echo problem...
Save next code snippet, possibly named blabla.bat:
#Echo OFF
setlocal
set complete_name=%1
if "%complete_name:9000=%"=="%complete_name%" (
if "%complete_name:930=%"=="%complete_name%" (
if "%complete_name:310=%"=="%complete_name%" (
echo problem
) else (
echo valid 310
)
) else (
echo valid 930
)
) else (
echo valid 9000
)
Exit /B
and watch the output from
blabla x9000y
blabla x930y
blabla x310y
blabla x9a0b0c0y
That's a way of 1. nested IF ... ( ... ) ELSE ( ... ) and 2. using "Edit/Replace" a variable
Or, if GOTOs considered necessary, there is something similar with For loop (a good thought topic as well..).
#Echo OFF
setlocal EnableDelayedExpansion
set complete_name=%1
for %%G in (9000 930 310) DO (
if /I "!complete_name:%%G=!" neq "%complete_name%" GOTO :%%G
)
echo problem %complete_name%
GOTO :commonEnd
:9000
Echo valid 9000 %complete_name%
GOTO :commonEnd
:930
Echo valid 930 %complete_name%
GOTO :commonEnd
:310
Echo valid 310 %complete_name%
GOTO :commonEnd
:commonEnd

Strange behavior of batch file

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 )

Best way to check if directory is writable in BAT script?

How can I check whether a directory is writable by the executing user from a batch script?
Here's what I've tried so far:
> cd "%PROGRAMFILES%"
> echo. > foo
Access is denied.
> echo %ERRORLEVEL%
0
Ok, so how about...
> copy NUL > foo
Access is denied.
> echo %ERRORLEVEL%
0
Not that either? Then what about...
> copy foo bar
Access is denied.
0 file(s) copied.
> echo %ERRORLEVEL%
1
This works, but it breaks if the file doesn't exist.
I've read something about internal commands not setting ERRORLEVEL, but copy obviously seems to do so in the last case.
Definitely running a command against it to find if its denied is the easy way to do it. You can also use CACLS to find exactly what the permissions are or aren't. Here's a sample.
In CMD type CACLS /?
CACLS "filename" will give you what the current permissions is allowed on the file.
R = Read, W = Write, C = Change (same as write?), F = Full access.
EDIT: You can use directory name as well.
So to do a check, you would:
FOR /F "USEBACKQ tokens=2 delims=:" %%F IN (`CACLS "filename" ^| FIND "%username%"`) DO (
IF "%%F"=="W" (SET value=true && GOTO:NEXT)
IF "%%F"=="F" (SET value=true && GOTO:NEXT)
IF "%%F"=="C" (SET value=true && GOTO:NEXT)
SET value=false
)
ECHO This user does not have permissions to write to file.
GOTO:EOF
:NEXT
ECHO This user is able to write to file.
You can write copy %0 foo to copy the batch file itself.
This will always exist.
Remember to delete the file afterwards, and to make sure that you aren't overwriting an existing file by that name.
There ought to be a better way to do this, but I don't know of any.
EDIT: Better yet, try mkdir foo.
In case the batch file is running off a network (or if it's very large), this may be faster.
set testdir=%programfiles%
set myguid={A4E30755-FE04-4ab7-BD7F-E006E37B7BF7}.tmp
set waccess=0
echo.> "%testdir%\%myguid%"&&(set waccess=1&del "%testdir%\%myguid%")
echo write access=%waccess%
i found that executing copy within the batch file echoed an error to STDERR, but left %ERRORLEVEL% untouched (still 0). so the workaround was to combine the command with a conditional execution of set.
copy /Y NUL "%FOLDER%\.writable" > NUL 2>&1 && set WRITEOK=1
IF DEFINED WRITEOK (
rem ---- we have write access ----
...
) else (
rem ---- we don't ----
...
)
this is tested on XP and 7 and seems to work reliably.
An extension to Mechaflash's answer, and solves the problem of overwriting the file by generating a unique filename for the "testing" file.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "a=%~1"
SET "b="
SET "g=0"
:a
SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!##$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
SET /A "d=0, e=1"
:b
IF "!c!" NEQ "" (
IF "!c:~%d%,1!" NEQ "" (
IF EXIST "!a!\!b!!c:~%d%,1!" (
SET "c=!c:~0,%d%!!c:~%e%!"
) ELSE (
SET /A "d=!d!+1, e=!e!+1"
)
GOTO :b
)
)
IF "!c!" EQU "" (
SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!##$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
:c
IF "!c!" NEQ "" (
IF "!c:~%d%,1!" NEQ "" (
SET /A "d=!d!+1"
GOTO :c
)
)
SET /A "d=!d!-1"
SET /A "f=%RANDOM%*!d!/32768"
SET "b=!b!!c:~%f%,1!"
GOTO :a
) ELSE (
SET /A "d=!d!-1"
SET /A "f=%RANDOM%*!d!/32768"
SET "b=!b!!c:~%f%,1!"
)
((ECHO EXIT>"!a!\!b!" && SET "g=1") & IF EXIST "!a!\!b!" DEL /F "!a!\!b!") >NUL 2>&1
ENDLOCAL & (SET "a=%g%")
IF "%a%" EQU "1" ECHO TRUE
(%~1 is the input directory)
EDIT: If you want a more safe option
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "a=%~1"
SET "b="
SET "g=0"
:a
SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!##$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
SET /A "d=0, e=1"
:b
IF "!c!" NEQ "" (
IF "!c:~%d%,1!" NEQ "" (
IF EXIST "!a!\!b!!c:~%d%,1!" (
SET "c=!c:~0,%d%!!c:~%e%!"
) ELSE (
SET /A "d=!d!+1, e=!e!+1"
)
GOTO :b
)
)
IF "!c!" EQU "" (
SET "c= `1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.~!##$%%^&()_+QWERTYUIOP{}ASDFGHJKLZXCVBNM"
:c
IF "!c!" NEQ "" (
IF "!c:~%d%,1!" NEQ "" (
SET /A "d=!d!+1"
GOTO :c
)
)
SET /A "d=!d!-1"
SET /A "f=%RANDOM%*!d!/32768"
SET "b=!b!!c:~%f%,1!"
GOTO :a
) ELSE (
SET /A "d=!d!-1"
SET /A "f=%RANDOM%*!d!/32768"
SET "b=!b!!c:~%f%,1!"
)
IF EXIST "!a!\!b!" (
SET "b=!b:~0,-1!"
GOTO :a
) ELSE (
((ECHO EXIT>"!a!\!b!" && SET "g=1") & IF EXIST "!a!\!b!" DEL /F "!a!\!b!") >NUL 2>&1
)
ENDLOCAL & (SET "a=%g%")
IF "%a%" EQU "1" ECHO TRUE

Resources