windows - How can I run a batch file only one time per comptuer?

06
2014-04
  • David

    I have a batch file that I want to push out to make some changes, but the changes take a while and only need to be done one time, how can I manage this?

  • Answers
  • David

    You can create a flag file. When the program first starts up, it checks if the flag is already there, and exits if it does. When the program is done, it creates the flag file.

    SET FLAG=C:\Flag.txt
    IF EXIST %FLAG% GOTO END
    
    DO WORK > %FLAG%
    
    :END
    

  • Related Question

    windows - How can I prevent to run same batch file twice to allow only one instance?
  • Nime Cloud

    I need to detect if a batch file is already running or not.

    In the batch I simply loop and repeatedly do some tasks. Sometimes the loop cannot complete. I run the batch file at a scheduled time. When it runs, it should check if a previous instance exists and is healthy. If it doesn't exist it should start a new instance. If the instance that exist is not healthy/outdated, the new instance should kill/cancel the older process.

    A few theories:

    1. How can I detect a previous instance in a batch file? Can I give an ID like thing?
    2. I can use a pulse mechanism to say the batch is healty; ie, a global variable, a newly created dummy file, a timestamp in a dummy file, etc.
    3. Can I detect a kind of "timeout", if the last pulse is expired then allow a new instance...

    Yes, I all want them in a batch file - instead of a Windows app - I think it's not so hard for one who is a batch-file addict and takes this question as challenge!


  • Related Answers
  • surfasb

    This is rather difficult from a batch file standpoint, mainly because there is no guaranteed method for a batchfile to detect instances across processes.

    IMO, I think you are using the wrong tool. While, yes, it is a challenge, the more important concern is "Does it work?"

    I run batch file in a scheduled time.

    This tells me you should be using a scheduling program, like Task Scheduler. Task Scheduler will guarantee there is only one instance of your file, even if it is running on another user.

    For example, if you run the task every 30 minutes, you configure the task to run for a duration of 30 minutes. Then you set the "if task is already running" setting to "do not create a new instance." Or you have to option of "kill the old one", "Run another instance", or "Start a new task as soon as the old one is done".

    For Vista and up: http://technet.microsoft.com/en-us/library/cc748993.aspx#BKMK_cmd
    For Xp and up: http://technet.microsoft.com/en-us/library/bb490996.aspx

    The challenging method is to create states.

    1. Your batch file enters execution
    2. Your batch file loops
    3. Your batch file ends

    You can create an arbitrary file in %allusersprofile%, like >>Startmybatchfile.txt echo 1 for each state, then check if it exists. It will also help with trouble shooting. But don't delete the file at the end. Just change it to End State. That way it's deterministic if your batch file has truly finished and no longer running.

    I would not use a global variable as it requires admin privileges to run.

    You could also use the %temp% variable as but that changes from user to user. I guess that isn't a concern if you are a single login user machine.

  • Nime Cloud

    I just finished the batch file which one ensures both monitoring itself -the batch file- and the job file -facerecog.exe- are running smoothly. I've used hello.exe as a test probe tool, you may replace your own; ie. ping.exe, etc. When it starts without any parameter it fires another instance and quit, so you can run it as a scheduled task in specific intervals. I hope it helps someone who don't want to use advanced tools.

        @goto code
    
        :comments
        @REM RunMagick for FaceRecog
        @REM Runs FaceRecog forever
        @REM Author Emin Akbulut [email protected]
        @REM 29/11/2011
        @REM This code is freeware
    
    
        :code
        @C:
        @CD C:\NET\FaceRecog
    
        :settings
        set jobexe=FaceRecog.exe
        set remotehost=192.168.35.211
        set remoteport=1333
        @REM Timeout for response of the batch, in seconds
        set /a timeout=120
        set batchtitle=Monitoring FaceRecog...
    
    
        :requirements
        @if NOT exist "stopwatch.exe" (
        @echo. stopwatch.exe is missing!
        @ping localhost > nul
        start http://www.jfitz.com/dos/stopwatch10.zip
        goto end
        ) 
    
    
    
    
        :menu
        @if "%1" == "/monitor" goto monitor
        @if "%1" == "/stop" goto request-stop
        @if "%1" == "/force-stop" goto stop
    
    
        :batch-instance-check 
        tasklist /v /fi "IMAGENAME eq cmd.exe" | find /I /c "%batchtitle%"
        @if "%ERRORLEVEL%" == "0" goto batch-instance-found
        goto start
    
        :batch-instance-found
        @REM Check the previous instance is healthy/responsive or not
        stopwatch stop < pulse.log > elapsed.log
        set /a elapsed=999
        for /F %%a in ('type elapsed.log') do set /a elapsed=%%a
        if %elapsed% gtr %timeout% (
        taskkill /F /FI "WINDOWTITLE eq %batchtitle%*"
        goto start
        ) else (
        @echo Already running...
        @ping localhost > nul
        goto end
        )
    
        del elapsed.log
    
    
    
        @goto monitor
    
    
    
        :run-job
        @REM Test FaceRecog process
        tasklist | Find "FaceRecog.exe"
        @If Not ErrorLevel 1 Goto monitor
    
        taskkill /f /im:conime.exe
        @PING 1.1.1.1 -n 1 -w 1000 >NUL
        start FaceRecog.exe
        @REM Take a breathe
        @PING 1.1.1.1 -n 1 -w 1000 >NUL
        @goto run-job
    
        :start
        @REM Fire another instance with /monitor command and exit
        start "%batchtitle%" /low /I %0 /monitor
        goto end
    
        :stop
        @REM Stop the job
        taskkill /F /IM:%jobexe%
        @REM Stop the batch
        taskkill /F /FI "WINDOWSTITLE eq %batchtitle%*"
        del stop.log > nul
        title Done
        goto end
    
        :request-stop
        @REM Ask programs to quit
        @REM %jobexe% /quit
        @REM Take a breathe
        @ping localhost > nul
        stopwatch start > stop.log
        goto end
    
        :monitor
        stopwatch start > pulse.log
        @REM Test /stop requested
        @if exist stop.log goto stop
        @REM Test FaceRecog process
        tasklist | Find "%jobexe%"
        @If Not ErrorLevel 0 Goto run-job
    
        :shorttest
        @Echo Shorttest...
        hello.exe %remotehost% %remoteport% | Find "Version" 
        @If Not ErrorLevel 1 Goto job-ok
    
        :crashcheck
        @REM No response, crashed?
        tasklist | Find "WerFault.exe"
        @If ErrorLevel 1 Goto longcheck
        taskkill /F /IM:WerFault.exe
        @goto shorttest
    
        :longcheck
        @Echo Longtest...
        @REM Last check, maybe FaceRecog was busy
        hello.exe %remotehost% %remoteport% | Find "Version" 
        @If Not ErrorLevel 1 Goto job-ok
    
        :nonresponsive
        @REM Kill non-responsive FaceRecog process and wait for a while to auto-revive
        taskkill /F /IM:%jobexe%
    
    
    
        :job-ok
        @echo OK
        @REM 10 seconds to wait then loop again
        @PING 1.1.1.1 -n 1 -w 10000 >NUL
        @goto monitor
    
    
        :end
    

    Thanks stijn for his great comment. Thanks surfasb for his warning about Scheduled Task that already running.