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

我怎样才能检查一个应用程序是否从一个批处理文件(well cmd)运行?

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

此外,应用程序可以像任何用户一样运行。

我用grep启发的另一个可能性是:

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

它不需要保存一个额外的文件,所以我更喜欢这种方法。

以下是我的工作方式:

 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 

以上将打开记事本,如果它尚未运行。

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

我喜欢Chaosmaster的解决方案! 但我寻找一个解决方案,不启动另一个外部程序(如find.exe或findstr.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下,您可以使用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)

我使用安装在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 

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! 

无论如何,我希望有所帮助。 我知道有时阅读批处理/命令行可能会有点混乱,如果你是一个像我这样的新手。

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 

我希望这可以帮助别人。

我喜欢WMICTASKLIST工具,但是它们不能在家庭/基本版本的Windows中使用。 QPROCESS一种方法是在几乎所有的Windows机器上使用QPROCESS命令(对于那些有终端服务的人 – 我认为只有在没有SP2的情况下才能获得XP,所以实际上每个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不可用,应该考虑到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 ):

 @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的调用虽然可以减少一点点性能(也应该保存为bat):

 @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(); 

我不知道如何使用CMD构建,但如果你有grep,你可以尝试下面的方法:

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

npocmaka建议使用QPROCESS而不是TASKLIST,但是它的答案是如此之大而且复杂,所以我觉得有必要发布一个相当简单的版本,我想这将解决大多数非高级用户的问题:

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

上面的代码在Windows 7中进行了测试,具有管理员权限的用户。

我在这里假设窗户。 所以,你需要使用WMI来获取这些信息。 查看脚本专家的档案 ,了解如何从脚本使用WMI的大量示例。

我使用了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 

您应该检查父进程名称,请参阅有关基于.NET的解决方案** 的代码项目文章。

非编程方式来检查:

  1. 启动Cmd.exe
  2. 启动一个应用程序(例如, c:\windows\notepad.exe
  3. 在Process Explorer中检查Notepad.exe进程的属性
  4. 检查父进程(这显示了cmd.exe)

可以通过获取父进程名来检查。

另一个解决方案是

 @echo off setlocal EnableExtensions DisableDelayedExpansion CD "Path that contains the program" TASKLIST | FINDSTR ProgramName > NUL 2> NUL IF %ERRORLEVEL%==1 ( START ProgramName.exe ) endlocal 

建议使用“setlocal”命令来提高与其他操作系统的兼容性。

检查进程是否正在运行的行是:

 TASKLIST | FINDSTR ProgramName 

如果程序关闭,则会将“ERRORLEVEL”变量设置为1,否则设置为0。

我通常在cmd提示符下执行以下命令来检查我的program.exe是否正在运行:

 tasklist | grep program 

基于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. ) 

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