识别批处理文件的运行实例

时间:2012-07-23 19:45:19

标签: batch-processing batch-file

这些对我不起作用。

任何有关definitelly的帮助都会纠正以下四个例子?

即使我打开了三个CMD.exe,EXAMPLE01也会回显“继续”。

----------例01 ------------

@echo off 
wmic process where name="cmd.exe" | find "cmd.exe" /c
SET ERRORLEVEL=value if "%value%" GTR 1 ( 
    ECHO This batch is not first  
    ECHO quitting ...
    )
if "%value%" LSS 2 ECHO continue

我在示例02中收到“意外的错误”消息!

-----------例02 -------

@echo off
FOR /F "usebackq tokens=2" %i IN (`tasklist ^| findstr /r /b "cmd.exe"`)
   DO taskkill /pid %%i

我在示例03中收到“是第一个”消息,即使打开了三个CMD.exe!

-----------例03 -------

 @echo off
    wmic process where name="cmd.exe" | find "cmd.exe" /c
    if "%errorlevel%" LEQ 1 echo CMD is first
    if "%errorlevel%" GTR 1 echo CMD is already running

我也可能无法在工作中访问Wmic命令,因此,在示例04中找到了另一种可能性......但无济于事。

-----------例04 -------

@echo off
Tasklist /FI "IMAGENAME eq cmd.exe" 2>NUL | find /I /N "cmd.exe">NUL
if "%ERRORLEVEL%"==0 do (goto Use) else (goto Cont)
:Cont
ECHO Only one instance running
pause

:Use
echo Application running already. Close this window

亲切的问候, Maleck

2 个答案:

答案 0 :(得分:7)

wmz在OP的代码中发现了许多错误,并且还有一个很好的建议,即使用锁文件进行并发控制。

下面是一个强大的批处理解决方案,它使用锁定文件来防止批处理文件的多个实例同时运行。它使用临时锁定文件进行并发控制。仅仅存在锁文件并不会阻止脚本运行。如果另一个进程对锁定文件具有独占锁定,则该脚本将失败。如果脚本崩溃或被删除而不删除锁定文件,这一点很重要。下一个运行脚本的过程仍然会成功,因为该文件不再被锁定。

此脚本假定脚本安装在本地驱动器上。它只允许整个机器的一个实例。有许多变体可以控制允许的并发数量。例如,将%USERNAME%合并到锁定文件名中将允许网络环境中的每个用户一个实例。在名称中加入%COMPUTERNAME%将允许网络环境中每台计算机一个实例。

@echo off
setlocal

:: save parameters to variables here as needed
set "param1=%~1"
:: etc.

:: Redirect an unused file handle for an entire code block to a lock file.
:: The batch file will maintain a lock on the file until the code block
:: ends or until the process is killed. The main code is called from
:: within the block. The first process to run this script will succeed.
:: Subsequent attempts will fail as long as the original is still running.
set "started="
9>"%~f0.lock" (
  set "started=1"
  call :start
)
if defined started (
    del "%~f0.lock" >nul 2>nul
) else (
    echo Process aborted: "%~f0" is already running
)
exit /b

:start
:: The main program appears below
:: All this script does is PAUSE so we can see what happens if
:: the script is run multiple times simultaneously.
pause
exit /b


修改

错误消息“进程无法访问该文件,因为正在被另一个进程使用。”可以通过将stderr输出重定向到外部块中的nul来抑制。

2>nul (
  9>"%~f0.lock" (
    set "started=1"
    call :start
  )
)

上述问题是主程序的所有错误消息也将被抑制。这可以通过将stderr的当前定义保存到另一个未使用的文件句柄,然后添加另一个内部块(将stderr重定向回已保存的文件句柄)来修复。

8>&2 2>nul (
  9>"%~f0.lock" (
    2>&8 (
      set "started=1"
      call :start
    )
  )
)

答案 1 :(得分:3)

  1. 您没有在任何地方设置value。即使你这样做也不会有效,因为变量是在解析时扩展的。如果您需要根据设置设置和测试变量,则需要使用延迟扩展。不需要进行比较的报价(见3)。 help set会向您显示信息延迟扩展。
  2. %我应该是%% i。 DO taskkill /pid %%i必须与其余for命令位于同一行。您还可以在正则表达式模式下使用findstr,这意味着它将搜索 cmd [任何字符] exe
  3. 您使用字符串(词汇)比较:“1”leq 1 为真为“4”leq 1也是...... )。使用等于 errorlevel等于或大于1 errorlevel 1help if显示语法
  4. 应删除与do中的3 + do (goto Use)相同的内容。 %errorlevel%==0可行,但通常建议使用errorlevel number
  5. 如何检查是否只有1 cmd运行:

    @echo off
    for /f %%i in ('Tasklist /FI "IMAGENAME eq cmd.exe" 2^>NUL' ^| find /I /c  "cmd.exe"') do (
    if %%i leq 2 (echo only one instance) else (echo More than one instance)
    )
    

    注意:这只是一个例子。我不建议将其作为一种真正的并发控制方法。我宁愿使用锁文件。