I have looked at many SO questions/answers and though some seem similar to my issue they do not seem to be. The answers given fix issues the questions were asking about but will not solve my issue.
I have a batch file...
@ECHO ON
ECHO Disabling the following... >> C:\App\Debug.log
ECHO - V1 >> C:\Apps\Debug.log
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1'"`) DO (
Echo %%F >> C:\Apps\Debug.log
)
EXIT /B
When I run this file at the command prompt it works perfectly fine. When I run it as a scheduled task it show me the echos but nothing for the for loop as expected.
Any ideas what might be wrong or what I can try for debugging purposes? Thanks!
sqlcmd
is perhaps not enough. cmd.exe
in environment of scheduled task may fail to find the executable using local PATHEXT
and local PATH
environment variables. The executable should be specified with full qualified file name, i.e. drive + path + name + extension. Then the batch file does not anymore depend on the environment variables PATH
and PATHEXT
because of all files are referenced with full qualified file name.
for
executes the specified command line with starting in background one more command process with %ComSpec% /c
and the specified command line appended. This means executed is following with Windows installed on drive C:
:
C:\Windows\System32\cmd.exe /c sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1'"
for
captures everything written to handle STDOUT of started command process. The lines of captured output are processed line by line by for
after started cmd.exe
terminated itself. Error messages output by started cmd.exe
or the commands/executables executed by Windows command processor in background to handle STDERR are redirected to handle STDERR of command process processing the batch file and printed to console. But there is no console window on running a batch file as scheduled task. So error messages cannot be seen in this case.
The for
command line can be modified easily here to get also error messages written into the C:\Apps\Debug.log
.
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1' 2^>^&1"`) DO (
The Microsoft article Using command redirection operators explains 2>&1
. The two operators >
and &
must be escaped with ^
to be interpreted as literal characters on Windows command processor parsing the for
command line before executing finally for
which executes next %ComSpec% /c
with the specified command line on which 2^>^&1
is changed already to 2>&1
.
Does the log file C:\App\Debug.log
contain with this modification following two lines?
'sqlcmd' is not recognized as an internal or external command,
operable program or batch file.
Yes, then no executable with file name sqlcmd
is found by started cmd.exe
. The best solution is referencing this executable with full qualified file name. See also: What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?
Otherwise sqlcmd
outputs perhaps an error message which should be now also in the log file C:\App\Debug.log
.
It would be also possible to use following command line to let background cmd.exe
write the error messages into a separate error log file C:\App\Error.log
:
FOR /F "tokens=* USEBACKQ" %%F IN (`sqlcmd -j -S DOMAIN\SQLSERVER -U username -P password -d DBNAME -Q "UPDATE [DBNAME].[dbo].[table1] SET ColOne='V1_OFF' WHERE ColOne='V1'" 2^>C:\App\Error.log`) DO (
"tokens=* usebackq"
results in first deleting all leading horizontal tabs and normal spaces on non-empty lines by for
, then checking if the remaining line starts with ;
in which case the line is also ignored and finally assigning the captured line not starting with ;
and with leading tabs/spaces removed to loop variable F
for further processing.
Better would be using the options usebackq^ delims^=^ eol^=
not enclosed in double quotes which requires escaping the two spaces and the two equal signs with caret character ^
to be interpreted as literal characters by cmd.exe
on parsing the command line before executing for
. The line splitting behavior is disabled completed with delims=
because of the definition of an empty list of delimiters. And no line except an empty line is ignored anymore because of end of line character modified from default ;
to no character.
Finally a space on an echo
line left to redirection operator >>
is also output by echo
and for that reason written as trailing space into the log file. Therefore no space should be used left to >
or >>
on printing a line with echo
redirected into a file. But care must be taken on omitting the space character left to the redirection operator. The word left to redirection operator should not be 1
, 2
, ..., 9
as this would result in redirecting the output to these numbered handles into the specified file instead of the character 1
, 2
, etc. So if unknown text should be written into a file, it is better to specify first the redirection operator >
or >>
and the full qualified file name and next the echo
command with the text to output. See also: Why does ECHO command print some extra trailing space into the file?
The three command lines with echo
would be for this batch file:
ECHO Disabling the following...>> C:\App\Debug.log
ECHO - V1>> C:\Apps\Debug.log
>>C:\Apps\Debug.log ECHO %%F
following...
is safe for being correct written into the file as also V1
. %%F
could be just 1
or a string ending with a space and a single digit and so it is better to specify the redirection first on the last echo
command line to get finally executed by cmd.exe
the command line ECHO %%F 1>>C:\Apps\Debug.log
.