[英]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命令的手冊頁。
我喜歡 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
這對我來說很好......
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
我希望這對其他人有幫助。
我喜歡WMIC
和TASKLIST
工具,但它們在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
我需要一個重試的解決方案。 此代碼將一直運行,直到找到該進程,然后將其終止。 如果您願意,您可以設置超時或任何內容。
筆記:
:: 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 的解決方案的代碼項目文章** 。
一種非編程方式來檢查:
c:\\windows\\notepad.exe
)同樣可以通過獲取父進程名稱來檢查。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.