如何通过批处理脚本检查进程是否正在运行


260

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

如果程序已经在运行,则无需启动另一个实例。(我无法将应用更改为仅使其成为单个实例。)

该应用程序也可以任何用户身份运行。



12
五年后问的一个问题的副本?
马特·莱西

@LưuVĩnhPhúc他们甚至都不是很近。
红衣主教-恢复莫妮卡

谁说@JackKirby没有关系?
phuclv

3
@oopsdazie是的,在这种情况下,我可能是错的,但是一般的规则是保留问题的最佳答案,并且不考虑时间,将另一个答案作为重复项关闭
phuclv

Answers:


330

grep启发,我想到的另一种可能性是:

tasklist /FI "IMAGENAME eq myapp.exe" 2>NUL | find /I /N "myapp.exe">NUL
if "%ERRORLEVEL%"=="0" echo Program is running

它不需要保存额外的文件,因此我更喜欢这种方法。


7
这对我很好(Windows XP SP3)。恕我直言,这是这里提出的所有方法中最优雅的方法,仅使用Windows附带的工具
hello_earth 2010年

2
我在此命令行中有语法问题。我将其更改为tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunning以便使其起作用(怀疑if部件周围的引号
Steve B

4
请记住,在其他语言版本的XP中,过滤器名称是用代码翻译的,但不是在帮助/?屏幕中翻译的。因此,例如IMAGENAME波兰语版本为NAZWA_OBRAZU
rsk82

3
在Win7下,我必须将其更改为tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL 第一个NUL似乎是不必要的,我也不知道'2'是什么意思,/ NH是可选的。
Jan Doggen 2013年

12
无论是否找到任何匹配的任务,tasklist始终以状态0退出,这就是为什么它本身没有用的原因。由于必须使用find(或findstr)来检查其输出,因此使用Tasklist的过滤器毫无意义。只是做任务清单| 找到“ myprog.exe”> nul:&& goto foundit或类似的东西。您可能需要/ v(详细)选项来任务列表。
Denis Howe 2014年

61

这是我的解决方法:

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

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

start notepad.exe

:end

del search.log

如果记事本尚未运行,则上面的内容将打开它。

编辑:请注意,这将找不到任务列表中隐藏的应用程序。这将包括以其他用户身份运行的所有计划任务,因为这些任务会自动隐藏。


2
将任务列表格式更改为CSV或除表以外的任何格式都很重要,因为任务列表的默认布局(表)会截断长图像名称,这会破坏逻辑。
斯科特·怀特

4
该解决方案在Vista上不起作用,因为即使找不到该进程,TASKLIST也会产生一些输出。我相信同样适用于Windows 7真的
dbenham

在Windows 10中不起作用。search.log包含“信息:没有运行符合指定条件的任务。” 而且没有启动记事本
谢尔盖(Sergey)'18年

46

我喜欢Chaosmaster的解决方案!但是我在寻找一种不会启动其他外部程序(例如find.exefindstr.exe)的解决方案。因此,我从Matt Lacey的解决方案中添加了这个想法,该解决方案创建了一个也可以避免的临时文件。最后,我可以找到一个相当简单的解决方案,所以我分享一下...

SETLOCAL EnableExtensions
set EXE=myprog.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% goto FOUND
echo Not running
goto FIN
:FOUND
echo Running
:FIN

这很适合我...


该解决方案效果很好-已在Windows 8.1中进行了测试。我确实注意到它区分大小写。
Oliver-clare 2014年

@LordScree当我在un * x系统上工作时,区分大小写对我有好处!我什至设置了文件系统以启用区分大小写的文件名。;)
TrueY 2014年

对我来说效果很好-在Windows 7 X64中测试
Rubix先生

如果应用程序名称中有空格,则此方法将不起作用,因为%x最终成为应用程序名称的一部分,直到第一个空格为止。
克里斯(Chris

可能的解决方案是检查是否未找到该应用程序,而是通过检查%x == INFO:来进行检查,但是我不知道它将在哪个Windows版本上运行,或者是否有更好的解决方案。
克里斯(Chris

21

npocmaka建议使用QPROCESS而不是TASKLIST很好,但是它的答案是如此之大和复杂,以至于我不得不发布一个相当简化的版本,我想它将解决大多数非高级用户的问题:

QPROCESS "myprocess.exe">NUL
IF %ERRORLEVEL% EQU 0 ECHO "Process running"

上面的代码在Windows 7中经过测试,并具有管理员权限。


我只是用这个想法来停止自动过程触发两次,它就像一个魅力!
戴维C

我必须说,与该命令不同,任务列表解决方案不仅对于这种简单的查询而言看起来过于复杂,而且还运行了大约一秒钟并使用了大量的cpu!这要好得多,也可以在没有管理员权限的情况下使用(Windows Server 2012)。
尤金·马林

这似乎是最简单,最好的解决方案(至少对我而言),因为当应用程序名称中包含空格时,它按原样工作。我很好奇这个解决方案的局限性以及为什么它没有更多的票数。
克里斯(Chris

20

在Windows下,您可以使用Windows Management Instrumentation(WMI)来确保没有启动具有指定命令行的应用程序,例如:

wmic process where (name="nmake.exe") get commandline | findstr /i /c:"/f load.mak" /c:"/f build.mak" > NUL && (echo THE BUILD HAS BEEN STARTED ALREADY! > %ALREADY_STARTED% & exit /b 1)


请注意,WMIC需要管理特权。如果您没有,那么Only the administrator group members can use WMIC.EXE.接下来Reason:Win32 Error: Access is denied.
Jeroen Wiert Pluimers

我认为这是最好的解决办法,因为WMIC给你推出了完整的命令行和其他畅想信息...
Glavić

13
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"

3
这实际上很棒。简单!请注意,它是区分大小写的,除非您添加/i
杰森

8

我使用安装在Program Files \ PV中的http://www.teamcti.com/pview/prcview.htm中的PV.exe 带有如下批处理文件:

@echo off
PATH=%PATH%;%PROGRAMFILES%\PV;%PROGRAMFILES%\YourProgram
PV.EXE YourProgram.exe >nul
if ERRORLEVEL 1 goto Process_NotFound
:Process_Found
echo YourProgram is running
goto END
:Process_NotFound
echo YourProgram is not running
YourProgram.exe
goto END
:END

1
这在Windows 7上对我有效。第二行是包含程序的目录,而不是程序本身。
Fabio Cionini 2012年

8

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!

无论如何,我希望能有所帮助。我知道有时阅读批处理/命令行有时会使您感到困惑,如果您像我一样是个新手。


6

Matt Lacey提供答案适用于Windows XP。但是,在Windows Server 2003中

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

退货

信息:没有运行符合指定条件的任务。

然后在进程运行时读取它。

我没有大量的批处理脚本经验,因此我的解决方案是在search.log文件中搜索进程名称,然后将结果泵入另一个文件,然后搜索任何输出。

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

FINDSTR notepad.exe search.log > found.log

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

start notepad.exe

:end

del search.log
del found.log

我希望这可以帮助其他人。


这适用于Win2008。+ 1表示没有运行符合指定条件的任务。
Mangesh Pimpalkar 2014年

5

我喜欢WMICTASKLIST工具,但是它们在QPROCESSWindows的家庭/基本版本中不可用。另一种方法是使用几乎每台Windows机器上都可用的命令(对于具有终端服务的机器-我认为只有Win XP而没有SP2,所以实际上Windows机器):

@echo off
:check_process
setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
set process_to_check=%~1
:: QPROCESS can display only the first 12 symbols of the running process
:: If other tool is used the line bellow could be deleted
set process_to_check=%process_to_check:~0,12%

QPROCESS * | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal

QPROCESS该命令不那么强大,TASKLIST并且只能显示进程名称的12个符号,但如果TASKLIST不可用,则应予以考虑。

如果使用进程作为参数,则使用名称更简单的用法(在.exe传递可执行文件名称的情况下,后缀是必需的):

@echo off
:check_process
setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
:: .exe suffix is mandatory
set "process_to_check=%~1"


QPROCESS "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal

两种QPROCESS使用方式之间的区别在于,QPROCESS *会列出所有进程,而QPROCESS some.exe只会过滤当前用户的进程。

WMI通过Windows脚本宿主exe而不是使用对象WMIC也是一种选择。它也应该在每台Windows计算机上运行(不包括已关闭WSH的计算机,但这是一种罕见的情况)。这里的bat文件列出了通过WMI列出的所有进程类,可以代替QPROCESS上面的脚本使用(它是jscript / bat混合体,应另存为.bat):

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **


@echo off
cscript //E:JScript //nologo "%~f0"
exit /b

************** end of JSCRIPT COMMENT **/


var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
var processes =  new Enumerator(colProcess);
for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    WScript.Echo( process.processID + "   " + process.Name );
}

修改将检查进程是否正在运行:

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **


@echo off
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
set process_to_check=%~1

cscript //E:JScript //nologo "%~f0" | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)

exit /b

************** end of JSCRIPT COMMENT **/


var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
var processes =  new Enumerator(colProcess);
for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    WScript.Echo( process.processID + "   " + process.Name );
}

这两个选项可以在没有的机器上使用TASKLIST

最终的技术是使用MSHTA。这将在XP及以上版本的每台Windows计算机上运行,​​并且不依赖于Windows脚本主机设置。的调用MSHTA可能会稍微降低性能(再次应保存为蝙蝠):

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **
@echo off

setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running

set process_to_check=%~1


mshta "about:<script language='javascript' src='file://%~dpnxf0'></script>" | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal
exit /b
************** end of JSCRIPT COMMENT **/


   var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);


   var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
   var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
   var processes =  new Enumerator(colProcess);
   for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    fso.Write( process.processID + "   " + process.Name + "\n");
   }
   close();

2

我不知道如何使用内置CMD进行操作,但是如果您有 grep,可以尝试以下操作:

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

2

只需提及,如果您的任务名称确实很长,那么结果将不会完整显示tasklist,因此检查相反的名称可能更安全(除了本地化)。

这个答案的变化:

:: in case your task name is really long, check for the 'opposite' and find  the message when it's not there
tasklist /fi "imagename eq yourreallylongtasknamethatwontfitinthelist.exe" 2>NUL | find /I /N "no tasks are running">NUL
if "%errorlevel%"=="0" (
    echo Task Found
) else (
    echo Not Found Task
)

0

我在这里假设窗户。因此,您将需要使用WMI来获取该信息。请查看Scripting Guy的档案,以获取有关如何从脚本中使用WMI的许多示例。


0

我使用了Matt(2008-10-02)提供脚本。我唯一遇到的麻烦是它不会删除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

1
@Sebastian:这里添加了一些额外的信息,所以我倾向于将其作为答案。
比尔蜥蜴


0

基于vtrz的答案Samuel Renkert的另一个主题的答案,我想出了以下脚本,该脚本仅在%EXEC_CMD%尚未运行时才运行:

@echo off
set EXEC_CMD="rsync.exe"
wmic process where (name=%EXEC_CMD%) get commandline | findstr /i %EXEC_CMD%> NUL
if errorlevel 1 (
    %EXEC_CMD% ...
) else (
    @echo not starting %EXEC_CMD%: already running.
)

如前所述,这需要管理权限。


不适用于我,我正在使用管理员帐户。出现一个DOS框Node - (computer name) ERROR: Description = Invalid query
khaverim

1
对我来说很好。
Mark Duncan

1
此处适用于Windows 7。没有问题。
galacticninja

0

我需要重试解决方案。该代码将一直运行,直到找到该进程,然后将其杀死。您可以设置超时,也可以根据需要设置任何内容。

笔记:

  • “ .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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.