web-dev-qa-db-fra.com

Comment vérifier si un processus est en cours d'exécution via un script batch

Comment puis-je vérifier si une application est en cours d'exécution à partir d'un fichier batch (bien cmd)?

Je n'ai pas besoin de lancer une autre instance si un programme est déjà en cours d'exécution. (Je ne peux pas modifier l'application pour n'en faire qu'une seule instance.)

De plus, l'application pourrait être en cours d'exécution en tant qu'utilisateur.

242
Matt Lacey

Une autre possibilité que j'ai imaginée, inspirée de grep , est la suivante:

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

Il n'est pas nécessaire de sauvegarder un fichier supplémentaire, je préfère donc cette méthode.

302
Chaosmaster

Voici comment j'ai résolu le problème:

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

Ce qui précède s'ouvrira Notepad s'il n'est pas déjà en cours d'exécution.

Edit: Notez que cela ne trouvera pas les applications cachées de la liste des tâches. Cela inclut toutes les tâches planifiées exécutées sous un utilisateur différent, car elles sont automatiquement masquées.

59
Matt Lacey

J'aime la solution de Chaosmaster! Mais j'ai cherché une solution qui ne démarre pas un autre programme externe (comme find.exe ou findstr.exe ). J'ai donc ajouté l'idée de la solution de Matt Lacey, qui crée un fichier temporaire évitable également. À la fin, je pouvais trouver une solution assez simple, alors je la partage ...

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

Cela fonctionne bien pour moi ...

38
TrueY

Sous Windows, vous pouvez utiliser Windows Management Instrumentation (WMI) pour vous assurer qu'aucune application avec la ligne de commande spécifiée n'est lancée, par exemple:

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)

21
vtrz

La suggestion de npocmaka d'utiliser QPROCESS au lieu de TASKLIST est géniale, mais sa réponse est si complexe et si complexe que je me sens obligé d'en publier une version assez simplifiée qui, je suppose, résoudra le problème de la plupart des utilisateurs non avancés:

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

Le code ci-dessus a été testé sous Windows 7 avec un utilisateur disposant de droits d’administrateur.

18
aldemarcalazans

La réponse de TrueY semblait la solution la plus élégante, cependant, je devais faire quelques bêtises parce que je ne comprenais pas ce qui se passait exactement. Permettez-moi de clarifier les choses pour espérer gagner du temps pour la prochaine personne.

Réponse de TrueY modifiée:

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

Quoi qu'il en soit, j'espère que cela aide. Je sais que parfois la lecture batch/ligne de commande peut être un peu déroutante parfois si vous êtes un peu novice, comme moi.

8
kayleeFrye_onDeck

J'utilise PV.exe à partir de http://www.teamcti.com/pview/prcview.htm installé dans Program Files\PV avec un fichier de commandes comme celui-ci:

@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
8
Adam

Le réponse fournie par Matt Lacey fonctionne pour Windows XP. Cependant, dans Windows Server 2003, la ligne

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

résultats

INFO: Aucune tâche en cours ne correspond aux critères spécifiés.

qui est alors lu lorsque le processus est en cours d'exécution.

Comme je n'ai pas beaucoup d'expérience en script de traitement par lots, mon objectif est de rechercher ensuite le nom du processus dans le fichier search.log, de pomper les résultats dans un autre fichier et de rechercher le résultat.

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

J'espère que ça aidera quelqu'un d'autre.

6
benmod
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
6
Riccardo La Marca

J'aime les outils WMIC et TASKLIST mais ils ne sont pas disponibles dans les éditions principale/de base de Windows. Une autre méthode consiste à utiliser la commande QPROCESS disponible sur presque toutes les machines Windows (pour celles qui disposent de services de terminal - je pense que winXP sans SP2, donc pratiquement chaque machine 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 La commande n'est pas aussi puissante que TASKLIST et ne permet d'afficher que 12 symboles du nom du processus, mais doit être prise en compte si TASKLIST n'est pas disponible.

Utilisation plus simple, où le nom est utilisé si le processus est un argument (le suffixe .exe est obligatoire dans le cas où vous passez le nom de l'exécutable):

@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 différence entre deux méthodes d'utilisation de QPROCESS est que le QPROCESS * liste tous les processus, tandis que QPROCESS some.exe ne filtre que les processus de l'utilisateur actuel.

Utiliser des objets WMI via le script windows Host Host au lieu de WMIC est également une option. Il doit également être exécuté sur toutes les machines Windows (à l'exception de celles pour lesquelles le WSH est désactivé, mais il s'agit d'un cas rare). Voici un fichier bat qui répertorie tous les processus via les classes WMI et peut être utilisé à la place de QPROCESS dans le script ci-dessus (il s’agit d’un hybride jscript/bat et doit être enregistré sous le nom .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 );
}

Et une modification qui vérifiera si un processus est en cours d'exécution:

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

Les deux options peuvent être utilisées sur des machines dépourvues de TASKLIST.

La technique ultime utilise MSHTA. Cela fonctionnera sur toutes les machines Windows à partir de XP et au-dessus et ne dépendra pas des paramètres de l'hôte de script Windows. L’appel de MSHTA pourrait cependant réduire un peu les performances (à nouveau, il devrait être enregistré en tant que batte):

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

Je ne sais pas comment faire avec CMD intégré, mais si vous avez grep , vous pouvez essayer les solutions suivantes:

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

Mentionnons simplement que si le nom de votre tâche est vraiment long, il n'apparaîtra pas dans son intégralité dans le résultat tasklist. Il pourrait donc être plus sûr (sauf la localisation) de vérifier le contraire.

Variation de cette réponse :

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

Je suppose que les fenêtres ici. Vous devrez donc utiliser WMI pour obtenir ces informations. Consultez le script archives de Scripting Guy pour de nombreux exemples sur l'utilisation de WMI à partir d'un script.

0
NotMe

J'ai utilisé le script fourni par Matt (2008-10-02). La seule chose qui me posait problème, c’est que le fichier search.log ne serait pas supprimé. Je pense que je devais cd me rendre à un autre endroit pour démarrer mon programme. Je cd 'reviens à l'emplacement où se trouvent le fichier BAT et search.log, mais il ne serait toujours pas supprimé. J'ai donc résolu le problème en supprimant le fichier search.log au lieu de dernier.

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
0
Nin

Vous devriez vérifier le nom du processus parent, voir l'article Le projet de code sur un solution basée sur .NET ** .

Un moyen non programmatique de vérifier:

  1. Lancer Cmd.exe
  2. Lancer une application (par exemple, c:\windows\notepad.exe)
  3. Vérifiez les propriétés du processus Notepad.exe dans Process Explorer
  4. Vérifier le processus parent (Ceci montre cmd.exe)

La même chose peut être vérifiée en obtenant le nom du processus parent.

0
prakash