Writing a simple batch file that checks if a program is running - windows

Me and couple of my friends are using a shared folder on Dropbox, where've uploaded our minecraft server. The point of this is that anyone can launch a server at any time, insted of one person having to run it all the time.
The only problem is, two people might launch the server at the same time, and overlapping save files might occur. To combat this, I want to write a simple batch file.
The logic is this:
IF the process "minecraft_server.1.8.1" is running, rename the the server folder to "RUNNING AS _INSERT_NAME_HERE_", ELSE rename it back to "Minecraft server"
The NAME would be read as a computer name (if that's at all possible), or from some txt file that a user would create (to write their own name)
I've never written a batch file and I don't know if this is possible, but it seems simple enough and any help would be appreciated.
Thank you in advance.
Ok so after a bit of tinkering, I wrote my first batch file. For the most part it seems to be working, however I can't seem to implement a proper loop.
#echo off
IF EXIST *_RUNNING.txt (
echo "ERROR, SERVER ALREADY RUNNING as %computername%"
pause
EXIT
) ELSE (
copy NUL %computername%_RUNNING.txt
START /WAIT minecraft_server.1.8.1.exe
tasklist /FI "IMAGENAME eq javaw.exe" 2>NUL | find /I /N "javaw.exe">NUL
:loop
IF "%ERRORLEVEL%"=="0" (
TIMEOUT /t 5
GOTO loop
) ELSE (
del %computername%_RUNNING.txt
echo "Server ended."
pause
EXIT ) )
When I start minecraft_server.1.8.1.exe it then launches javaw.exe, and that is the actual process that starts the server. After that I just check if the process is still running or not. However I can't seem to loop that particular part of the code, I keep getting synatx errors.

This is not exactly what you are looking for in the topic of the question, but if I get it right you would like to avoid that a server is started twice. So I would do the following:
Create a batch-file that:
First checks if a file named *_MinecraftServer.txt exists. If yes, it assumes that the server is already running and simply exits.
If no such file exists, it creates the file.
Then it starts the server.
Once the server exits, the file is deleted.
This would be something like this:
#echo off
REM Define a filename for the text-file informing other people that a server is running
SET FILENAME=%computername%_MinecraftServer.txt
REM Check if such a file already exists, if not refuse to start:
if exist *_MinecraftServer.txt (
REM Such a file exists, print the content of the file:
echo "ERROR, SERVER ALREADY RUNNING"
type *_MinecraftServer.txt
) else (
REM No such file is found. Create a file, then start the server process.
echo "SERVER is running on %computername%" > %FILENAME%
REM replace the notepad.exe with the name of the server.exe (and all params it requires)
REM Maybe you will also need to write the full-path to the server
notepad.exe
REM Once the server exits, remove the file
del %FILENAME%
echo "Server exited"
)
REM Require the user to hit a key before exiting the batch:
pause
This sample batch starts a notepad.exe and created a file COMPUTERNAME_MinecraftServer.txt.
You would have to replace notepad.exe with the path to the minecraft server exe.
Note that I'm not sure if this batch works if any of the directories involved contains spaces.
And of course this only works if from now on all people start the server only using the batch-file.
Also, theoretically multiple servers can be run if multiple users start the server at more or less the same time, as there is some delay until dropbox will have uploaded and distributed the created txt-file.

Related

Can I prevent a batch file to be executed by more than 1 user at the same time

I have a batch file which can update a web project and clean/rebuild it. I made it executable for network users. Now I want to make the batch executable only by one user at the same time. Like synchronize object in programming languages.
Is there a possibility to do that?
A simple solution to check if batch file is already running is using file system.
The batch file can check if a file exists and denies execution in this case, otherwise it creates the file, runs the commands and finally deletes the file.
#echo off
if exist "C:\Temp\BatchLock.txt" goto BatchRunning
echo Batch file is running by %username%.>C:\Temp\BatchLock.txt
rem All other commands of the batch file
del C:\Temp\BatchLock.txt
goto :EOF
:BatchRunning
type C:\Temp\BatchLock.txt
echo/
echo Please run the batch later again.
echo/
echo Press any key to exit ...
pause >nul
Of course C:\Temp is not a good storage location for the lock text file. It must be a directory which is identical for all users, a directory on server with write permissions for all users.

How to get an exclusive lock on a file using batch file?

I have a project I need to monitor a batch file which constantly runs to see if its still working. I have a remote machine which needs to monitor this batch file running on another server.
What i need to do is have the batch file create and exclusively lock a text file (can be empty, can be full it does not matter). This is so I can poll it from my remote machine (using an exe created by c#) to see if there is exclusive lock on the file - if so, then do nothing. If can get a lock, then raise alarm (as the batch has failed).
Understand this is probably not the best approach, but unfortunately its what I have to go with. So, is there a way to exclusively lock a file (automatically) using a batch file?
I was skeptical about this initially, but it turns out it can be done by using file redirection. Consider this example:
#echo off
if '%1' == '-lock' (
shift
goto :main
)
call %0 -lock > lockfile.txt
goto :eof
:main
echo %DATE% %TIME% - start
TREE C:\
echo %DATE% %TIME% - finish
goto :eof
Whilst the above batch is running, it is not possible to delete lockfile.txt.
Essentially, the batch checks for a '-lock' parameter. If it's not present, it re-executes itself with the -lock parameter and re-directs it's own output to lockfile.txt
It's also possible to create locks for 'critical' sections within a batch e.g.
#echo off
echo %DATE% %TIME% - started
(
echo Starting TREE
tree c:\
echo TREE finished
) > lock2.lock
echo %DATE% %TIME% - finished
Sources:
How do you have shared log files under Windows?
http://www.dostips.com/forum/viewtopic.php?p=12454
Here is a plain vanilla batch file to lock a particular file temporarily. Edit the txt path accordingly.
#ECHO OFF
powershell.exe -command "$lock=[System.IO.File]::Open('C:\test.txt','Open','ReadWrite','None');Write-Host -NoNewLine 'Press any key to release the file...';$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')"
It unlocks when you press the any key.

how to send each iteration of a loop in a batch script to a new cmd window and continue with loop

Disclaimer: I'm an engineer not a programmer, so while I do have technical knowledge, please bear with me if I am using the wrong terminology or asking the wrong questions.
I am trying to write a windows batch script that will allow me to submit multiple finite element simulations as a batch with all of the same settings. I currently have a script that works after a fashion, but it is not as efficient as I would like. My current script steps through the directories and runs the simulation in the command window before moving on to the next directory and repeating the loop. This script can be seen below:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
title BEST FRM Runs batch submission
echo This script will step through the run# directories and run the blast.k file in each run# folder. The .cmd file needs to be placed in the "FRMRuns" directory. You may need to change the reference to the LSDYNA solver if the version has changed.
SET /P ANSWER=Do you want to continue (y/n)?
if /i {%ANSWER%}=={y} (goto :yes)
if /i {%ANSWER%}=={n} (goto :no)
:yes
SET /P i=Enter input file name (e.g blast.k)
SET /P n=Enter number of CPUs (e.g. 2)
SET /P m=Enter memory (e.g 500m)
FOR /D %%D IN (run*) DO (
echo %%D
cd %%D
set lstc_license=network
set lstc_license_server=###.##.##.##
::the solver reference may need to be changed as we move on to new versions
c:\LSDYNA\program\ls971_s_R5.1.1_winx64_p.exe i=%i% ncpu=%n% memory=%m%
cd ..
)
exit /b
:no
exit /b
Our network licensing for LSDYNA allows for queuing of jobs, so ideally I would like to run through the entire loop and have the jobs run simultaneously rather than run one after another. I think this would be possible if I could send each iteration of the loop to a new command window and have it execute independently while the loop in batch script continues.
I'm not sure if I am searching for the wrong things, or if this is a unique request, but I have not been able to find anything that really helps with what I am trying to do. I have tried various things using start /b cmd /k, but I have not been able to pass the loop commands to the new window and have the loop continue in the original window. I have managed to get the new window to open, but not to actually execute any commands, and the code does not continue until the new window is closed.
I would appreciate any suggestions that you might have for how to accomplish my goal.
Thank you!
This starts each command in it's own process, with the start "" at the beginning.
start "" c:\LSDYNA\program\ls971_s_R5.1.1_winx64_p.exe i=%i% ncpu=%n% memory=%m%

Take the result of previous command safely : Batch (Wait,Sleep,Ping etc..)

I am trying to create a batch file which is doing these things :
move some folder
call another batch file
copy the result of batch file to clipboard
run the imacros (imacros will use the clipboard)
So the important thing is I have to be sure for every step that it is completed. Because every step is attached together.
My question is how can I do that ? I read something about SLEEP, PING, TIMEOUT, PAUSE etc.. But I cannot know very much prons and cons. Could someone give some tips about these commands or which should i use for safe programming ?
Not : I am working on windows xp and windows server 2008
And here is my batch code :
#echo off
set cwd=D:\workset\xx\yyy\
set wp=D:\workset\xx\yyyy\zzzzz\
:: ensure folder exist
mkdir %cwd% > nul 2>&1
mkdir %wp%\done > nul 2>&1
d:
cd %wp%
:export
::echo tidy folder %wp%
for %%i in (xx_to_yy*.zip) do (
move "%%i" "done\%%i"
)
echo call %cwd%aaa_bbb_export.bat
call %cwd%aaa_bbb_export.bat 5555
#echo off
for %%i in (xx_to_yy*.zip) do (
echo %wp%%%i | clip
move "%%i" "done\%%i"
)
#echo off
:finish
start "" "C:\Program Files\Mozilla Firefox\firefox.exe" http://www.google.com
ping 127.1.1.1
start "" "C:\Program Files\Mozilla Firefox\firefox.exe" imacros://run/?m=yyy.iim
Using the pause and echo command is a great way to debug a piece of scrip in batch.
Simply add:
Echo Task Complete: [Description] : Continue ?&>nul pause
At the end of every task. That way, you can check if everythings fine before giving the all clear for you batch file to continue. Later on, you'll learn to do error checking in batch files, in which case you could do something similar with an error message and include soloutions as options.
Edit:
If you wish to automate the script, so that it doesn't need user input, and instead attempts to check ikf an error occured you could either:
Check manualy, that is 1: check if folder has moved, 2: check if other batch file did what it needed (create new files etc.) 3: check if clipboard has suffiecent lines to be result of batch files (maybe clear it at the start) and lastly, check if imacros did what was needed
Check if commands were succeful. (redirec errors to a text file and then see if they were any.
Since, I don't know exactly what you are doing, I can only help you wit case 2 (though 1 would be better). You redirect the errors as so:
command [parameters] 2>>errors.log
And at the end of every section:
set /p error=<errors.log
if defined error (
Echo An Error Occured : Last Step == [Step Description]
ECHO ---------- RUN : %Date% %Time% ----------
type errors.log >> error-log.txt
del errors.log
if "%~1"=="RESTART" (
Echo Error Occured Two Times in a Row . . .
Echo Exiting in 20 seconds . . .
Exit /b 9
)
Echo Restarting procedure in 60 seconds . . .
sleep 60
Start %~f0 "RESTART"
Exit
)
The above code will check if there were any errors, add them to a log called error-log.txt. If there is an error, it will restart and if there is an error again, it will exit. There will be a small pause before either of these events, incase you want to cancel it (simply close)
Hope you found this helpful,
Mona.
First option is, after each "critical" command, check for errorlevel
copy someThing someWhere
if errorlevel 1 (
rem something goes bad
goto somewhereToHandleIt
)
Alternatively, you can add code to check that the operation was sucessful, testing everything is where it is supossed to be. But first option is usually better. Trust the system, it will do the work and report when problems found.

pipe multiple files into a single batch file (using explorer highlight)

I can already get a batch file to run when a user right clicks on a file type. How can I make it so that only one instance runs per highlighted group and gets all the files as arguments.
Currently it runs single instance per file when a user "shift clicks"
there is most likely a better way to word this... you can see why I had trouble googling it.
thanks
Normally a file association multi-selection invocation will start several instances of a program and the program itself would have to deal with it on its own (Or with the help of DDE or IDropTarget)
It is going to be very hard to implement this in a batch file, this example should get you started:
#echo off
setlocal ENABLEEXTENSIONS
set guid=e786496d-1b2e-4a49-87b7-eb325c8cc64d
set id=%RANDOM%
FOR /F "tokens=1,2,3 delims=.,:/\ " %%A IN ("%TIME%") DO SET id=%id%%%A%%B%%C
set sizeprev=0
>>"%temp%\%guid%.lock" echo %id%
>>"%temp%\%guid%.list" echo %~1
:waitmore
>nul ping -n 3 localhost
FOR %%A IN (%temp%\%guid%.list) DO set sizenow=%%~zA
if not "%sizeprev%"=="%sizenow%" (
set sizeprev=%sizenow%
goto waitmore
)
FOR /F %%A IN (%temp%\%guid%.lock) DO (
if not "%%A"=="%id%" goto :EOF
FOR /F "tokens=*" %%B IN (%temp%\%guid%.list) DO (
echo.FILE=%%B
)
del "%temp%\%guid%.list"
del "%temp%\%guid%.lock"
pause
)
While this works, it is a horrible horrible hack and will fail badly if you don't wait for the first set of files to be parsed before starting a new operation on another set of files.
If you create a batch file and place it on your desktop, then you can select multiple files and drop them on that batch file. They will get passed as multiple parameters to the file.
For example, assume you put dropped.bat on your desktop, and it looks like this:
#echo off
echo %*
pause
Now assuming you had three files x, y and z, if you multiple-selected them and dropped them on dropped.bat, you'd see a command window come up with this text in it:
C:\Users\alavinio\Desktop\x C:\Users\alavinio\Desktop\y C:\Users\alavinio\Desktop\z
Press any key to continue . . .
That's the closest you can get. The right-click-and-Open semantics expect to start a new executable for each selected item, and typically those executables check for another instance of themselves, and if they see one, send the parameter over there to that existing process, and terminate themselves. You can actually watch that happen with Task Manager or Process Explorer.
Late to the party but here is my 2 cents. I had the same problem when trying to customise the behaviour of a 'Move to Dropbox Folder...' context menu command. I needed every file selected to be piped to a batch file to handle the processing in one instance.
After some digging I found Context Menu Launcher.
Simple enough to use. I popped singleinstance.exe in C:\Windows\system32 and created and ran a .reg file similar to below.
Windows Registry Editor Version 5.00
; Documents
[HKEY_CLASSES_ROOT\SystemFileAssociations\document\Shell\Dropbox]
#="Move to Dropbox Folder"
"Icon"="%SystemRoot%//system32//imageres.dll,-112"
"MultiSelectModel"="Player"
[HKEY_CLASSES_ROOT\SystemFileAssociations\document\Shell\Dropbox\command]
#="singleinstance.exe \"%1\" \"C:\\Move to Dropbox Folder.bat\" $files --si-timeout 400"
The way it works seems to have been imposed on you by the shell, and there doesn't seem to be an easy way to solve this.
Some application would add its own menu item that would allow the app to be invoked differently (i.e. just once for the group) from how it is done generally (repeatedly for every selected item), while another one would employ the API to check its own presence and would redirect the 'open' request to its already running copy.
Batch files aren't meant for either of these. You would probably need a different tool. Even if you would like the main job to be done by the batch file, you'd still need a way to call the batch file for processing of the item list.
I'm guessing you have a group of highlighted files and you want to run some program for each file.
#echo off
for %%A in (%*) do echo %%A
pause

Resources