Could not open a connection to SQL server with batch file - batch-file

i'm getting this error while trying to run some sql query via a batch file.
The program works fine on its own, i think the problem is due to the fact that now i created a batch file that picks variables and commands from 2 separate files and the %istance% variable does not get recognised.
The code looks something like this:
set i=0
for /f "delims=" %%c in ('findstr /v /c:"::" var.txt') do (
set /a i+=1
set "var[!i!]=%%c"
)
set "hostname=%var[1]%"
set "istance=%var[2]%"
set "folder=%var[3]%"
set "program=%var[4]%"
set "printer=%var[5]%"
set "activation=%var[6]%"
set "customer=%var[7]%"
set i=0
for /f "delims=" %%c in ('findstr /v /c:"::" command.txt') do (
set /a i+=1
set "command[!i!]=%%c"
)
for /l %%L in (1 1 7) do (
set "command=!command[%%L]!"
!command!
)
goto :eof
the second line in the var.txt file is the SQL istance (MYPC\SQLEXPRESS) and this is an example of a command:
sqlcmd -Q "ALTER DATABASE MYDB SET MULTI_USER" -S %istance% -d master -U user -P pwd
As i said if i set the istance directly on the batch it seems to work fine.
Any advice?

Related

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.

Environment variable value not set, but why?

Why is batch variable TESTTYPE not passed through to the calling batch file (Windows 7 machine)?
I trigger a test system via SVN commit message. Given e.g. this SVN message:
This should trigger my test system for a long test.
testing RunTest#longtest
Problem: The command set at the end of the inner batch file properly outputs longtest but the outer batch file outputs smoketest unexpectedly.
This is the calling batch file test.bat:
call %~dp0gettype.bat trunk 12345
echo %TESTTYPE%
This is the called batch file gettype.bat doing the work:
set TESTTYPE=smoketest
::find all lines in the string which contain the keyword "RunTest#"
setlocal EnableDelayedExpansion
set "cmd=svn log -r %2 -v | findstr /r "RunTest#""
::for all words in that found line call the subroutine "handleElement"
for /F "tokens=*" %%a in ('!cmd!') do (
if "%%a" NEQ "" for %%b in (%%a) do call:handleElement %%b
)
goto ende
::split on hashtag char and handle the keyword after the hashtag (and find the type)
:handleElement
set TMPSTR=%1
set TAGNAME=%TMPSTR:~0,8%
if "%TAGNAME%"=="RunTest#" call:getSpecialType %TMPSTR:~8%
goto:eof
:getSpecialType
set TESTTYPE=%1
goto:eof
:ende
set
change
call %~dp0gettype.bat
echo %TESTTYPE%
to
for /F "usebackq" %%i in (`call %~dp0gettype.bat`) do set "TESTTYPE=%%i"
echo %TESTTYPE%
and in gettype.bat
change
:ende
set
to
:ende
echo %TESTTYPE%

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

Loop over SQLCMD results on batch file

I'm using the folling .cmd to get the values returned by one sql sentence.
#echo off
SET SERVER=.\SQLExpress
SET SQLCMD="C:\Program Files\Microsoft SQL Server\110\Tools\Binn\sqlcmd.exe"
for %%f in (%SQLCMD%) do set alternatepath=%%~sf
SET EXEC_LINE=%alternatepath% -S %SERVER% -d SkpMaster -h-1 -Q "set nocount on; select distinct id from sometable "
for /F "usebackq delims=" %%i in (`%EXEC_LINE%`) do (
set count=%%i
echo %count%
)
if not defined count (
echo Failed to execute SQL statement 1>&2
)
The SQL return 4 occurrences, but the echo print 4 times the 1ยบ ocurrence.
Maybe I'm not using correctly the "delims=" option, I have also tested with "tokens=*" with the same result.
Any idea?
Fixed after handle the parameter %%i in a different way.
#echo off
SET SERVER=.\SQLExpress
SET SQLCMD="C:\Program Files\Microsoft SQL Server\110\Tools\Binn\sqlcmd.exe"
for %%f in (%SQLCMD%) do set alternatepath=%%~sf
SET EXEC_LINE=%alternatepath% -S %SERVER% -d SkpMaster -h-1 -Q "set nocount on; select distinct id from sometable "
for /F "usebackq delims=" %%i in (`%EXEC_LINE%`) do call :processline %%i
if not defined count (
echo Failed to execute SQL statement 1>&2
)
pause
goto :eof
:processline
echo line=%*
goto :eof
:eof

Determining OS version via Scripting

I found this script on another site but I can not get it to work and I don't know batch scripting that well
Set objWshShell = WScript.CreateObject("WScript.Shell")
strOSVersion = objWshShell.RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\CurrentVersion")
If strOSVersion = "5.1" Then
Debug.WriteLine("Windows XP")
Rem Insert Windows XP Statements
ElseIf strOSVersion = "6.0" Then
Debug.WriteLine("Windows Vista")
Rem Insert Windows Vista Statements
ElseIf strOSVersion = "6.1" Then
Debug.WriteLine("Windows 7")
Rem Insert Windows 7 Statements
End If
now if I run this I get the error on the second line
'strOSVersion' is not recognized as an internal or external command
operable program or batch file.
= was unexpected at this time.
I do not know why
It's a VB script. You can save in a file named like test.vbs
Then open a command prompt, change directory to where you saved the file. At the prompt type cscript test.vbs.
Before that, I changed the Debug.WriteLine calls to WScript.Echo instead.
This is a Batch Script (.bat) that I've put together and use often for determining OS.
#ECHO OFF
SetLocal
REM --------> EDIT BELOW <--------
REM Edit below if you would like to audit the pc's you run this on and store the information in a file, either T or F (for True or False)
set storeValue=T
REM Edit below the location on a network drive that you can write to
set sharePath=\\servername\sharepath
REM -----> DO NOT EDIT BELOW <-----
IF NOT EXIST C:\Temp MD C:\Temp
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | findstr ProductName>C:\temp\osver.txt
set osver=
set tempLoc=C:\Temp
FOR /F "tokens=3* delims= " %%I IN (%tempLoc%\OSver.txt) DO SET osVer=%%I %%J
echo.-----------------------------------------
echo. You are running: %osVer%
echo.-----------------------------------------
IF '%storeValue%'=='F' goto end
IF '%storeValue%'=='T' goto storeValue
:storeValue
ipconfig |findstr IPv4>c:\temp\ipadd.txt
REM FOR /F "tokens=12* delims=." %%A IN (%tempLoc%\IPAdd.txt) DO SET IPAdd=%%A.%%B
FOR /F "tokens=2* delims=:" %%A IN (%tempLoc%\IPAdd.txt) DO SET IPAdd=%%A
IF EXIST %sharePath%\PC_Audit_List.txt goto audit
echo.PC Audit List>%sharePath%\PC_Audit_List.txt
echo.------------------------------------------------------------->>%sharePath%\PC_Audit_List.txt
goto audit
:audit
echo.%computername% - %IPAdd% - %osVer%>>%sharePath%\PC_Audit_List.txt
goto end
:end
IF EXIST %tempLoc%\OSver.txt del %tempLoc%\OSver.txt /f /q
IF EXIST %tempLoc%\IPAdd.txt del %tempLoc%\IPAdd.txt /f /q
EndLocal
pause
exit
I'm sure this will suit your needs, I've included an option for you to write the IP, Name and then the Version into a file.
#echo off
setlocal EnableDelayedExpansion
::Identify OS
for /F "delims=" %%a in ('ver') do set ver=%%a
set Version=
for %%a in (95=95 98=98 ME=ME NT=NT 2000=2000 5.1.=XP 5.2.=2003 6.0.=Vista 6.1.=7 6.2.=8 6.3=8.1) do (
if "!Version!" equ "this" (
set Version=Windows %%a
) else if "!ver: %%a=!" neq "%ver%" (
set Version=this
)
)
::Identify bit
if exist "%SYSTEMDRIVE%\Program Files (x86)" (
set Type=64 bit
) else (
set Type=32 bit
)
::Display result
echo %Version% %Type%
echo/
pause
Copied from: http://www.dostips.com/forum/viewtopic.php?f=3&t=4387

Resources