Come verificare se un processo è in esecuzione tramite uno script batch


260

Come posso verificare se un'applicazione è in esecuzione da un file batch (ben cmd)?

Non è necessario avviare un'altra istanza se un programma è già in esecuzione. (Non riesco a cambiare l'app per renderla solo una singola istanza.)

Inoltre l'applicazione potrebbe essere in esecuzione come qualsiasi utente.



12
duplicato di una domanda posta cinque anni dopo?
Matt Lacey,

@ LưuVĩnhPhúc non sono nemmeno relativamente vicini.
Cardinale - Ripristina Monica il

@JackKirby che ha detto che non è correlato?
phuclv,

3
@oopsdazie sì, in questo caso potrei sbagliarmi, ma la regola generale è quella di mantenere la domanda con la migliore raccolta di risposte e chiudere l'altra come duplicata , indipendentemente dal tempo
phuclv,

Risposte:


330

Un'altra possibilità che mi è venuta in mente, ispirata all'utilizzo di grep , è:

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

Non è necessario salvare un file aggiuntivo, quindi preferisco questo metodo.


7
questo ha funzionato bene per me (Windows XP SP3). IMHO questo è il modo più elegante di tutti proposto qui, usando solo gli strumenti forniti con Windows
hello_earth

2
Ho avuto un problema di sintassi con questa riga di comando. L'ho cambiato in tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunningper farlo funzionare (sospettando la citazione intorno alle parti if
Steve B

4
Ricorda che nelle versioni in altre lingue di XP i nomi dei filtri sono stati tradotti in codice ma non nella /?schermata di aiuto . Quindi, ad esempio, IMAGENAMEnella versione polacca è NAZWA_OBRAZU.
rsk82,

3
Sotto Win7 ho dovuto cambiarlo in tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL Il primo NUL non sembra necessario, non ho idea di cosa sia il "2", / NH è facoltativo.
Jan Doggen,

12
tasklist esce sempre con stato 0 indipendentemente dal fatto che trovi o meno attività corrispondenti, motivo per cui è inutile da solo. Dato che devi usare find (o findstr) per controllare comunque il suo output, non ha senso usare i filtri dell'elenco delle attività. Basta fare la lista delle attività | trova "myprog.exe"> nul: && vai a foundit o somesuch. Potrebbe essere necessaria l'opzione / v (dettagliata) per l'elenco delle attività.
Denis Howe,

61

Ecco come l'ho capito:

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

Quanto sopra aprirà Blocco note se non è già in esecuzione.

Modifica: si noti che questo non troverà applicazioni nascoste dall'elenco delle attività. Ciò includerà tutte le attività pianificate in esecuzione come utente diverso, poiché vengono automaticamente nascoste.


2
La modifica del formato dell'elenco attività in CSV o qualsiasi cosa tranne la tabella è importante perché il layout predefinito dell'elenco attività (tabella) tronca i nomi lunghi delle immagini che interrompono la logica.
Scott White,

4
Questa soluzione non funzionerà su Vista perché TASKLIST produce un output anche se il processo non viene trovato. Presumo che lo stesso vale per Windows 7.
dbenham,

non funziona in Windows 10. search.log contiene "INFO: non sono in esecuzione attività che soddisfano i criteri specificati". e nessun blocco note è stato avviato
Sergey,

46

Mi piace la soluzione di Chaosmaster! Ma ho cercato una soluzione che non avvii un altro programma esterno (come find.exe o findstr.exe ). Quindi ho aggiunto l'idea della soluzione di Matt Lacey, che crea anche un file temporaneo evitabile. Alla fine ho trovato una soluzione abbastanza semplice, quindi la condivido ...

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

Funziona bene per me ...


Questa soluzione funziona bene - testata in Windows 8.1. Ho notato che è sensibile al maiuscolo / minuscolo.
oliver-clare,

@LordScree Mentre lavoro su sistemi un * x la distinzione tra maiuscole e minuscole fa bene! Ho anche impostato il file system per abilitare i nomi di file con distinzione tra maiuscole e minuscole. ;)
TrueY

Funziona bene per me - testato su Windows 7 X64
Sig. Rubix

Questo non funziona se l'applicazione ha uno spazio nel nome poiché% x finisce per far parte del nome dell'applicazione fino al primo spazio.
Chris,

Una possibile soluzione sarebbe quella di verificare se l'applicazione non viene invece trovata controllando se% x == INFO: ma non so su quali versioni di Windows funzionerebbe o se esiste una soluzione migliore.
Chris,

21

Il suggerimento di npocmaka di usare QPROCESS invece di TASKLIST è fantastico ma, la sua risposta è così grande e complessa che mi sento obbligato a pubblicarne una versione piuttosto semplificata che, immagino, risolverà il problema della maggior parte degli utenti non avanzati:

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

Il codice sopra è stato testato in Windows 7, con un utente con diritti di amministratore.


Ho appena usato questa idea per interrompere due volte un processo automatizzato e ha funzionato come un incantesimo!
Davy C

Devo dire che a differenza di questo comando, le soluzioni della lista delle attività non solo sembrano troppo complicate per una query così semplice, ma eseguono anche un secondo circa e usano tonnellate di CPU! Questo è molto meglio, ha funzionato anche senza autorizzazioni di amministratore (Windows Server 2012).
Eugene Marin,

Questa sembra essere la soluzione più semplice e migliore (almeno per me) in quanto funziona così com'è quando l'applicazione ha spazi nel nome. Sono curioso di sapere quali sono i limiti di questa soluzione e perché non ha più voti.
Chris,

20

In Windows è possibile utilizzare Strumentazione gestione Windows (WMI) per assicurarsi che non vengano avviate app con la riga di comando specificata, ad esempio:

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)


Si noti che WMIC richiede privilegi amministrativi; se non ce l'hai, Only the administrator group members can use WMIC.EXE.seguita daReason:Win32 Error: Access is denied.
Jeroen Wiert Pluimers,

penso che questa sia la soluzione migliore, perché wmic ti dà una linea di comando completa lanciata e milioni di altre informazioni ...
Glavić,

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

3
In realtà funziona alla grande. Semplice! Basta essere consapevoli della distinzione tra maiuscole e minuscole se non si aggiunge /i.
Jason,

8

Uso PV.exe da http://www.teamcti.com/pview/prcview.htm installato in Programmi \ PV con un file batch come questo:

@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

1
questo funziona per me su Windows 7. La seconda riga è la directory che contiene il programma, non il programma stesso.
Fabio Cionini,

8

La risposta di TrueY sembrava la soluzione più elegante, tuttavia, ho dovuto fare un po 'di casino perché non capivo cosa stesse succedendo esattamente. Vorrei chiarire le cose per sperare di risparmiare un po 'di tempo per la prossima persona.

La risposta modificata di 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!

Spero comunque che aiuti. So che a volte leggere batch / riga di comando può essere un po 'fonte di confusione a volte se sei un novizio, come me.


6

La risposta fornita da Matt Lacey funziona per Windows XP. Tuttavia, in Windows Server 2003 la linea

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

ritorna

INFO: non sono in esecuzione attività che soddisfano i criteri specificati.

che viene quindi letto mentre il processo è in esecuzione.

Non ho un sacco di esperienza di script in batch, quindi la mia animazione è quindi cercare il nome del processo nel search.logfile e pompare i risultati in un altro file e cercare quello per qualsiasi output.

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

Spero che questo aiuti qualcun'altro.


Funziona per Win 2008. +1 per Nessuna attività in esecuzione che corrisponde ai criteri specificati.
Mangesh Pimpalkar,

5

Mi piacciono gli strumenti WMICe TASKLISTma non sono disponibili nelle edizioni home / basic di Windows. Un altro modo è usare il QPROCESScomando disponibile su quasi tutti i computer Windows (per quelli che hanno servizi terminal - penso che vinca solo XP senza SP2, quindi praticamente tutti macchina 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

QPROCESSIl comando non è così potente come TASKLISTed è limitato nel mostrare solo 12 simboli del nome del processo ma dovrebbe essere preso in considerazione se TASKLISTnon è disponibile.

Utilizzo più semplice in cui utilizza il nome se il processo come argomento (il .exesuffisso è obbligatorio in questo caso in cui si passa il nome eseguibile):

@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

La differenza tra due modi di QPROCESSutilizzo è che QPROCESS *elencherà tutti i processi mentre QPROCESS some.exefiltrerà solo i processi per l'utente corrente.

Anche l'utilizzo di WMIoggetti tramite exe host di script di Windows anziché WMICè un'opzione. Dovrebbe essere eseguito anche su tutti i computer Windows (esclusi quelli in cui il WSH è disattivato ma questo è un caso raro) .Qui file bat che elenca tutti i processi tramite WMI classi e possono essere usate al posto dello QPROCESSscript sopra (è un ibrido jscript / bat e dovrebbe essere salvato come .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 );
}

E una modifica che controllerà se un processo è in esecuzione:

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

Le due opzioni potrebbero essere utilizzate su macchine che non hanno TASKLIST.

L'ultima tecnica sta usando MSHTA. Questo verrà eseguito su tutti i computer Windows da XP e versioni successive e non dipende dalle impostazioni dell'host di script di Windows. il call di MSHTApotrebbe ridurre un po 'le prestazioni (di nuovo dovrebbe essere salvato come 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();

2

Non so come fare con CMD integrato ma se hai grep puoi provare quanto segue:

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

2

Solo menzionando, se il nome dell'attività è davvero lungo, nel tasklistrisultato non comparirà nella sua interezza , quindi potrebbe essere più sicuro (oltre alla localizzazione) verificare il contrario.

Variazione di questa risposta :

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

0

Sto assumendo Windows qui. Quindi, dovrai utilizzare WMI per ottenere tali informazioni. Dai un'occhiata agli archivi di The Scripting Guy per molti esempi su come usare WMI da uno script.


0

Ho usato la sceneggiatura fornita da Matt (2008-10-02). L'unica cosa con cui ho avuto problemi è che non avrebbe eliminato il search.logfile. Mi aspetto perché sono dovuto andare cdin un'altra posizione per avviare il mio programma. I cd'd di nuovo a dove il file BAT e search.logsono, ma ancora non sarebbero cancellare. Quindi l'ho risolto eliminando il search.logfile prima anziché l'ultimo.

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

1
@Sebastian: ci sono alcune informazioni extra aggiunte qui, quindi sono propenso a lasciarle come risposta.
Bill the Lizard,

0

È necessario controllare il nome del processo principale, consultare l' articolo del progetto Code su una soluzione basata su .NET ** .

Un modo non programmatico per verificare:

  1. Avviare Cmd.exe
  2. Avvia un'applicazione (ad esempio, c:\windows\notepad.exe)
  3. Controllare le proprietà del processo Notepad.exe in Process Explorer
  4. Verifica del processo padre (mostra cmd.exe)

Lo stesso può essere verificato ottenendo il nome del processo genitore.


0

Sulla risposta di vtrz e la risposta di Samuel Renkert su un altro argomento , mi si avvicinò con il seguente script che viene eseguito solo %EXEC_CMD%se non è già in esecuzione:

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

Come detto prima, ciò richiede privilegi amministrativi.


non ha funzionato per me e sto usando un account amministratore. Viene visualizzata una finestra DOS conNode - (computer name) ERROR: Description = Invalid query
khaverim

1
Funziona bene per me.
Mark Duncan,

1
Funziona benissimo per Windows 7 qui. Senza problemi.
galacticninja

0

Avevo bisogno di una soluzione con un nuovo tentativo. Questo codice verrà eseguito fino a quando non viene trovato il processo e quindi viene ucciso. Se lo desideri, puoi impostare un timeout o altro.

Appunti:

  • ".Exe" è obbligatorio
  • È possibile rendere eseguibile un file con parametri, versione di seguito
    :: 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
        )

Corri con .\taskkill.bat ProgramToKill.exe


-2

Di solito eseguo il seguente comando nel prompt di cmd per verificare se il mio program.exe è in esecuzione o meno:

tasklist | grep program
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.