簡體   English   中英

如何通過批處理腳本檢查進程是否正在運行

[英]How to check if a process is running via a batch script

如何檢查應用程序是否正在從批處理(well cmd)文件運行?

如果程序已經在運行,我不需要啟動另一個實例。 (我無法更改應用程序以使其僅成為單個實例。)

該應用程序也可以作為任何用戶運行。

我想出的另一種可能性,它不需要保存文件,靈感來自使用grep是:

tasklist /fi "ImageName eq MyApp.exe" /fo csv 2>NUL | find /I "myapp.exe">NUL
if "%ERRORLEVEL%"=="0" echo Program is running
  • /fi ""定義要查找的應用程序過濾器,在我們的例子中它是 *.exe 名稱
  • /fo csv定義了輸出格式, csv 是必需的,因為默認情況下,如果可執行文件的名稱太長,則可能會被截斷,因此以后find將無法匹配。
  • find /I表示不區分大小寫匹配,可以省略

有關整個語法,請參閱tasklist命令的手冊頁。

這是我如何解決的:

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

這對我來說很好......

npocmaka 使用 QPROCESS 而不是 TASKLIST 的建議很好,但是,它的答案是如此龐大和復雜,以至於我覺得有必要發布它的一個非常簡化的版本,我想這將解決大多數非高級用戶的問題:

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

上面的代碼在 Windows 7 中進行了測試,用戶具有管理員權限。

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

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

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!

無論如何,我希望這會有所幫助。 我知道,如果您是像我這樣的新手,有時閱讀批處理/命令行有時會讓人感到困惑。

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

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工具,但它們在TASKLIST家庭版/基本版中不可用。 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不可用,則應予以考慮。

更簡單的用法,如果進程作為參數使用名稱(在這種情況下, .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 *將列出所有進程,而QPROCESS some.exe將僅過濾當前用戶的進程。

通過 Windows 腳本主機 exe 而不是WMIC使用WMI對象也是一種選擇。它也應該在每台 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的調用可能會降低一點性能(再次應保存為 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"

只是提一下,如果您的任務名稱真的很長,那么它不會完整地出現在任務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
)

如果您有多個同名的 .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

我假設這里有窗戶。 因此,您需要使用 WMI 來獲取該信息。 查看腳本專家的檔案以獲取有關如何從腳本使用 WMI 的大量示例。

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

如前所述,這需要管理權限。

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

我需要一個重試的解決方案。 此代碼將一直運行,直到找到該進程,然后將其終止。 如果您願意,您可以設置超時或任何內容。

筆記:

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

我通常在 cmd 提示符下執行以下命令來檢查我的 program.exe 是否正在運行:

tasklist | grep program

您應該檢查父進程名稱,請參閱有關基於.NET 的解決方案的代碼項目文章**

一種非編程方式來檢查:

  1. 啟動 Cmd.exe
  2. 啟動應用程序(例如, c:\\windows\\notepad.exe
  3. 進程資源管理器中檢查 Notepad.exe 進程的屬性
  4. 檢查父進程(這顯示 cmd.exe)

同樣可以通過獲取父進程名稱來檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM