batch script was unexpected this time - batch-file

after running this script shows somesoftware was unexpected this time i am using windows 7 64 bit. trying to get installed location of software using registry. if i echo THE_NAME then i get proper installed location but script exits in if else says somesoftware was unexpected this time
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKEY_CURRENT_USER\Software\somesoftware
set VALUE_NAME=InstallDirectory
SET THEME_NAME=
FOR /f "usebackq tokens=2,*" %%a in (`REG QUERY "HKEY_CURRENT_USER\Software\somesoftware" /v InstallDirectory`) DO (
SET THEME_NAME=%%b
)
echo %THEME_NAME%
if defined THEME_NAME (
set PathValue= %THEME_NAME%
) else (
echo %KEY_NAME%\%VALUE_NAME% not found.
)

Your script does not make use of KEY_NAME or VALUE_NAME, and this might be just how you trimmed your example down.
I modified your script as shown below for testing, and it appeared to work as I expected.
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKEY_CURRENT_USER\Software\%1
set VALUE_NAME=InstallDirectory
SET THEME_NAME=
FOR /f "usebackq tokens=2,*" %%a in (`REG QUERY "%KEY_NAME%" /v %VALUE_NAME%`) DO (
SET THEME_NAME=%%b)
echo THEME_NAME=%THEME_NAME%
if NOT ""=="%THEME_NAME%" (
set PathValue=%THEME_NAME%
echo PathValue=%PathValue%
) else (
echo %KEY_NAME%\%VALUE_NAME% not found.
)
NOTE: I changed the IF test to just test for empty string, an echo for my own debugging, I used %1 so I could test...
You will want to use this as a guide to inform your final script.

Related

How to receive a processes that with name via a batch script

I need to receive a string with processes whose name is equal to "MSSQLSERVER" or starts with "MSSQL$". The names should be separated by forward slashes (/).
I am trying to do it with such script:
#echo off
set mssqlDependenties=
set defaultSqlServerServiceName="MSSQLSERVER"
set namedSqlServerServiceNameBeginning="MSSQL$"
setlocal enabledelayedexpansion
for /f "tokens=2" %%s in ('sc query state^= all ^| find "SERVICE_NAME: MSSQL"') do (
set serviceName=%%s
if "%%s" equ %defaultSqlServerServiceName% (
set mssqlDependenties=!mssqlDependenties!/%%s
)
if "%serviceName:~0,7%" equ %namedSqlServerServiceNameBeginning% (
set mssqlDependenties=!mssqlDependenties!/%%s
)
)
echo %mssqlDependenties%
But I receive an error:
The syntax of the command is incorrect.
mssqlDependenties should contain MSSQLSERVER/MSSQL$1/MSSQL$2/MSSQL$3, etc.
The solution from avery_larry works perfectly:
I changed
if "%serviceName:~0,7%" equ %namedSqlServerServiceNameBeginning% (
to
if "!serviceName:~0,7!" equ %namedSqlServerServiceNameBeginning% (

Variables on telnet

I'm pretty new to coding and I needed a little automation batch file.
I usually just open Telnet from CMD and do this:
I type:o 192.168.1.248
And I get connected to the device
I send my string WE1*1RTMP and the device responds with E1*1RTMP
This is correct and everything works.
But I would like to make this an automation without me requiring to type everything, just launch a .bat file.
I was able to do that both with Ncat, creating a bat file that says:
echo WE1*1RTMP | ncat 192.1568.1.248 23and everything works.
I was also able to do it using Plink with a .bat file saying plink.exe -load RECtelnet < *path to a text file containing the WE1*1RTMP command.
Now I need a way to check the response from the device.
When the command is received and executed correctly, the answer I get is E1*1RTMP, but I'd love to have something that check this.
Like if the response I get is the same as this one, everything just disappear after running, but if the response is anything different, like the E10 error I get when I type a command that is not recognized from the device, instead of disappearing the cmd windows just says something like "Hey your command failed" or anything similar.
I could also send this command using SSH, I have another profile with Plink called "REC" that connects me thru SSH, if this is somehow easier to automate compared to telnet.
How can I archive this ?
Thanks to everyone who will try to help.
I Modified the example Script to be much tighter and use yoru command and IP and do telnet instead of SSH etc.
REM Script Name: TelnetToDevice.cmd
#(
SETLOCAL EnableDelayedExpansion
ECHO OFF
REM SETUP Device Connection Details and commands
SET "_PLink.Path=%~dp0plink.exe"
SET "_PLink.Method=-telnet"
REM SET "_PLink.Method=-ssh"
SET "_Device.User=USERNAME"
SET "_Device.PW=PASSWORD"
SET "_Devices.List="192.1568.1.248""
SET "_Devices.Cmd.List="WE1*1RTMP""
SET /A "_Results.Count=0"
)
FOR %%A IN (%_Devices.List%) DO (
FOR %%B IN (%_Devices.Cmd.List%) DO (
FOR /F "Tokens=*" %%C IN ('
ECHO.Y^|%_PLink.Path% %_PLink.Method% %_Device.User%#%%~A -pw %_Device.PW% "%%~B"
') DO (
ECHO.Results is "%%C"
SET /A "_Results.Count+=1"
SET "_Result.!_Results.Count!=%%C"
)
)
)
ECHO.
ECHO.Listing all Variables generated:
ECHO.
SET "_Result."
PAUSE
(
ENDLOCAL
EXIT /B 0
)
Okay if you just need to collect the output from that command, maybe launch another command in response then it's fairly easy to do in CMD using PLINK, and NCAT should work the same.
(I use Plink to connect to our Cisco Devices from CMD to collect Data, and run some simple commands if I get certain responses)
This is done by catching the output from the command by parsing the results in a FOR /F loop.
At the CLI Directly:
NCAT
FOR /F "Tokens=*" %A IN ('
ECHO.WE1*1RTMP^| ncat 192.1568.1.248 23
') DO (
ECHO.%%A
SET "_Result=%%A"
)
PLINK
FOR /F "Tokens=*" %A IN ('
plink.exe -load RECtelnet ^< "C:\path\to\file containing WE1*1RTMP command.txt"
') DO (
ECHO.%%A
SET "_Result=%%A"
)
Note, I assume you know that in the above commands you will need to provide the Username password etc in these cases, as you say these are working commands as stand.
I happen to have a Script that I use to connect to multiple devices and run commands, its over-kill for your needs, and I will write a trimmed down version, but it seemed worthwhile to include it as the example of running in a CMD script:
Here is the shell of the actual CMD Script I use to check and fix our Fibre switches:
#(
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO OFF
REM SETUP Device Connection Details and commands
SET "_PLink.Path=%~dp0plink.exe"
SET "_Device.User=USERNAME"
SET "_Device.PW=PASSWORD"
SET "_Devices.List="IP/Hostname1" "IP/Hostname_2" "IP/Hostname_3" "IP/HostnameN""
SET "_Devices.Cmd.List="show feature ^| inc http" "show system internal flash ^| include Mount" "show system internal flash ^| include tmp" "dir ^| include free" "show system internal dir /var/tmp ^| Inc 'log.+[0-9][0-9][0-9][0-9][0-9][0-9]'" "show environment fan ^| ex ---- ^| ex Filter" "show environment temperature ^| ex ---- ^| ex '('""
REM Setup Log files and Email
CALL :GetDateTime
SET "_Log.Folder=%~dp0Log"
SET "_eMail.Folder=%~d0\Temp"
IF NOT EXIST "!_Log.Folder!" ( MD "!_Log.Folder!" )
IF NOT EXIST "!_eMail.Folder!" ( MD "!_eMail.Folder!" )
SET "_Log.File=!_Log.Folder!\%~n0_Log_!IsoDate!_!IsoTime!.log"
SET "_eMail.File=!_eMail.Folder!\%~n0_eml.tmp"
SET "_eMail.Subject=%~n0 - Log"
ECHO.>"!_eMail.File!"
SET "_SMTPServer=SMTPServerIP"
SET "_RcptTo=Yourname#YourDomain.com"
SETLOCAL DISABLEDELAYEDEXPANSION
)
CALL :Main
(
ENDLOCAL
Exit /b %eLvl%
)
:Main
FOR %%A IN (%_Devices.List%) DO (
CALL :OutEcho
CALL :DateEcho %%~A:
FOR %%B IN (%_Devices.Cmd.List%) DO (
FOR /F "Tokens=*" %%C IN ('
ECHO.Y^|%_PLink.Path% -ssh %_Device.User%#%%~A -pw %_Device.PW% "%%~B"
') DO (
CALL :OutEcho %%~A: %%~C
(
ECHO.%%~C | FIND /I "log" >NUL
) && (
FOR /F "Tokens=1" %%D IN ("%%~C") DO (
CALL :OutEcho %%~A: Deleting: %%~D
FOR %%b IN (
%_Devices.Cmd.DeleteFoundFile%
) DO (
FOR /F "Tokens=*" %%c IN ('
%_PLink.Path% -ssh %_Device.User%#%%~A -pw %_Device.PW% "%%~b%%~D"
') DO (
CALL :OutEcho %%~A: %%~c
)
CALL :OutEcho %%~A: Deleted: %%~D
)
)
)
)
)
)
CALL :SendMail "%_eMail.File%" "%_eMail.Subject%"
GOTO :EOF
:SendMail
ECHO.Sending Email for "%~2"
CALL ECHO CALL "%~dp0mailsend.exe" -domain reval.com -smtp %_SMTPServer% -f %Computername%#reval.com -t %_RcptTo% -sub "%~2" -attach "%~1",text,i
CALL "%~dp0mailsend.exe" -domain reval.com -smtp %_SMTPServer% -f %Computername%#reval.com -t %_RcptTo% -sub "%~2" -attach "%~1",text,i
GOTO :EOF
:DateEcho
(
SETLOCAL
CALL :GetDateTime
)
CALL :OutEcho %TDate% - %*
ENDLOCAL
GOTO :EOF
:OutEcho
ECHO.%*
ECHO.%*>>"%_Log.File%"
ECHO.%*>>"%_eMail.File%"
GOTO :EOF
:GetDateTime
FOR /F "Tokens=1-7 delims=MTWFSmtwfsouehrandit:-\/. " %%A IN ("%DATE% %TIME: =0%") DO (
FOR /F "Tokens=2-4 Skip=1 Delims=(-)" %%a IN ('ECHO.^| DATE') DO (
SET "%%~a=%%~A"
SET "%%~b=%%~B"
SET "%%~c=%%~C"
SET /a "#%%~a=1%%~A - (2%%~A-1%%~A)"
SET /a "#%%~b=1%%~B - (2%%~B-1%%~B)"
SET /a "#%%~c=1%%~C - (2%%~C-1%%~C)"
SET "HH=%%~D"
SET "Mn=%%~E"
SET "SS=%%~F"
SET "Ms=%%~G"
SET /a "#HH=1%%~D - (2%%~D-1%%~D)"
SET /a "#Mn=1%%~E - (2%%~E-1%%~E)"
SET /a "#SS=1%%~F - (2%%~F-1%%~F)"
SET /a "#Ms=1%%~G - (2%%~G-1%%~G)"
SET /a "#TMinutes=((1%%~D - (2%%~D-1%%~D))*60)+(1%%~E - (2%%~E-1%%~E))"
SET /a "#TSeconds=((((1%%~D - (2%%~D-1%%~D))*60)+(1%%~E - (2%%~E-1%%~E)))*60)+(1%%~F - (2%%~F-1%%~F))"
)
)
SET "TTime=%HH%.%Mn%.%SS%"
SET "IsoTime=%HH%.%Mn%.%SS%.%Ms%"
SET "TDate=%yy%-%mm%-%dd%"
SET "IsoDate=%yy%-%mm%-%dd%"
GOTO :EOF
Below is a MUCH tighter script that uses your provided info directly.
REM Script Name: TelnetToDevice.cmd
#(
SETLOCAL EnableDelayedExpansion
ECHO OFF
REM SETUP Device Connection Details and commands
SET "_PLink.Path=%~dp0plink.exe"
SET "_PLink.Method=-telnet"
REM SET "_PLink.Method=-ssh"
SET "_Device.User=USERNAME"
SET "_Device.PW=PASSWORD"
SET "_Devices.List="192.1568.1.248""
SET "_Devices.Cmd.List="WE1*1RTMP""
SET /A "_Results.Count=0"
)
FOR %%A IN (%_Devices.List%) DO (
FOR %%B IN (%_Devices.Cmd.List%) DO (
FOR /F "Tokens=*" %%C IN ('
ECHO.Y^|%_PLink.Path% %_PLink.Method% %_Device.User%#%%~A -pw %_Device.PW% "%%~B"
') DO (
ECHO.Results is "%%C"
SET /A "_Results.Count+=1"
SET "_Result.!_Results.Count!=%%C"
)
)
)
ECHO.
ECHO.Listing all Variables generated:
ECHO.
SET "_Result."
PAUSE
(
ENDLOCAL
EXIT /B 0
)
The simplest way for you to do what you want is likely to:
Install python.
Write this in a text file (e.g. with notepad), and save it as something ending in .py:
import socket
import traceback
try:
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(("192.168.1.248", 23))
mysock.send(b"WE1*1RTMP\n")
read_so_far = b""
while b"E1*1RTMP".startswith(read_so_far):
read_bit = sock.recv(1024)
if read_bit == b"":
print("Didn't get full message; had", repr(read_so_far))
input("Press enter to continue... ")
break
read_so_far += read_bit
if read_so_far.startswith(b"E1*1RTMP"):
print("Got success message")
break
else:
print("Got the wrong message: ", repr(read_so_far))
input("Press enter to continue... ")
except Exception as e:
traceback.print_exc()
input("Press enter to continue... ")
raise
NOTE: The way the lines are indented there is important.
Double-clicking on that file should now do what you want. If something goes wrong, before asking for help here open up a command prompt, cd to the relevant directory and run it at the command line with python myfile.py (or whatever you named the file). People here will need that output.
Sometime in the future, pick up a book on python or enroll in a python-focused course on coursera or elsewhere. I've heard good things about "Python for Everybody", but there's loads out there - well over 10% of your local big box book store's computer section these days is books trying to teach you python.

Unset variable value assigned within if statement inside a nested for loop

I am trying to make one batch file to read parameters from the file and pass it to ant for deployment.
I have made the below batch file:
setlocal enabledelayedexpansion
echo on
IF EXIST "D:\testfile1.txt" (
echo Do one thing
set string=
set /p string=< D:\testfile1.txt
echo value taken from file is %string
for /f "tokens=2,4,6 delims==:" %%G IN ("%string%") DO (
echo %%G %%H %%I
set env=%%G
set dom=%%H
set com=%%I
echo ENV !env!
echo DOM !dom!
echo COM !com!
cd D:\kpn_eai\EAI_FIXED\branches\kpn_eai_fixed\fixed\build\scripts
%ANT_HOME%\bin\xanteai deploy %%G %%H %%I
)
) ELSE (
echo Do another thing
)
endlocal
In testfile1.txt I have parameters in below format:
Environment=Env_Name1:Domain=Domain_Name1:Component=Component_name1
Parameters are different deployments. When I am running the above code it is giving below output
D:\>echo off
Do one thing Ant home is C:\tibco\ant\apache-ant-1.9.13
value taken from file is Environment=Env_name1:Domain=Domain_Name1:Component=Component_name1
Env_name1 Domain_Name1 Component_name1
ENV Env_name1
DOM Domain_Name1
COM Component_name1
Deployments starts after this.
The issue I am facing is when I run this code for different parameters (in testfile1.txt) the values of ENV, DOM and COM remains same regardless of any parameters read from testfile1.txt.
Can anyone help me to correct this code and let me know how can I just assign the values read from file to a variable and pass it to ant for deployment?
NOTE:- This batch file will be placed in scheduler which will check for testfile1.txt after every 5 minutes, when it finds that file deployment process gets triggered. Thus I have included if condition to check availability of file.
There really shouldn't be any need to be setting or echoing everything as you go, so why not just do something like this instead:
#Echo Off
If Exist "testfile1.txt" (Set /P "string="<"testfile1.txt"
SetLocal EnableDelayedExpansion
Echo value taken from file is !string!
For /F "Tokens=2,4,6 Delims==:" %%A In ("!string!") Do (
CD /D "D:\kpn_eai\EAI_FIXED\branches\kpn_eai_fixed\fixed\build\scripts"
"%ANT_HOME%\bin\xanteai" deploy %%A %%B %%C)
EndLocal) Else Echo Do another thing
You could first split the read line at the colons with a simple for and
obtain the variable names env,dom,com from the content.
Here preceeded with an underscore for easier output.
:: Q:\Test\2019\03\08\SO_55061545_.cmd
#echo off
setlocal enabledelayedexpansion
set "FileIn=D:\testfile1.txt"
IF not EXIST "%FileIn%" (
echo Do another thing
Goto :somewhere
)
echo Do one thing
set "string="
set /p "string="<"%FileIn%"
echo value taken from file is %string%
for %%A in ("%string::=" "%") do for /f "tokens=1* delims==" %%B IN ("%%~A") DO (
echo %%A %%B %%C
set var=%%B
set "_!var:~0,3!=%%C"
)
set _
:: cd D:\kpn_eai\EAI_FIXED\branches\kpn_eai_fixed\fixed\build\scripts
:: %ANT_HOME%\bin\xanteai deploy %_env% %_dom% %_com%
endlocal
:somewhere
> SO_55061545_.cmd
Do one thing
value taken from file is Environment=Env_Name1:Domain=Domain_Name1:Component=Component_name1
"Environment=Env_Name1" Environment Env_Name1
"Domain=Domain_Name1" Domain Domain_Name1
"Component=Component_name1" Component Component_name1
_Com=Component_name1
_Dom=Domain_Name1
_Env=Env_Name1

Conditional If Statement Syntax in Batch

I have checked several resources on conditional if statement syntax for batch scripts, and despite this, I'm unable to find my mistake. I typically avoid asking questions here that should be this simple, but it's the last task on a huge project so I'm hoping someone can help me see what I'm doing wrong. This is a script for a university project, and is merely for an exploration of concepts.
#Echo OFF
REM Check time remaining
for /f "tokens=3 delims=: " %%a in (
'cscript //nologo "%systemroot%\system32\slmgr.vbs" /dli ^| find "Time remaining: "'
) do set "timeRemainingStatus=%%a"
Echo %timeRemainingStatus%
pause
REM Check SkipRearm dword value
setlocal ENABLEEXTENSIONS
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform"
set VALUE_NAME=SkipRearm
FOR /F "usebackq skip=2 tokens=1-3" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
set ValueName=%%A
set ValueType=%%B
set ValueValue=%%C
)
Echo Value Name: %ValueName%
Echo Value Value: %ValueValue%
pause
IF %timeRemainingStatus% EQU 20160 (
Echo First level
pause
IF defined ValueName (
Echo Second Level
pause
IF %ValueValue% == "0x0" (
Echo Third Level
pause
regedit.exe /s "C:\Windows\SR.reg"
)
) ELSE (
Echo Fourth Level
pause
SLMGR /REARM
)
)
pause
I have the echos and pauses in there so I can see what code runs and to verify that the variables are retaining their values. It crashes for me after the second pause (after the Echo Value Value: %ValueValue% command). I assume it's something wrong with syntax, but I've been unable to see any errors because the command prompt closes, despite all the pauses I have.
There were a few things wrong. This is the solution I went with:
#Echo OFF
REM Check time remaining
for /f "tokens=3 delims=: " %%a in (
'cscript //nologo "%systemroot%\system32\slmgr.vbs" /dli ^| find "Time remaining: "'
) do set /a "timeRemainingStatus=%%a"
setlocal ENABLEEXTENSIONS
set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform"
set VALUE_NAME=SkipRearm
FOR /F "usebackq skip=2 tokens=1-3" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
set ValueName=%%A
set ValueType=%%B
set ValueValue=%%C
)
IF %timeRemainingStatus% EQU 0 (
IF defined ValueName (
IF "%ValueValue%" == "0x0" (
regedit.exe /s "C:\Windows\SR.reg"
)
IF "%ValueValue%" == "0x1" (
SLMGR /REARM
)
)
)
I needed to add /a to set (which I thought I had before, but I guess not). Additionally, I forgot quotes when comparing %ValueValue% to "0x0". While it may not be the cleanest way of doing things, I also changed the if-else into two if statements.
I've tested this at startup on a VM and it appears to be working properly. Much appreciated to the help given.
When setting variables within for loops or if statements, you'll need to take advantage of Setlocal EnableDelayedExpansion. This also applies when referencing variables set in this context. Any variables that use EnableDelayedExpansion will need to have exclamation points around the variable instead of percentages (!Value! instead of %Value%). You'll need to change your code to take advantage of this.

Reading registry value's data with spaces

I am making a program. When installed, It will run a batch file which needs to know where the application folder is.
The installation wizard software I am using creates a registry key that represents the program's path, but "Program Files" has a space in it, so the batch output will be "C:\Program"
My current script is:
#echo off
setlocal ENABLEEXTENSIONS
set KEY_NAME="HKEY_LOCAL_MACHINE\Software\MarksRTZ\AV"
set VALUE_NAME=DataPath
FOR /F "usebackq skip=2 tokens=1-3" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
set ValueName=%%A
set ValueType=%%B
set ValueValue=%%C
)
if defined ValueName (
echo data "%ValueValue%"
echo name "%ValueName%"
echo type "%ValueType%"
) else (
echo Not found
)
The DataPath value is set to [APPDIR]\data on installation, [APPDIR] being the location the user selected.
But like I said, that script will always output C:\Program if [APPDIR] was set to something like C:\Program Files (x86)\MarksRTZ\AV\ in the installer (Which is actually the default)
How can I fix this?
I will also note; the batch file isn't the real program, It's going to be the simple script that launches the program in the correct working directory.
Next code snipped should work with tokens=1-2* and even with setlocal DISABLEEXTENSIONS:
rem ensure %ValueName% is not visible as it could be defined already!
set "ValueName="
FOR /F "usebackq skip=2 tokens=1-2*" %%A IN (
`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
set "ValueName=%%A"
set "ValueType=%%B"
set "ValueValue=%%C"
)
if defined ValueName (
echo data "%ValueValue%"
echo name "%ValueName%"
echo type "%ValueType%"
) else (
echo Not found
)
Resources:
FOR /F Loop command: against the results of another command;
SETLOCAL Set options to control the visibility of environment variables in a batch file

Resources