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

时间:2008-10-02 13:35:00

标签: windows command-line batch-file

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

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

该应用程序也可以像任何用户一样运行。

18 个答案:

答案 0 :(得分:298)

我提出的另一种可能性,灵感来自于使用grep,是:

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

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

答案 1 :(得分:58)

以下是我如何解决这个问题:

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

如果尚未运行,上面的内容将会打开Notepad

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

答案 2 :(得分:35)

我喜欢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

这对我很有帮助......

答案 3 :(得分: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)

答案 4 :(得分:17)

npocmaka使用QPROCESS代替TASKLIST的建议很棒但是,它的答案是如此之大和复杂,以至于我觉得有必要发布一个非常简化的版本,我想这将解决大多数非高级版本的问题用户:

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

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

答案 5 :(得分: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

答案 6 :(得分: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!

无论如何,我希望有所帮助。我知道,如果你像我这样的新手,阅读批处理/命令行有时会让人感到困惑。

答案 7 :(得分:6)

answer provided by 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

我希望这有助于其他人。

答案 8 :(得分:6)

values

答案 9 :(得分:5)

我喜欢WMICTASKLIST工具,但它们在家庭/基本版本的Windows中不可用。另一种方法是在几乎每台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不可用,则应予以考虑。

如果将进程用作参数,则使用名称的更简单用法(在传递可执行文件名的情况下,.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将仅过滤当前用户的进程。

通过Windows脚本主机exe而不是WMI使用WMIC对象也是一个选项。它也应该在每台Windows机器上运行(不包括关闭WSH的那些但是这是一个罕见的情况)。这是通过WMI类列出所有进程的bat文件,可以在上面的脚本中使用而不是QPROCESS(它是一个jscript / bat混合,应保存为.bat):< / p>

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

答案 10 :(得分:2)

我不知道如何使用内置CMD,但如果你有grep,你可以尝试以下方法:

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

答案 11 :(得分:0)

我在这里假设窗户。因此,您需要使用WMI来获取该信息。查看脚本专家archives,了解有关如何从脚本中使用WMI的大量示例。

答案 12 :(得分:0)

如果您有多个同名的 .exe 文件并且您只想检查其中一个(例如您关心 C:\MyProject\bin\release\MyApplication.exe 而不是 C:\MyProject\ bin\debug\MyApplication.exe) 然后你可以使用以下内容:

@echo off

set "workdir=C:\MyProject\bin\release"
set "workdir=%workdir:\=\\%"

setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
    wmic process  where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"'   get CommandLine^,ProcessId  /format:value
`) do (
    for /f "tokens=* delims=" %%G in ("%%a")  do (
        if "%%G" neq "" (
rem            echo %%G
            set "%%G"
rem            echo !ProcessId!
            goto :TheApplicationIsRunning
        )
    )
) 

echo The application is not running
exit /B

:TheApplicationIsRunning
echo The application is running
exit /B

答案 13 :(得分:0)

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

注意:

  • “。exe”是必需的
  • 您可以使用以下版本的参数使文件可运行
string

:: 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 )

答案 14 :(得分:0)

我使用script provided by 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

答案 15 :(得分:0)

您应该检查父进程名称,请参阅The Code Project有关.NET based solution**的文章。

检查的非程序化方式:

  1. 启动Cmd.exe
  2. 启动应用程序(例如,c:\windows\notepad.exe
  3. 检查Process Explorer
  4. 中Notepad.exe进程的属性
  5. 检查父进程(显示cmd.exe)
  6. 可以通过获取父进程名称来检查相同内容。

答案 16 :(得分:-1)

vtrz's answerSamuel Renkert's answer on an other topic的基础上,我提出了以下脚本,如果它尚未运行,则只运行%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.
)

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

答案 17 :(得分:-2)

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

tasklist | grep program