Situation:
To keep it simple: I got multiple shortcuts on a network share that starts an VMwareclient application that connects to a console of a virtual machine. The shortcut looks something like this:
\\share\vmware-vmrc.exe -h HOST -u USER -p PASS "[LocalStorage] NAME/NAME.vmx"
But i like to know if someone is already using this console connection, so i can avoid starting this shortcut and choose another machine. So i made an script to do this and changed the shortcut to:
C:\Windows\System32\wscript.exe \\share\start.vbs NAME "[LocalStorage] NAME/NAME.vmx"
This opens a vbscript that runs an batch file silent, so it is not visible for the user.
arg = " " & WScript.Arguments.UnNamed(0) & " """ & WScript.Arguments.UnNamed(1) & """"
CreateObject("Wscript.Shell").Run "client.cmd" & arg ,0,False
This opens client.cmd that operates the launch of the VMwareclient and connects to the given virtual machine and writes a logfile to log which user has the Virtual Machine in use.
@echo off
pushd "%~dp0"
set TIMESTAMP=%TIME:~0,2%:%TIME:~3,2%
set CLIENT=%1
:start
IF EXIST logs\%client% goto msg
echo %username% since %TIMESTAMP% on %DATE% >logs\%client%
start /wait c:\vmwareclient\vmware-vmrc.exe -h HOST -u USER -p PASS %2
del logs\%client%
goto exit
:msg
for /f "delims=" %%x in ('type logs\%client%') do set "type=%%x"
echo wscript.quit MsgBox ("%client% is in use by %type%. Do you like to continue?", 4, "%client% is in use") > yesno.vbs
wscript //nologo yesno.vbs
set value=%errorlevel%
del yesno.vbs
if "%value%"=="6" start /wait c:\vmwareclient\vmware-vmrc.exe -h HOST -u USER -p PASS %2
if "%value%"=="7" goto exit
goto exit
:exit
popd
The variable %client% contains the first parameter given in the shortcut, it represents NAME.
This all works fine. But there is one problem, at "start /wait :.." the scripts waits till the client application is closed. But when the user logs off or shuts down Windows it force closes the script and it doesn't continue the script to delete the logfile. That causes the logs to be irrelevant because some users who logged off or force closed the script are still present in the logfile as if the virtual machine is still in use.
Problem:
"start /wait" waits till the application is closed, but when a user shuts down windows or logs off the script is force closed and doesn't continue.
Question:
Is there a solution to detect such force close in batch? (probably not) Do i need to switch to VBscript or an other program/script language to accomplish this?
Best option is not to check file existence, but hold a lock on file. If file is locked, it is in use. If it is not locked, you are in the scenario described with a lock file from old connection. Start the following code from two consoles to see how it works.
What it does is redirect output of stream 3 (0=stdin 1=stdout 2=stderr 3-9= for your use) to a lock/log file. This fill will have a lock on it (is is been written) while the code in the parenthesis block is running. Other instance of the batch file trying to run will not be allowed to open the lock file for writting, so the block will not be executed. This case is checked via a environment variable that is asigned a value inside the block. If it has value, the block was executed, if it has no value (not defined) the block has not been executed (the log file is locked by another process).
Stream 3 is used instead of usual output redirection to allow code inside block to echo information to console, but it is not needed.