scheduling of batch script through task scheduler - batch-file

I have below script which have output as well as log redirection along with date and tiem written into the log and erro files. i am saving this script with .cmd extension. Manually when i try to run this script through the command prompt it runs perfectly and first write current date and time in output and error log and then start recording the logs. but when schedueled through task schedule it only writes current date and time int othe logs but not hte actual logs. Can someone please let me know how i can schedule this script in such a way it will first record the current date and time and then start recording the logs.
Echo Date:%date% Time:%time% >> error.txt
#echo off
(
Echo Date:%date% Time:%time%
start "" /wait /b "D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_EXTRACT.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_EXTRACT.CONF"
:loop
for /f "tokens=2 delims=: " %%a in ('tasklist ^| find "BES_EXTRACT.exe"' ) do (
if "%ERRORLEVEL%"=="0" (
ping -n 10 localhost > nul 2>nul
goto loop
)
)
start "" /wait /b "D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_DATA_MAP.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_DATA_MAP.conf"
) >> Output.txt 2>> error.txt

Use redirection on the batch file. In order to output date and time to both files, you could use this technique:
ECHO Date:%date% Time:%time%
1>&2 ECHO Date:%date% Time:%time%
The first ECHO will write to standard output which would be caught with >> Output.txt applied to the batch file. The second ECHO will write to standard error, that output would be redirected by 2 >> error.txt.
If you are worried that the values might differ slightly (by hundredth of a second, perhaps), you could first store the output string to a variable:
SET "datetime=Date:%date% Time:%time%"
ECHO %datetime%
1>&2 ECHO %datetime%

Set 'program/script' : 'yourfile.bat' WITHOUT PATH
Set 'Start in' the rest of path

Related

My Batch file loop stops because of open file

I am trying to build a batch file that pings multiple devices on our network and continues logging ping results data in an output file in an infinite loop. However, the infinite loop gets hung up because the output file is open. Once I manually close the output file, the loop begins another iteration and logs more data. How do I automate this step? I've gone through so many options with taskkill, but none of them will close the output file for some reason. Other Notepad files close, but not the output file running on notepad.
Thanks for you help! Code is below:
#echo off
if exist C:\Users\Tsgadmin\Desktop\data\computers.txt goto Label1
echo.
echo Cannot find C:\Users\Tsgadmin\Desktop\data\computers.txt
echo.
Pause
goto :eof
:Label1
:loop
echo ================================================= >> C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt
echo PingTest executed on %date% at %time% >> C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt
for /f %%i in (C:\Users\Tsgadmin\Desktop\data\computers.txt) do call :Sub %%i
notepad C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt
choice /n/t:c,<10>/c:cc
echo ================================================= >> C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt
echo. >> C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt
start notepad.exe
for /f "tokens=2" %%x in ('tasklist ^| findstr notepad.exe') do set PIDTOKILL=%%x
taskkill /F /IM notepad.exe > nul
goto loop
goto :eof
:Sub
echo Testing %1
ping -n 1 %1 >> C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt | find /i "(0% loss)"
echo %1 Testing done
echo %1 Testing done >> C:\Users\Tsgadmin\Desktop\ping_firepanels_output.txt
Here is your batch code rewritten for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LogFile=%USERPROFILE%\Desktop\ping_firepanels_output.txt"
set "ListFile=%USERPROFILE%\Desktop\data\computers.txt"
if exist "%ListFile%" goto PrepareForPings
echo/
echo Cannot find file: "%ListFile%"
echo/
endlocal
pause
goto :EOF
rem Delete existing log file before running the echo requests.
rem Get just file name with file extension without path from
rem log file name with path specified at top of the batch file.
:PrepareForPings
del "%LogFile%" 2>nul
for /F %%I in ("%LogFile%") do set "LogFileName=%%~nxI"
rem Always terminate (not kill) running Notepad instance with having
rem the log file opened for viewing before running first/next test run.
:PingLoop
%SystemRoot%\System32\taskkill.exe /FI "WINDOWTITLE eq %LogFileName% - Notepad" >nul 2>nul
echo =================================================>>"%LogFile%"
>>"%LogFile%" echo PingTest executed on %DATE% at %TIME%
echo/>>"%LogFile%"
for /F "usebackq" %%I in ("%ListFile%") do (
echo Testing %%I ...
%SystemRoot%\System32\ping.exe -n 1 -w 500 %%I>nul
if errorlevel 1 (
echo %%I is not available in network (no reply^).>>"%LogFile%"
) else echo %%I is available.>>"%LogFile%"
echo %%I testing done.
)
echo =================================================>>"%LogFile%"
echo/>>"%LogFile%"
start "" %SystemRoot%\notepad.exe "%LogFile%"
echo/
%SystemRoot%\System32\choice.exe /C NY /N /T 10 /D Y /M "Run again (Y/n): "
echo/
if errorlevel 2 goto PingLoop
endlocal
In general it is advisable to define environment variables with names of files specified multiple times in the batch file at top to make it easier to modify them in future.
On referencing those file environment variables it is strongly recommended to enclose the name in double quotes to get a working batch file also when file name with path contains a space character or one of these characters: &()[]{}^=;!'+,`~
If a file name enclosed in double quotes is specified as text file of which lines to read in a for /F command line, it is necessary to use option usebackq to get interpreted the file name enclosed in double quotes as file name and not as string to process by FOR.
The DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ explains why it is better to use echo/ instead of echo. to output an empty line.
The TASKKILL command used to send Notepad the terminate signal for a graceful termination should be send only to the Notepad instance having the log file opened and not any other perhaps running Notepad instance.
An ECHO line redirected to a file with > or >> with a space left to redirection operator results in having this space also written as trailing space into the file. For that reason there should be no space between text to write into the file and redirection operator. A space right to > or >> would be no problem as not written into the file.
When a variable text is output on an ECHO line redirected into a file which could end with 1, 2, 3, ... 9, it is necessary to specify the redirection from STDOUT into the file with >> at beginning of the line as otherwise 1>>, 2>>, ... would be interpreted different as expected on execution of the ECHO command line. Read also the Microsoft article about Using Command Redirection Operators.
There is no subroutine necessary for this task. A command block starting with opening parenthesis ( and matching ) can be used here too. That makes the execution of the loop a bit faster, not really noticeable faster, but nevertheless faster.
There is a text written with echo into the log file containing also a closing parenthesis ) not within a double quoted string. This ) would be interpreted as matching ) for opening ( of true branch of IF condition. It is necessary to escape ) with caret character ^ to get ) interpreted as literal character by Windows command interpreter.
PING exits with exit code 1 if the echo request was not replied. Otherwise on successful reply the exit code is 0. It is better to evaluate the exit code via errorlevel than filtering the language dependent output.
New instance of Notepad with the log file to view is started by this batch file using command start to run Notepad in a separate process running parallel to command process executing the batch file. Otherwise the execution of the batch file would be halted as long as the started Notepad instance is not closed by the user. That different behavior can be easily seen on removing start "" at beginning of the command line starting Notepad.
The command CHOICE gives the user of the batch file the possibility to exit the loop by pressing key N (case-insensitive) within 10 seconds. Otherwise the user prompt is automatically answered with choice Y and the loop is executed once again by first terminating running Notepad.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
choice /?
del /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
ping /?
set /?
setlocal /?
start /?
taskkill /?
See also Windows Environment Variables for details on environment variables USERPROFILE and SystemRoot as used in this batch file.

command in for loop behaves differently (Batch file)

I'm running a command in a batch file[Just for info: this command runs a python script which generates different outputs]
The code is as follows:
:meshfunc
echo "starting command"
echo "!inst_dir!runME.bat -parameter1 !parameter2! !parameter1v! -script pythonscript.py"
echo start_time=!time!
for /F "delims=" %%i IN ('"!inst_dir!runME.bat -parameter1 !parameter2! !parameter1v! -script pythonscript.py"') DO (
set cmdline=%%i
echo currentENDline=!cmdline!
)
EXIT /B 0
The output of the script is:
PS: I have stripped the output lines for obvious reasons, but they shouldn't matter here
So my questions is :
If i run the same command without a for loop , it will complete in maybe 30 sec without the warning at the end.
However, if I run it inside a for loop, it takes much longer about 3 mins and gives the warning at the end
Why am I'm getting the Warning at the end as shown. Why is this happening?
Because for /F execute the command enclosed in parentheses and store all its output in a temporary disk file until the command ends; after that, it start to repeatedly execute the group of commands. In this way, if the output is very large, the temporary file needs to grow several times and such a process takes some time... It should be faster to redirect the output to a disk file and then process such a file with for /F:
:meshfunc
echo "starting command"
echo "!inst_dir!runME.bat -parameter1 !parameter2! !parameter1v! -script pythonscript.py"
echo start_time=!time!
call "!inst_dir!runME.bat" -parameter1 !parameter2! !parameter1v! -script pythonscript.py > output.txt
for /F "delims=" %%i IN (output.txt) DO (
set cmdline=%%i
echo currentENDline=!cmdline!
)
EXIT /B 0

Batch script that monitors for file changes

I need to create a batch script that continually monitors a specific file for changes, in this case, LogTest.txt.
When the file is updated it will trigger a VBScript message box, which displays the last line from within LogTest.txt. The idea is that this will continue monitoring after the message box is cleared.
I have tried using the forfiles option, but this really only lets me deal with the date and not the time. I know that PowerShell and other options are available, but for reasons that are just too long to explain I am limited to being only able to use a batch and VBScript.
Batch File:
#echo off
:RENEW
forfiles /m LogTest.txt /d 0
if %errorlevel% == 0 (
echo The file was modified today
forfiles /M LogTest.txt /C "cmd /c echo #file #fdate #ftime"
cscript MessageBox.vbs "Error found."
REM do whatever else you need to do
) else (
echo The file has not been modified today
dir /T:W LogTest.txt
REM do whatever else you need to do
)
goto :RENEW
MessageBox.vbs:
Set objArgs = WScript.Arguments
messageText = objArgs(0)
MsgBox "This is an error", vbOkCancel + vbExclamation, "Error Found"
There is an archive attribute on every file. Windows sets this attribute on every write access to the file.
You can set it with the attrib command and check it for example with:
#echo off
:loop
timeout -t 1 >nul
for %%i in (LogTest.txt) do echo %%~ai|find "a">nul || goto :loop
echo file was changed
rem do workload
attrib -a LogTest.txt
goto :loop
timeout /t 1 >nul: small wait interval to reduce CPU-Load (never build a loop without some idle time)
for %%i in (logTest.txt) do... process the file
echo %%~ai print the attributes (see for /? for details)
|find "a" >nul try to find the "a"rchive-attribute in the output of the previous echo and redirect any output to nirvana (we don't need it, just the errorlevel)
|| goto :loop works as "if previous command (find) failed, then start again at the label :loop"
If find was successful (there is the archive attribute), then the next lines will be processed (echo file was changed...)
attrib -a LogTest.txt unsets the archive attribute of the file.

redirecting .exe output within batch script to txt file

i am trying to redirect output from an exe(commanline exe) which is being called in from batch file to log file. In this script IP addresses of hostnames provided in input.txt are being redirected to result.txt. i am trying to run .exe within same batch script to place those IPs in maintenance mode in my monitoring tool. Script runs fine and performs the action as expected but it fails to capture the output from .exe. please help.
#echo off
setlocal enabledelayedexpansion
set OUTPUT_FILE=result.txt
>nul copy nul %OUTPUT_FILE%
for /f %%i in (input.txt) do (
set SERVER_ADDRESS=ADDRESS N/A
for /f "tokens=1,2,3" %%x in ('ping -n 1 %%i ^&^& echo SERVER_IS_UP') do (
if %%x==Pinging set SERVER_ADDRESS=%%y
if %%x==Reply set SERVER_ADDRESS=%%z
if %%x==SERVER_IS_UP (set SERVER_STATE=UP) else (set SERVER_STATE=DOWN)
)
echo !SERVER_ADDRESS::=!>>%OUTPUT_FILE%
)
start c:\MaintenanceMode.exe ON %OUTPUT_FILE% %USERNAME% >> "c:\result2.txt"
Output from .exe if i run it directly from command prompt:
PS C:\> .\MaintenanceMode.exe ON C:\result.txt username
Not an IP!!
Reading IPs from File: C:\result.txt
Valid Arguments
System put into MM Host# 10.*.*.* Status# Success
System put into MM Host# 10.*.*.* Status# Success
You are redirecting the output of the START command, but not the exe.
If you want to use START and redirect the output, then you most execute a new CMD.EXE session and escape the redirection so it occurs within the new session:
start cmd /c c:\MaintenanceMode.exe ON %OUTPUT_FILE% %USERNAME% ^>^> "c:\result2.txt"
But why are you using START? It would be so much simpler if you simply execute your exe directly:
c:\MaintenanceMode.exe ON %OUTPUT_FILE% %USERNAME% >> "c:\result2.txt"

batch to check if the first script out of two has completely created a .csv file and then execute second script

I have two scripts. First script creates .csv files which are used as input for second script.
Can someone please let me know what additional steps I need to write in between below two lines so that second script will only start execution when first script has completely written all the files in .csv format.
start "" /wait /b "D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_EXTRACT.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_EXTRACT.CONF"
start "" /wait /b "D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_DATA_MAP.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_DATA_MAP.conf"
You could try something like this. It loop untill the process "BES_EXTRACT.exe" is finished. when the task is running %ERRORLEVEL% will be "0" when the task is finished %ERRORLEVEL% will change to "1" and the loop will end. so when "BES_EXTRACT.exe" is finished %ERRORLEVEL% will change to "1" and "BES_DATA_MAP.exe" will start
Echo Date:%date% Time:%time% >> error.txt
#echo off
(
Echo Date:%date% Time:%time%
start "" /wait /b "D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_EXTRACT.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_EXTRACT.CONF"
:loop
for /f "tokens=2 delims=: " %%a in ('tasklist ^| find "BES_EXTRACT.exe"' ) do (
if "%ERRORLEVEL%"=="0" (
ping -n 10 localhost > nul 2>nul
goto loop
)
)
start "" /wait /b "D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_DATA_MAP.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_DATA_MAP.conf"
) >> Output.txt 2>> error.txt
Explanation
the the for loop uses the "tasklist" and the find command to check if the task "BES_EXTRACT.exe" is running if it is running it sets %ERRORLEVEL% to "0". If the %ERRORLEVEL% is "0" the script will ping yourown PC 10 times then go back and start the for loop again the Ping command is only there to count 10 Seconds (each ping is 1 second) then when the first script is finished the for loop will set %ERRORLEVEL% to "1" which ends the loop and starts the second script. This is a short explaination of the script if you require more of an explaination let me know :)
Have you tried it without the start command?
Normal command line programs will pause until done before the next line is executed.
#echo off
"D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_EXTRACT.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_EXTRACT.CONF"
"D:\ITSMaaS\BTscripts\capgemini\BESExtract\bin\BES_DATA_MAP.exe" "-f D:\ITSMaaS\BTscripts\capgemini\BESExtract\conf\BES_DATA_MAP.conf"

Resources