如何通过批处理脚本检查进程是否正在运行
我怎样才能检查一个应用程序是否从一个批处理文件(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
我希望这可以帮助别人。
我喜欢WMIC
和TASKLIST
工具,但是它们不能在家庭/基本版本的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的解决方案** 的代码项目文章。
非编程方式来检查:
- 启动Cmd.exe
- 启动一个应用程序(例如,
c:\windows\notepad.exe
) - 在Process Explorer中检查Notepad.exe进程的属性
- 检查父进程(这显示了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. )
如前所述,这需要管理权限。