So here is what I have
:a
IF EXIST D:\ (
goto copy
) ELSE (
goto wait
)
:wait
timeout /t 300
goto a
:copy
xcopy "D:\photos" "C:\Photos From Cam"
exit
but I'm not very fond of this becuase that means it is always looping, except for the 5 minute pause, and I would like a way to do this where it doesnt run any code until it detects the files. Is this possible?
I do not think there's a better solution using just shell, than the one you already have.
You would have to use some external tools
For example refer to question Windows: File Monitoring Script (Batch/VBS).
Related
I am looking to exit my loop at a defined number of loops (10 - Loops). I looked at a few things on Google, but the loop was to do something else, so I was a little lost.
Here is my basic loop script and I hope one of you can educate me and point me in the right direction. If your wondering what I am doing it this way, here's why and if you have a better option, please let me know. I am fairly new to this batch scripting and I am open to suggestions.
This Uninstaller.exe does not pause the batch script. So I am basically looking for the Uninstaller.exe, which will be deleted upon completion of the Uninstaller.exe process. So once the loop detects the deletion of the executable, it will then exit the loop and move on to the next action in the script.
I have had a couple times where the uninstaller.exe crashed before it ended and deleted its self and prevented the batch file from continuing on. So I figured it would be best to only have it loop for a set number of times before exiting.
:: Uninstall App
"C:\Program Files\App Name\uninstall.exe" -quiet
::Validates the uninstall
SET LookForUninstaller="C:\Program Files\App Name\uninstall.exe"
:CheckForUninstaller
IF NOT EXIST %LookForUninstaller% GOTO ExitLoop
TIMEOUT /T 5 >nul
GOTO CheckForUninstaller
:ExitLoop
You may benefit from using the "start" command to run the uninstaller on a different process.
And you may also take advantage of its optional "/WAIT" which will allow the batch to wait until the process is finished to continue.
You may not need the loop after all.
i.e.
start /WAIT "C:\Program Files\App Name\uninstall.exe"
Here is what I did and seems to work ok.
::Set Uninstaller Variable
SET AppToUninstall="C:\Program Files\App Name\uninstall.exe"
:: Uninstall App
"%AppToUninstall%" -quiet
::Loops for 12 times in 10 second intervals (Total 120 seconds) to confirm deletion. Loop will exit after 12 loops and move on if uninstaller is not deleted.
for /l %%i in (1,1,12) do (
TIMEOUT /T 10 >nul
IF NOT EXIST %AppToUninstall% GOTO ExitLoop
)
:ExitLoop
I need to know how can I check in batch file if the second batch file which is opened in other command window has stopped (waiting for argument or process not successful).
#echo off
:loop
start /wait rapidminer-batch.bat -f C:\Users\AHM-PC\Documents\ccc.rmp
echo cmd stopped
pause
goto loop
When called batch ends, it returns a value to errorlevel. It works for call, don't know if for start too.
if %errorlevel% gtr 0 (
echo failed
) else (
echo success)
or call exit /b <number of error> in your called batch, to return specific value. Check exit for more details.
The normal method to provide interbatch communication is a flag file
Either you create a flag file in the main routine and wait for the started routine to delete it or wait until the started batch creates a file, and delete it.
eg
echo.>myflag.txt
start anotherbatch.bat
:loop
timeout /t 1 >nul
if exist myflag.txt goto loop
Here, the batch will wait until myflag.txt is deleted, which you do in the second batch. All you need is for the two routines to agree on a filename to use.
I'm using a network management tool to apply updates to software and I have an issue where if a users is already using the program you want to update the update will fail as you would expect.
I have been trying to put together a batch script that will detect whether the the program is running and if it is the script will wait until the user closes down the program and the apply the msi update.
I've pretty much scoured google but can only really find previous scripts that kill the program first before proceeding and I don't want that to happen as the user may lose work.
Hope someone can help!
#echo off
start "" notepad.exe
:loop
(tasklist | find /i "notepad.exe" && ( ping -n 2 localhost & goto loop)) >nul
echo Notepad closed
This just starts notepad.exe (the running program) and waits until it is closed. Adapt according to your needs
`tasklist |find "programname"`
will tell you if the programm is running:
if %errorlevel%==0 echo running
put just a little loop around it:
:loop
tasklist |find "programname" >nul
if %errorlevel%==0 (
echo prgram running
timeout 2>nul
goto loop
)
echo program not running
I need to check whether a file is created and locked or not, using a batch file,
if the file is locked the program should wait and check periodically whether the file is released from lock, and when it gets unlocked the program should exit.
I am very new to writing batch files (started today)
This is what I have tried:
#echo off
:loop
if (2<nul (>>test.txt echo off))(
goto END
)
else (goto MESSAGE)
:MESSAGE
echo trying to access file
goto loop
:END
pause
You were close :) But you cannot use IF to directly test whether a command succeeded or not. Use the || conditional operator instead.
Assuming you mean Windows, and not DOS:
#echo off
:loop
2>nul (
(call ) >>test.txt
) || (
echo Trying to access file
timeout /nobreak 1 >nul
goto loop
)
(call ) is simply a very efficient way to perform a no-op that always returns success.
The TIMEOUT introduces a 1 second delay to prevent the loop from hogging CPU resources.
See How to check in command-line if a given file or directory is locked (used by any process)? for more info on how the above works.
I like to have a final PAUSE in my *.bat scripts so I can just double click on them in Windows explorer and have the chance to read the output. However, the final PAUSE is an annoyance when I run the same script from the command line.
Is there any way to detect whether we are running the script from a command prompt (or not) and insert the PAUSE (or not) accordingly?
(Target environment is Windows XP and greater.)
Update
I've managed to compose this from Anders's answer:
(((echo.%cmdcmdline%)|find /I "%~0")>nul)
if %errorlevel% equ 0 (
set GUI=1
) else (
set CLI=1
)
Then, I can do stuff like this:
if defined GUI pause
#echo off
echo.Hello World
(((echo.%cmdcmdline%)|find /I "%~0")>nul)&&pause
...NT+ only, no %cmdcmdline% in Win9x probably.
As pointed out by E M in the comments, putting all of this on one line opens you up to some edge cases where %cmdcmdline% will escape out of the parenthesis. The workaround is to use two lines:
#echo off
echo.Hello World
echo.%cmdcmdline% | find /I "%~0" >nul
if not errorlevel 1 pause
I doubt that there's a distinction, because I think it just starts a command prompt and then runs the bat when you double click on it.
However, if you make shortcuts to the bat files and go to Properties and add in an extra argument (something like "/p") in the "Target" field, then you could check for the presence of that argument at the end of the script and pause if it is set. Then, running from the shortcut would cause it to end in a pause and running from command line wouldn't.
I was hoping the answer by #Anders would work in its own .bat file. Unfortunately, it does not for me. Based on #DarinH's comment, perhaps it does for some. The script below should work for all, but requires an extra parameter.
The key lies in the %CmdCmdLine% environment variable, which I imagine might be a bit different for a few edge cases.
PauseIfGui.bat
#echo off
if "%~1" == "" ((echo.%CmdCmdLine%)|"%WinDir%\System32\find.exe" /I "%~0")>nul && pause & exit /b
((echo.%CmdCmdLine%)|"%WinDir%\System32\find.exe" /I "%~1")>nul && pause
This accepts one optional parameter: the full path of calling script. If no params are passed, it runs the same as #Anders script.
AnyOtherFile.bat
#echo off
call PauseIfGui.bat %~f0
If opened from Explorer (i.e. double-clicking) , AnyOtherFile.bat will pause. If called from a command prompt, it will not.