如何检查应用程序是否从批处理(好cmd)文件运行?

如果程序已经在运行,我不需要启动另一个实例。(我不能改变应用程序,使它只有单一实例。)

此外,应用程序可以作为任何用户运行。


当前回答

TrueY的回答似乎是最优雅的解决方案,然而,我不得不瞎折腾一番,因为我不明白到底发生了什么。我先把问题讲清楚希望能给下一位同学节省点时间。

TrueY修改后的答案:

::Change the name of notepad.exe to the process .exe that you're trying to track
::Process names are CASE SENSITIVE, so notepad.exe works but Notepad.exe does NOT
::Do not change IMAGENAME
::You can Copy and Paste this into an empty batch file and change the name of
::notepad.exe to the process you'd like to track
::Also, some large programs take a while to no longer show as not running, so
::give this batch a few seconds timer to avoid a false result!!

@echo off
SETLOCAL EnableExtensions

set EXE=notepad.exe

FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% goto ProcessFound

goto ProcessNotFound

:ProcessFound

echo %EXE% is running
goto END
:ProcessNotFound
echo %EXE% is not running
goto END
:END
echo Finished!

不管怎样,我希望这对你们有帮助。我知道,如果你像我一样是新手,阅读批处理/命令行有时会有点困惑。

其他回答

我不知道如何用内置CMD这样做,但如果你有grep,你可以尝试以下:

tasklist /FI "IMAGENAME eq myApp.exe" | grep myApp.exe
if ERRORLEVEL 1 echo "myApp is not running"

我使用了Matt提供的脚本。我唯一遇到的麻烦是它不能删除search.log文件。我想是因为我必须cd到另一个位置来启动我的程序。我cd回BAT文件和search.log所在的位置,但它仍然不能删除。所以我首先删除了search.log文件,而不是最后删除。

del search.log

tasklist /FI "IMAGENAME eq myprog.exe" /FO CSV > search.log

FOR /F %%A IN (search.log) DO IF %%-zA EQU 0 GOTO end

cd "C:\Program Files\MyLoc\bin"

myprog.exe myuser mypwd

:end

我假设这里是窗户。因此,您需要使用WMI来获取该信息。查看脚本编写者的档案,有很多关于如何从脚本中使用WMI的示例。

我喜欢《混沌大师》的解决方案!但我寻找了一个解决方案,不启动另一个外部程序(如find.exe或findstr.exe)。所以我添加了Matt Lacey解决方案中的想法,它创建了一个同样可以避免的临时文件。最后我找到了一个相当简单的解决方案,所以我把它分享给大家……

SETLOCAL EnableExtensions
set EXE=MyProg.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF NOT %%x == %EXE% (
  echo %EXE% is Not Running
)

这对我很有用……

以上是编辑。最初的代码中显然有一个GOTO,有人在评论中认为这很粗俗。

空间

如果你担心程序名中可能有空格,那么你需要稍微复杂化代码:

SETLOCAL EnableExtensions
set EXE=My Prog.exe
FOR /F %%x IN ("%EXE%") do set EXE_=%%x
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF NOT %%x == %EXE_% (
  echo %EXE% is Not Running
)

无论其他正在运行的进程的名称中是否有空格,原始代码都可以正常工作。唯一需要关注的是我们所瞄准的进程是否有空间。

ELSE

请记住,如果您添加了ELSE子句,那么它将对已经运行的应用程序的每个实例执行一次。在运行此脚本时,不能保证只有一个实例在运行。

无论如何,如果你想要一个,一个GOTO或标志变量被指明。

理想情况下,目标应用程序应该已经互斥自己以防止多个实例,但这是另一个SO问题的主题,不一定适用于本问题的主题。

再次转到

我同意“ELSE”的评论。GOTO-less解决方案的问题是,可能会多次运行条件部分(和ELSE部分),所以它有点混乱,因为它必须退出循环。(对不起,我在这里不处理空间问题,因为它似乎相当罕见,并显示了一个解决方案)

SETLOCAL EnableExtensions
SET EXE=MyProg.exe
REM for testing
REM SET EXE=svchost.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF NOT %%x == %EXE% (
  ECHO %EXE% is Not Running
  REM This GOTO may be not necessary
  GOTO notRunning
) ELSE (
  ECHO %EXE is running
  GOTO Running
)
...
:Running
REM If Running label not exists, it will loop over all found tasks

我需要一个重试的解决方案。这段代码将一直运行,直到找到进程,然后将其终止。你可以设置一个超时或任何你喜欢的东西。

注:

“。exe”是必选项 你可以让一个文件运行参数,版本如下

    :: Set programm you want to kill
    :: Fileextension is mandatory
    SET KillProg=explorer.exe

    :: Set waiting time between 2 requests in seconds
    SET /A "_wait=3"

    :ProcessNotFound
        tasklist /NH /FI "IMAGENAME eq %KillProg%" | FIND /I "%KillProg%"
        IF "%ERRORLEVEL%"=="0" (
            TASKKILL.EXE /F /T /IM %KillProg%
        ) ELSE (
            timeout /t %_wait%
            GOTO :ProcessNotFound
        )

taskkill.bat:

    :: Get program name from argumentlist
    IF NOT "%~1"=="" (
        SET "KillProg=%~1"
    ) ELSE (
        ECHO Usage: "%~nx0" ProgramToKill.exe & EXIT /B
    )

    :: Set waiting time between 2 requests in seconds
    SET /A "_wait=3"

    :ProcessNotFound
        tasklist /NH /FI "IMAGENAME eq %KillProg%" | FIND /I "%KillProg%"
        IF "%ERRORLEVEL%"=="0" (
            TASKKILL.EXE /F /T /IM %KillProg%
        ) ELSE (
            timeout /t %_wait%
            GOTO :ProcessNotFound
        )

使用。\taskkill.bat ProgramToKill.exe运行