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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/162291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:27:54  来源:igfitidea点击:

How to check if a process is running via a batch script

windowscommand-linebatch-file

提问by Matt Lacey

How can I check if an application is running from a batch (well cmd) file?

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

I need to not launch another instance if a program is already running. (I can't change the app to make it single instance only.)

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

Also the application could be running as any user.

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

回答by

Another possibility I came up with, inspired by using grep, is:

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

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

It doesn't need to save an extra file, so I prefer this method.

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

回答by Matt Lacey

Here's how I've worked it out:

这是我如何解决的:

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

The above will open Notepadif it is not already running.

如果记事本尚未运行,上面将打开记事本

Edit: Note that this won't find applications hidden from the tasklist. This will include any scheduled tasks running as a different user, as these are automatically hidden.

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

回答by TrueY

I like Chaosmaster's solution! But I looked for a solution which does not start another external program (like find.exeor findstr.exe). So I added the idea from Matt Lacey's solution, which creates an also avoidable temp file. At the end I could find a fairly simple solution, so I share it...

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

This is working for me nicely...

这对我来说很好......

回答by aldemarcalazans

The suggestion of npocmaka to use QPROCESS instead of TASKLIST is great but, its answer is so big and complex that I feel obligated to post a quite simplified version of it which, I guess, will solve the problem of most non-advanced users:

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

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

The code above was tested in Windows 7, with a user with administrator rigths.

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

回答by vtrz

Under Windows you can use Windows Management Instrumentation (WMI) to ensure that no apps with the specified command line is launched, for example:

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

回答by Riccardo La Marca

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

回答by kayleeFrye_onDeck

TrueY's answer seemed the most elegant solution, however, I had to do some messing around because I didn't understand what exactly was going on. Let me clear things up to hopefully save some time for the next person.

TrueY 的答案似乎是最优雅的解决方案,但是,我不得不做一些乱七八糟的事情,因为我不明白到底发生了什么。让我把事情弄清楚,希望能为下一个人节省一些时间。

TrueY's modified Answer:

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!

Anyway, I hope that helps. I know sometimes reading batch/command-line can be kind of confusing sometimes if you're kind of a newbie, like me.

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

回答by kayleeFrye_onDeck

I use PV.exe from http://www.teamcti.com/pview/prcview.htminstalled in Program Files\PV with a batch file like this:

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

回答by benmod

The answer provided by Matt Laceyworks for Windows XP. However, in Windows Server 2003 the line

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

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

returns

回报

INFO: No tasks are running which match the specified criteria.

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

which is then read as the process is running.

然后在进程运行时读取。

I don't have a heap of batch scripting experience, so my soulution is to then search for the process name in the search.logfile and pump the results into another file and search that for any output.

我没有大量的批处理脚本经验,所以我的解决方案是在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

I hope this helps someone else.

我希望这对其他人有帮助。

回答by npocmaka

I like the WMICand TASKLISTtools but they are not available in home/basic editions of windows.Another way is to use QPROCESScommand available on almost every windows machine (for the ones that have terminal services - I think only win XP without SP2 , so practialy every windows machine):

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

@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

QPROCESScommand is not so powerful as TASKLISTand is limited in showing only 12 symbols of process name but should be taken into consideration if TASKLISTis not available.

QPROCESScommand 没有那么强大,TASKLIST并且仅限于显示进程名称的 12 个符号,但如果TASKLIST不可用,则应予以考虑。

More simple usage where it uses the name if the process as an argument (the .exesuffix is mandatory in this case where you pass the executable name):

更简单的用法,如果进程作为参数,则使用名称(在.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

The difference between two ways of QPROCESSusage is that the QPROCESS *will list all processes while QPROCESS some.exewill filter only the processes for the current user.

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

Using WMIobjects through windows script host exe instead of WMICis also an option.It should on run also on every windows machine (excluding the ones where the WSH is turned off but this is a rare case).Here bat file that lists all processes through WMI classes and can be used instead of QPROCESSin the script above (it is a jscript/bat hybrid and should be saved as .bat):

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 );
}

And a modification that will check if a process is running:

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

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

The two options could be used on machines that have no TASKLIST.

这两个选项可用于没有TASKLIST.

The ultimate technique is using MSHTA. This will run on every windows machine from XP and above and does not depend on windows script host settings. the call of MSHTAcould reduce a little bit the performance though (again should be saved as bat):

终极技术是使用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();