Using batch file I scan my PC for viruses using McAfee. At the end of the scan it writes locally file called 'OnDemandScanLog.txt'. The last step before I shut down the system I have to copy this file from local directory to shared folder.
The problem is that sometimes it does not copy it. In case when it failed I always could copy it manually using 'copy' command but I need it to be done at the end of the scan.
I assume that I could copy it condititionally ... and check for ERRORLEVEL until it get copied for sure. Then it should shut down PC.
Could someone please help me to insert conditional statement in order to make sure it was copied.
I will attach my batch file:
#echo off
REM Perform a Full scan and log result
if exist "%ProgramFiles(x86)%" (
set "PATH_=%ProgramFiles(x86)%\McAfee\VirusScan Enterprise"
set SHUTDOWN=shutdown /s /f
) else (
set "PATH_=%ProgramFiles%\McAfee\VirusScan Enterprise"
set SHUTDOWN=shutdown -s -f
)
set LOGDIR=C:\McAfee
set VADIR=\\servername\McAfee Logs\Log1\
"%PATH_%\scan32.exe" /Task {ED73BEB7-1E8F-45AC-ABBC-A749AF6E2710} %* /ANALYZE /MANY /ALL /CLEAN /DAM /NC /NOEXPIRE /PLAD /PROGRAM /SUB /STREAMS /UNZIP /THREADS=4 /TIMEOUT=15 /APPEND /AUTOEXIT
copy %LOGDIR%\OnDemandScanLog.txt /Y "%VADIR%"
start %SHUTDOWN%
As XCopy has been deprecated since Vista and Windows 2008, use robocopy. It has built-in default retry... And exit codes from Robocopy are well documented
:: syntax ::
:: robocopy <Source> <Destination> [<File>[ ...]] [<Options>]
::
set "LOGDIR=C:\McAfee"
set "VADIR=\\servername\McAfee Logs\Log1"
"%PATH_%\scan32.exe" /Task ... /AUTOEXIT
robocopy "%LOGDIR%" "%VADIR%" "OnDemandScanLog.txt"
Embedded robocopy retry features could be tested by next code snippet:
#echo off
#SETLOCAL enableextensions enabledelayedexpansion
#echo :: using temporary directory %temp%
#echo :: define and make destination folder
set "destfldr=%temp%\dstfldr"
md "%destfldr%" 2>Nul
#echo :: create destination file first to be older
echo text test >"%destfldr%\mytest.txt"
#echo :: lock destination file
start "" notepad >>"%destfldr%\mytest.txt"
#echo :: waiting for 5 second to assure file is locked
ping 1.1.1.1 -n 1 -w 5000 > nul
set "sourcef=%temp%"
#echo :: create source file to be newer
echo test text %date% %time% >"%sourcef%\mytest.txt"
#echo :: classic copy file should fail
copy /Y "%sourcef%\mytest.txt" "%destfldr%\."
#echo :: robocopy file, 5 retries with seconds delay
robocopy "%sourcef%\." "%destfldr%\." "mytest.txt" /r:5 /w:3
#echo ::
#ENDLOCAL
::
Don't forget close that notepad, please :)
Well, copying the log file fails if
the copy command was already executed before McAfee scan finished and therefore before exclusive file access lock was removed by McAfee scan from log file, or
the destination directory on the other computer is not yet accessible.
For the first reason I might help to use
start "Scan for malware" /wait "%PATH_%\scan32.exe" /Task {ED73BEB7-1E8F-45AC-ABBC-A749AF6E2710} %* /ANALYZE /MANY /ALL /CLEAN /DAM /NC /NOEXPIRE /PLAD /PROGRAM /SUB /STREAMS /UNZIP /THREADS=4 /TIMEOUT=15 /APPEND /AUTOEXIT
For the second reason something like the commented code below could be useful.
rem Count the retries to avoid an endless loop if server is not reachable ever.
set "RetryCount=0"
:RetryLoop
rem Copy with verification on destination directory and resume if
rem connection to destination server is lost during copy process.
copy /V /Y /Z %LOGDIR%\OnDemandScanLog.txt "%VADIR%"
rem Was there no error on copying the file?
if not errorlevel 1 goto TurnOff
rem There was an error. Therefore increase counter and shutdown
rem nevertheless if copying the log file failed already 30 times.
set /A "RetryCount+=1"
if "%RetryCount%"=="30" goto TurnOff
rem Set a default wait time of 5 seconds before next try.
set "MilliSeconds=5000"
rem Ping server to test if server connection is established at all. Increase
rem the wait time to 60 seconds before next try if server is not connected.
%SystemRoot%\System32\ping.exe -n 1 servername >nul
if errorlevel 1 set "MilliSeconds=60000"
rem Wait 5 or 60 seconds before next try.
%SystemRoot%\System32\ping 1.1.1.1 -n 1 -w %MilliSeconds% >nul
goto RetryLoop
:TurnOff
start %SHUTDOWN%
See How to sleep for 5 seconds in Windows' Command Prompt? for usage of ping to wait a certain time.
Related
I am a complete novice when it comes to scripting, but am attempting to write a batch script which runs a command to output a png file to a printer. The script I have works fine for one file, but when there are multiple files it does not.
Can anyone point me in the right direction please?
#echo off
REM ___Change Directory to where Label Is Stored___
pushd C:\AFP\to
REM ___Create Variable to capture filename of any png file___
for /F %%a in ('dir /b *.png') do set FileName=%%~na.png
REM ___Now we have the filename as a variable, send it to printer using Zebra SSDAL___
\\172.16.100.2\nDrive\Prime_DPD_Label_Print\ssdal.exe /p "TSC DA200" send %FileName% >> C:\AFP\Log\Label_Printing_Log.txt
REM ___Copy PNG File to Backup Folder___
XCOPY /y /q /c C:\AFP\to\*.png C:\AFP\backup\
REM ___Delete PNF File from To Folder___
DEL C:\AFP\to\*.png
When the script runs, the first file prints fine. The subsequent files then do not print, I get "File does not exist" back from the ssdal.exe command. Why would the first one work but not the subsequent prints? I would have expected the for to loop through.
#ECHO Off
SETLOCAL
REM ___Change Directory to where Label Is Stored___
pushd C:\AFP\to
REM ___Process all png files___
for /F "delims=" %%a in ('dir /b *.png') do (
REM ___Now we have the filename as "%%a", send it to printer using Zebra SSDAL___
\\172.16.100.2\nDrive\Prime_DPD_Label_Print\ssdal.exe /p "TSC DA200" send "%%a" >> C:\AFP\Log\Label_Printing_Log.txt
IF ERRORLEVEL 1 (
CALL ECHO SSDAL returned ERRORLEVEL %%errorlevel%% FOR "%%a"
) ELSE (
REM ___Move PNG File to Backup Folder___
IF EXIST "c:\afp\backup\%%a" (
ECHO MOVE "%%a" to backup skipped as file already exists IN backup
) ELSE (
MOVE "%%a" C:\AFP\backup\
)
)
REM Two-second delay
TIMEOUT /t 2 >nul 2>nul
)
POPD
GOTO :EOF
Ah! using Zebra printers. Sensible lad!
This replacement script should do what you want.
The setlocal command is used to ensure that any variation made by this batch to the cmd environment is discarded when the batch ends.
The delims= sets "no delimiters" so for/f will set %%a to the entire filename, even if it contains spaces or other delimiters. Quoting %%a ensures such filenames are kept together as a single unit, not interpreted as separate tokens.
I'm assuming that ssdal acts responsibly and returns errorlevel non-zero in the case of errors. The if errorlevel 1 means if the errorlevel is currently 1 or greater than 1 and in that case, the error message is generated. We need to call echo ... %%varname%% ... in order to display the current value of the variable, if we're not using delayed expansion (many SO articles explain this)
Otherwise, if ssdal was successful, check for the existence of the filename in the backup directory, and either move it there or report that it already exists.
Of course, there are many ways in which this could be manipulated if features I've added are not desired. I'm happy to adjust this script to comply.
timeout is a standard utility to wait for a keypress. The redirection takes care of its prompting (it will provide a countdown unless gagged).
I'm writing a script on a BAT file to use when necessary, to backup a folder of an application on several computers.
This script works on Windows 7: will it also work on Windows 10?
:: Backup script with logging
#echo off
net use \\SERVER\Shared_Folder userPassword /USER:userName
set PATH=c:\WINDOWS\system32;
set SRC="C:\Program Files (x86)\ApplicationName\TargetFolder"
set DST=\\SERVER\Shared_Folder\Backups
set LOG=%DST%\Backup_LogFile.log
echo:>>%LOG%
echo Backup from computer %COMPUTERNAME% >>%LOG%
echo Starts -- %DATE% %TIME% >>%LOG%
echo Wait please: backup is running...
xcopy %SRC% %DST%\%COMPUTERNAME%\ /A /D /E /J /Y /Z>>%LOG%
echo Ends -- %DATE% %TIME% >>%LOG%
echo:>>%LOG%
My script works fine but I want a better response on terminal for the user than execute it.
The script adds correctly the actions on a log file, but I want the user can see only the number of file copied not the list of all files copied.
Here is one way to accomplish what you ask. There are other ways too. The secret here is using "for /F" and sending each result to another function. The other function will log each line to a file. It will then look for xcopy's "File(s) copied" line and pipe that to the user if it sees it.
Also... note the "goto :EOF" statements. These tell the batch interpreter to return to the caller much like any other programming language.
I hope this does what you are asking. :)
:: Backup script with logging
#echo off
net use \\SERVER\Shared_Folder userPassword /USER:userName
set SRC="C:\Program Files (x86)\ApplicationName\TargetFolder"
set DST=\\SERVER\Shared_Folder\Backups
set LOG=%DST%\Backup_LogFile.log
echo:>>%LOG%
echo Backup from computer %COMPUTERNAME% >>%LOG%
echo Starts -- %DATE% %TIME% >>%LOG%
echo Wait please: backup is running...
for /f "delims=" %%f in ('xcopy %SRC% %DST%\%COMPUTERNAME%\ /A /D /E /J /Y /Z') do call :log_items "%%f"
echo Ends -- %DATE% %TIME% >>%LOG%
echo:>>%LOG%
goto :EOF
:log_items
Set InputLine=%~1
:: Log everything
echo %InputLine%>>%LOG%
:: Check if the line coming in contains "File(s) copied" if it doesn't, return
if "%InputLine:File(s) copied=%"=="%InputLine%" goto :EOF
:: If it does, show it to the user and return
echo %InputLine%
goto :EOF
The comparison done for the files copied looks like this:
For a line with your file name: (here they match so it returns)
C:\git\ps>if "test\targetver.h" == "test\targetver.h" goto :EOF
For a line with your number of files: (here they dont match do it doesn't return)
C:\git\ps>if "205 " == "205 File(s) copied" goto :EOF
#echo off
Call :YesNoBox "Press yes or no"
if "%YesNo%"=="6" (
set backupdir=D:\BackupEmail\
cd /d %backupdir%
set folder=%date:~10,4%_%date:~4,2%_%date:~7,2%_%time:~0,2%_%time:~3,2%_%time:~6,2%
mkdir %folder%
echo %folder% created
cd /d %folder%
mkdir Thunderbird
cd Thunderbird
set backupcmd=xcopy /s/h/i/c/k/e/r/y
echo ### Backing Up ...
%backupcmd% "C:\Users\username\AppData\Roaming\Thunderbird\*" "%backupdir%\%folder%\Thunderbird\"
echo Backup Completed!
echo "Deleting Temp files".
del /s /f /q \Windows\Temp\*.*
cmd /k
)
exit
:: Design for pop up window
exit /b
:YesNoBox
REM returns 6 = Yes, 7 = No. Type=4 = Yes/No
set YesNo=
set MsgType=4
set heading=%~2
set message=%~1
echo wscript.echo msgbox(WScript.Arguments(0),%MsgType%,WScript.Arguments(1)) >"%temp%\input.vbs"
for /f "tokens=* delims=" %%a in ('cscript //nologo "%temp%\input.vbs" "%message%" "%heading%"') do set YesNo=%%a
exit /b
:MessageBox
set heading=%~2
set message=%~1
echo msgbox WScript.Arguments(0),0,WScript.Arguments(1) >"%temp%\input.vbs"
cscript //nologo "%temp%\input.vbs" "%message%" "%heading%"
exit /b
I used notepad++ to save this code
Output received in command prompt:
The filename, directory name, or volume label syntax is incorrect.
The syntax of the command is incorrect.
created
The filename, directory name, or volume label syntax is incorrect.
A subdirectory or file Thunderbird already exists.
Here Thunderbird folder is created where the bat file exists, however it should have been created in "BackupEmail" folder in drive D.
When i ran it again on the same command prompt it runs successfully
What this characteristic indicates is that on the first execution there is a variable which is not set but its value is being used - normally in a if statement. However, executing the first time is establishing a value for the variable, so on the second run, the syntax is correct.
It is customary to include a setlocal command immediately after the #echo off. This makes sure that when the code is complete, any changes made to the environment are discarded. In this case, because you have no setlocal command, the variable's value is retained for the second run.
The problem with your code is the #1 FAQ - please search for delayed expansion using the search facility. The variable folder is not established when the if "%YesNo%"=="6" instruction is executed, hence on the first occasion
%folder% has no value BUT it is assigned a value within the code block and it retains that value for the second run (since there is no selocal to discard it).
#ECHO OFF
CLS
REM Start Backup
TITLE Backup
SETlocal EnableDelayedExpansion
REM Capture the date/time(right down to the second) and then assign it to a variable
SET yy=%date:~-4%
SET dd=%date:~-7,2%
SET mm=%date:~-10,2%
SET newdate=%dd%%mm%%yy%_%Time:~0,8%
SET newdate=%newdate::=%
SET foldername=svetlana_backup_%newdate%
REM Variables
SET drive=R:
SET sevenZip=%USERPROFILE%\7z.exe
SET destination=R:\Backup
ECHO Running Backup Batch File
ECHO Please Plug in %drive%
PAUSE
ECHO %foldername%
MKDIR %destination%\%foldername%
FOR /F "tokens=1,2 delims=," %%i IN (backuplist.txt) DO (
SET completeSource=%%i
SET completeDestination=%destination%\%foldername%\%%j
ECHO Source: "!completeSource:"=!"
ECHO Destination:"!completeDestination:"=!"
MKDIR "!completeDestination:"=!"
XCOPY "!completeSource:"=!" "!completeDestination:"=!" /E /F
)
REM Zip the folder using the 7z command line utility
%sevenZip% a -tzip %destination%\%foldername%.zip %destination%\%foldername%
REM Remove the unzipped backup folder
RMDIR /Q /S %destination%\%foldername%
PAUSE
EXIT
This is a backup batch file that I've been using for last couple of days. It worked well up until this morning. For some reason, when it creates the variable foldername, it contains a space in the string where there was none before. It ends up like this:
svetlana_backup_22092016_ 93829
The space between the dash and the 93829 was never there before until today for some reason. How would I remove it and prevent it from happening again?
You can parse the file-/foldername like this
set foldername=%foldername: =%
This will replace all spaces with an empty string
The problem was likely caused because the test was run at a time where the hour contained just one digit. With that %Time:~0,8% will output the time including an extra space, as the time will be stored like this: 9:38:29 which are 7 characters and you read the last 8 ones.
I've been at this for a few hours now. I'm finally giving in and asking for help. What I'm trying to do is use a batch file to get my Truecrypt volume mounted, then open Dropbox. When both of these things are done, executing the batch file the second time will exit Dropbox, then dismount the Truecrypt volume. Everything works correctly except for the exiting of Dropbox. I can't for the life of me, get it to exit Dropbox then dismount the volume. It skips right over the taskkill and just dismounts the volume. I've tried it a variety of different ways which should be working, but for some reason are not. The command window is saying taskkill isn't recognized as a command, but that's obviously bull. =\
#echo off
Set Drive=Z
Set Path="C:\Users\DK\AppData\Roaming\Dropbox.bak"
Set TrueCrypt="C:\Program Files\TrueCrypt\TrueCrypt.exe"
IF EXIST %Drive%: GoTo Dismount
GOTO Mount
:Dismount
taskkill /F /IM "dropbox.exe"
%TrueCrypt% /d %Drive% /f /w /q /s
exit
:Mount
%TrueCrypt% /v /l %Drive% %Path% /q
echo Waiting for volume...
:keepwaiting
ping -n 1 127.0.0.1 > nul
if not exist Z:\ goto keepwaiting
start "Dropbox" "C:\Users\DK\AppData\Roaming\Dropbox\bin\Dropbox.exe"
exit
Never use Path as your own variable! Change Set Path="C:\Users\DK\AppData\Roaming\Dropbox.bak" to something like Set DropboxPath="C:\Users\DK\AppData\Roaming\Dropbox.bak"
Taskkill.exe is in system32 but windows can only find it if it is listed in %Path%.
Tips:
It is probably a good idea to call setlocal as the second line in your script so your variables don't leak out of the batch file.
Never set path, pathext, temp, tmp, windir, SystemRoot, SystemDrive, OS, PROCESSOR_* or NUMBER_OF_* unless you really know what you are doing.
Use exit /B or goto :EOF instead of exit if you don't want to close a console window while you are testing...