在注销或关闭时完成批处理/ vbs脚本

时间:2013-12-19 10:15:31

标签: vb.net windows batch-file vbscript forceclose

情况:

为了简单起见:我在网络共享上有多个快捷方式,启动连接到虚拟机控制台的VMwareclient应用程序。快捷方式如下所示:

\\share\vmware-vmrc.exe -h HOST -u USER -p PASS "[LocalStorage] NAME/NAME.vmx"

但我想知道是否有人已经在使用此控制台连接,因此我可以避免启动此快捷方式并选择其他计算机。所以我制作了一个脚本来执行此操作并将快捷方式更改为:

C:\Windows\System32\wscript.exe \\share\start.vbs NAME "[LocalStorage] NAME/NAME.vmx"

这将打开一个运行批处理文件静默的vbscript,因此对用户不可见。

arg = " " & WScript.Arguments.UnNamed(0) & " """ & WScript.Arguments.UnNamed(1) & """"
CreateObject("Wscript.Shell").Run "client.cmd" & arg ,0,False

这将打开client.cmd,它运行VMwareclient的启动并连接到给定的虚拟机并写入日志文件以记录哪个用户正在使用虚拟机。

@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

变量%client%包含快捷方式中给出的第一个参数,它表示NAME。

一切正常。但是有一个问题,在“start / wait:..”脚本等待客户端应用程序关闭。但是当用户注销或关闭Windows时,它会强制关闭脚本,并且不会继续脚本来删除日志文件。这会导致日志无关紧要,因为注销或强制关闭脚本的某些用户仍然存在于日志文件中,就好像虚拟机仍在使用中一样。

问题:

“start / wait”等待应用程序关闭,但是当用户关闭窗口或注销脚本时,强制关闭并且不会继续。

问题:

是否有解决方案可以批量检测此类力量? (可能不是) 我是否需要切换到VBscript或其他程序/脚本语言才能实现此目的?

1 个答案:

答案 0 :(得分:0)

最佳选择不是检查文件是否存在,而是对文件进行锁定。如果文件被锁定,则它正在使用中。如果未锁定,则表示您使用旧连接中的锁定文件描述的方案。从两个控制台启动以下代码,看看它是如何工作的。

它的作用是将流3的输出(0 = stdin 1 = stdout 2 = stderr 3-9 =供您使用)重定向到锁定/日志文件。当括号块中的代码运行时,此填充将对其进行锁定(已写入)。尝试运行的批处理文件的其他实例将不允许打开锁定文件进行写入,因此不会执行该块。通过在块内部赋值的环境变量来检查此情况。如果它有值,则执行该块,如果它没有值(未定义),则该块尚未执行(日志文件被另一个进程锁定)。

使用流3代替通常的输出重定向,以允许块内的代码将信息回显给控制台,但不需要它。

@echo off
    rem Prepare environment
    setlocal enableextensions

    rem The file used as flag   
    set "file=client.log"

    rem The variable used to test if we got the lock
    set "started="

    ((
        rem Mark the process as started
        set "started=yes"

        rem echo data to screen
        echo User %username% will hold the lock

        rem save data to log file. It will be on output stream 3
        echo %username% >&3

        rem Simulate the process to work
        pause >nul

        rem Redirect output stream 3 to our lock/log file
        rem Send stderr to nul to not show errors (ex. file lock fail)
    ) 3> "%file%" ) 2>nul

    rem Check if the process got the lock and has ended
    rem OR it couldn't get the lock
    if not defined started (
        <"%file%" set /p "lockedBy="
        setlocal enabledelayedexpansion
        echo(Process is locked by !lockedBy!
        endlocal
    )

    endlocal