So überprüfen Sie, ob ein Prozess über ein Batch-Skript ausgeführt wird

260

Wie kann ich überprüfen, ob eine Anwendung aus einer Batch-Datei (Well Cmd) ausgeführt wird?

Ich muss keine weitere Instanz starten, wenn bereits ein Programm ausgeführt wird. (Ich kann die App nicht so ändern, dass sie nur eine einzelne Instanz ist.)

Die Anwendung kann auch als beliebiger Benutzer ausgeführt werden.

Matt Lacey
quelle
12
Duplikat einer Frage, die fünf Jahre später gestellt wurde?
Matt Lacey
@ LưuVĩnhPhúc sie sind nicht einmal relativ nah.
Kardinal - Wiedereinsetzung Monica
@ JackKirby wer hat gesagt, dass es nicht verwandt ist?
Phuclv
3
@oopsdazie Ja, ich kann mich in diesem Fall irren, aber die allgemeine Regel ist, die Frage mit der besten Sammlung von Antworten zu behalten und die andere als Duplikat zu schließen , unabhängig von der Zeit
phuclv

Antworten:

330

Eine andere Möglichkeit, die ich mir durch die Verwendung von grep ausgedacht habe , ist:

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

Es muss keine zusätzliche Datei gespeichert werden, daher bevorzuge ich diese Methode.

pkamb
quelle
7
Das hat bei mir gut funktioniert (Windows XP SP3). IMHO ist dies der eleganteste Weg von allen hier vorgeschlagenen, nur mit den mit Windows
gelieferten
2
Ich hatte ein Syntaxproblem mit dieser Befehlszeile. Ich habe es in tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunninggeändert, damit es funktioniert ( ich vermute das Zitat um die if-Teile
Steve B
4
Bitte denken Sie daran, dass in anderen Sprachversionen von XP die Filternamen in Code übersetzt wurden, jedoch nicht in den /?Hilfebildschirm. So ist zum Beispiel IMAGENAMEin polnischer Version NAZWA_OBRAZU.
rsk82
3
Unter Win7 musste ich es ändern in tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL Der erste NUL scheint unnötig, ich habe keine Ahnung, wofür die '2' ist, der / NH ist optional.
Jan Doggen
12
Die Aufgabenliste wird immer mit dem Status 0 beendet, unabhängig davon, ob passende Aufgaben gefunden wurden oder nicht. Deshalb ist sie für sich genommen nutzlos. Da Sie find (oder findstr) verwenden müssen, um die Ausgabe zu überprüfen, macht es keinen Sinn, die Filter der Taskliste zu verwenden. Einfach tasklist | find "myprog.exe"> nul: && goto foundit oder so. Möglicherweise benötigen Sie die Option / v (ausführlich) für die Aufgabenliste.
Denis Howe
61

So habe ich es ausgearbeitet:

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

Das oben genannte öffnet den Editor, wenn er noch nicht ausgeführt wird.

Bearbeiten: Beachten Sie, dass hierdurch keine Anwendungen gefunden werden, die in der Aufgabenliste versteckt sind. Dies schließt alle geplanten Aufgaben ein, die als anderer Benutzer ausgeführt werden, da diese automatisch ausgeblendet werden.

Matt Lacey
quelle
2
Das Ändern des Tasklistenformats in CSV oder etwas anderes als Tabelle ist wichtig, da das Standardlayout (Tabelle) der Taskliste lange Bildnamen abschneidet, was die Logik verletzt.
Scott White
4
Diese Lösung funktioniert unter Vista nicht, da TASKLIST auch dann eine Ausgabe erzeugt, wenn der Prozess nicht gefunden wird. Ich
gehe
funktioniert nicht unter Windows 10. search.log enthält "INFO: Es werden keine Aufgaben ausgeführt, die den angegebenen Kriterien entsprechen." und kein Notizblock wird gestartet
Sergey
46

Ich mag Chaosmasters Lösung! Ich habe jedoch nach einer Lösung gesucht, die kein anderes externes Programm startet (wie find.exe oder findstr.exe ). Also habe ich die Idee aus Matt Laceys Lösung hinzugefügt, die eine ebenfalls vermeidbare temporäre Datei erstellt. Am Ende konnte ich eine ziemlich einfache Lösung finden, also teile ich sie ...

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

Das funktioniert gut für mich ...

TrueY
quelle
Diese Lösung funktioniert gut - getestet in Windows 8.1. Mir ist aufgefallen, dass zwischen Groß- und Kleinschreibung unterschieden wird.
Oliver-Clare
@ LordScree Während ich an un * x-Systemen arbeite, ist Groß- und Kleinschreibung gut für mich! Ich habe sogar das Dateisystem so eingestellt, dass zwischen Groß- und Kleinschreibung unterschieden wird. ;)
TrueY
Funktioniert gut für mich - getestet in Windows 7 X64
Mr Rubix
Dies funktioniert nicht, wenn die Anwendung ein Leerzeichen im Namen enthält, da% x bis zum ersten Leerzeichen Teil des Anwendungsnamens ist.
Chris
Eine mögliche Lösung wäre zu überprüfen, ob die Anwendung nicht gefunden wird, indem überprüft wird, ob% x == INFO: aber ich weiß nicht, auf welchen Windows-Versionen dies funktionieren würde oder ob es eine bessere Lösung gibt.
Chris
21

Der Vorschlag von npocmaka, QPROCESS anstelle von TASKLIST zu verwenden, ist großartig, aber seine Antwort ist so umfangreich und komplex, dass ich mich verpflichtet fühle, eine recht vereinfachte Version davon zu veröffentlichen, die das Problem der meisten nicht fortgeschrittenen Benutzer lösen wird:

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

Der obige Code wurde in Windows 7 mit einem Benutzer mit Administratorrechten getestet.

Aldemarcalazane
quelle
Ich habe diese Idee nur verwendet, um einen automatisierten Prozess zu stoppen, der zweimal ausgelöst wurde, und es hat wie ein Zauber funktioniert!
Davy C
Ich muss sagen, dass die Aufgabenlistenlösungen im Gegensatz zu diesem Befehl nicht nur für eine so einfache Abfrage zu kompliziert aussehen, sondern auch eine Sekunde oder so ausführen und Tonnen von CPU verwenden! Dies ist viel besser und funktioniert auch ohne Administratorrechte (Windows Server 2012).
Eugene Marin
Dies scheint die einfachste und beste Lösung zu sein (zumindest für mich), da sie so funktioniert, wie sie ist, wenn die Anwendung Leerzeichen im Namen enthält. Ich bin gespannt, wo die Grenzen dieser Lösung liegen und warum sie nicht mehr Stimmen hat.
Chris
20

Unter Windows können Sie mithilfe der Windows-Verwaltungsinstrumentierung (WMI) sicherstellen, dass keine Apps mit der angegebenen Befehlszeile gestartet werden. Beispiel:

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)

vtrz
quelle
Beachten Sie, dass für WMIC Administratorrechte erforderlich sind. Wenn Sie es nicht haben, dann Only the administrator group members can use WMIC.EXE.gefolgt vonReason:Win32 Error: Access is denied.
Jeroen Wiert Pluimers
Ich denke, dies ist die beste Lösung, weil wmic Ihnen eine vollständige Befehlszeile bietet und Millionen anderer Informationen ...
Glavić
13
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
Riccardo La Marca
quelle
3
Das funktioniert eigentlich super. Einfach! Beachten Sie nur, dass zwischen Groß- und Kleinschreibung unterschieden wird, es sei denn, Sie fügen hinzu /i.
Jason
8

Ich verwende PV.exe von http://www.teamcti.com/pview/prcview.htm, das in Program Files \ PV mit einer Batchdatei wie der folgenden installiert ist:

@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

quelle
1
Dies funktioniert für mich unter Windows 7. Die zweite Zeile ist das Verzeichnis, das das Programm enthält, nicht das Programm selbst.
Fabio Cionini
8

Die Antwort von TrueY schien die eleganteste Lösung zu sein, aber ich musste ein bisschen herumspielen, weil ich nicht verstand, was genau los war. Lassen Sie mich die Dinge klären, um hoffentlich etwas Zeit für die nächste Person zu sparen.

Die modifizierte Antwort von 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!

Wie auch immer, ich hoffe das hilft. Ich weiß, dass das Lesen von Batch- / Befehlszeilen manchmal verwirrend sein kann, wenn Sie wie ich ein Neuling sind.

kayleeFrye_onDeck
quelle
6

Die Antwort von Matt Lacey funktioniert unter Windows XP. In Windows Server 2003 jedoch die Zeile

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

kehrt zurück

INFO: Es werden keine Aufgaben ausgeführt, die den angegebenen Kriterien entsprechen.

Dies wird dann gelesen, während der Prozess ausgeführt wird.

Ich habe keine Erfahrung mit Batch-Skripten, daher ist es meine Aufgabe, nach dem Prozessnamen in der search.logDatei zu suchen, die Ergebnisse in eine andere Datei zu pumpen und diese nach Ausgaben zu durchsuchen.

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

Ich hoffe das hilft jemand anderem.

benmod
quelle
Dies funktioniert unter Win 2008. +1 für Es werden keine Aufgaben ausgeführt, die den angegebenen Kriterien entsprechen.
Mangesh Pimpalkar
5

Ich mag die WMICund TASKLISTTools, aber sie sind nicht in den Home / Basic-Editionen von QPROCESSWindows verfügbar. Eine andere Möglichkeit besteht darin, Befehle zu verwenden, die auf fast jedem Windows-Computer verfügbar sind (für diejenigen, die Terminaldienste haben - ich denke, nur XP ohne SP2 zu gewinnen, also praktisch jeden Windows-Maschine):

@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

QPROCESSDer Befehl ist nicht so leistungsfähig wie TASKLISTund zeigt nur 12 Symbole des Prozessnamens an. Er sollte jedoch berücksichtigt werden, wenn er TASKLISTnicht verfügbar ist.

Einfachere Verwendung, wenn der Name verwendet wird, wenn der Prozess als Argument dient (das .exeSuffix ist in diesem Fall obligatorisch, wenn Sie den Namen der ausführbaren Datei übergeben):

@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

Der Unterschied zwischen zwei QPROCESSVerwendungsarten besteht darin, dass QPROCESS *alle Prozesse aufgelistet QPROCESS some.exewerden, während nur die Prozesse für den aktuellen Benutzer gefiltert werden.

Die Verwendung von WMIObjekten über Windows Script Host Exe anstelle von WMICist ebenfalls eine Option. Sie sollte auch auf jedem Windows-Computer ausgeführt werden (mit Ausnahme derjenigen, auf denen der WSH deaktiviert ist, dies ist jedoch ein seltener Fall). Hier ist eine Bat-Datei, in der alle Prozesse über WMI aufgelistet sind Klassen und kann anstelle des QPROCESSobigen Skripts verwendet werden (es ist ein jscript / bat-Hybrid und sollte als gespeichert werden .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 );
}

Und eine Änderung, die überprüft, ob ein Prozess ausgeführt wird:

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

Die beiden Optionen können auf Maschinen verwendet werden, die keine haben TASKLIST .

Die ultimative Technik ist die Verwendung MSHTA. Dies wird auf jedem Windows-Computer ab XP ausgeführt und hängt nicht von den Windows-Skript-Hosteinstellungen ab. Der Aufruf von MSHTAkönnte die Leistung jedoch ein wenig reduzieren (sollte wieder als Fledermaus gespeichert werden):

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

Ich weiß nicht, wie ich das mit eingebautem CMD machen soll, aber wenn Sie grep haben , können Sie Folgendes versuchen:

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

Nur zu erwähnen, wenn Ihr Aufgabenname wirklich lang ist, wird er nicht vollständig in der Liste angezeigt tasklist Ergebnis Daher ist es möglicherweise sicherer (außer bei der Lokalisierung), nach dem Gegenteil zu suchen.

Variation dieser Antwort :

:: 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
)
drzaus
quelle
0

Ich gehe hier von Fenstern aus. Sie müssen also WMI verwenden, um diese Informationen zu erhalten. In den Archiven von The Scripting Guy finden Sie viele Beispiele zur Verwendung von WMI in einem Skript.

Nicht ich
quelle
0

Ich habe das Skript von Matt (2008-10-02) verwendet. Das einzige, mit dem ich Probleme hatte, war, dass die search.logDatei nicht gelöscht wurde . Ich erwarte, weil ich an cdeinen anderen Ort musste, um mein Programm zu starten. Ich würde cddorthin zurückkehren, wo sich die BAT-Datei search.logbefindet, aber sie würde immer noch nicht gelöscht. Also habe ich das behoben, indem ich die search.logDatei zuerst statt zuletzt gelöscht habe .

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
Nin
quelle
1
@Sebastian: Hier wurden ein paar zusätzliche Informationen hinzugefügt, daher bin ich geneigt, diese als Antwort zu hinterlassen.
Bill the Lizard
0

Sie sollten die übergeordneten Prozessnamen überprüfen, siehe The Code Project Artikel über eine .NET - basierte Lösung ** .

Eine nicht programmatische Methode zur Überprüfung:

  1. Starten Sie Cmd.exe
  2. Starten Sie eine Anwendung (z. B. c:\windows\notepad.exe )
  3. Überprüfen Sie die Eigenschaften des Prozesses Notepad.exe im Prozess-Explorer
  4. Nach übergeordnetem Prozess suchen (Dies zeigt cmd.exe)

Dasselbe kann überprüft werden, indem der Name des übergeordneten Prozesses abgerufen wird.

Prakash
quelle
0

Aufbauend auf vtrz Antwort und Samuel Renkert Antwort auf ein anderes Thema , kam ich mit dem folgenden Skript, die nur läuft , %EXEC_CMD%wenn es nicht bereits ausgeführt wird :

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

Wie bereits erwähnt, sind hierfür Administratorrechte erforderlich.

Calimo
quelle
hat bei mir nicht funktioniert und ich benutze ein Administratorkonto. Eine DOS-Box erscheint mitNode - (computer name) ERROR: Description = Invalid query
khaverim
1
Funktioniert gut für mich.
Mark Duncan
1
Funktioniert hier hervorragend für Windows 7. Keine Probleme.
Galacticninja
0

Ich brauchte eine Lösung mit einem erneuten Versuch. Dieser Code wird ausgeführt, bis der Prozess gefunden wurde, und beendet ihn dann. Sie können eine Zeitüberschreitung oder etwas anderes einstellen, wenn Sie möchten.

Anmerkungen:

  • Die ".exe" ist obligatorisch
  • Sie können eine Datei mit den folgenden Parametern ausführbar machen
    :: 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
        )

Laufen Sie mit .\taskkill.bat ProgramToKill.exe

Patrick
quelle
-2

Normalerweise führe ich den folgenden Befehl in der cmd-Eingabeaufforderung aus, um zu überprüfen, ob meine program.exe ausgeführt wird oder nicht:

tasklist | grep program
Rajeev Jayaswal
quelle