Jak sprawdzić, czy proces działa za pomocą skryptu wsadowego

260

Jak mogę sprawdzić, czy aplikacja działa z pliku wsadowego (dobrze cmd)?

Nie muszę uruchamiać innej instancji, jeśli program jest już uruchomiony. (Nie mogę zmienić aplikacji tak, aby była pojedynczą instancją).

Aplikacja może również działać jak każdy użytkownik.

Matt Lacey
źródło
12
duplikat pytania zadanego pięć lat później?
Matt Lacey,
@ LưuVĩnhPhúc nie są nawet stosunkowo blisko.
Kardynał - Przywróć Monikę
@JackKirby, kto powiedział, że to nie jest powiązane?
phuclv
3
@ oopsdazie tak, mogę się mylić w tym przypadku, ale ogólną zasadą jest zachowanie pytania z najlepszym zbiorem odpowiedzi i zamknięcie drugiego jako duplikatu , niezależnie od czasu
phuclv

Odpowiedzi:

330

Inną możliwością, którą wymyśliłem, zainspirowaną użyciem grep , jest:

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

Nie musi zapisywać dodatkowego pliku, więc wolę tę metodę.

pkamb
źródło
7
działało to dla mnie ładnie (Windows XP SP3). IMHO jest to najbardziej elegancki ze wszystkich proponowanych tutaj, przy użyciu tylko narzędzi dostarczanych z oknami
hello_earth
2
Miałem problem ze składnią tego wiersza poleceń. Zmieniłem go na tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunning, aby działał (podejrzewając cytat wokół części if
Steve B,
4
Pamiętaj, że w innych wersjach językowych XP nazwy filtrów zostały przetłumaczone w kodzie, ale nie na /?ekranie pomocy . Na przykład IMAGENAMEw polskiej wersji jest NAZWA_OBRAZU.
rsk82
3
W Win7 musiałem zmienić go na tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL Pierwszy NUL wydaje się niepotrzebny, nie mam pojęcia do czego służy „2”, / NH jest opcjonalne.
Jan Doggen,
12
tasklist zawsze kończy pracę ze statusem 0, niezależnie od tego, czy znajdzie jakieś pasujące zadania, dlatego sam w sobie jest bezużyteczny. Ponieważ i tak musisz użyć find (lub findstr), aby sprawdzić jego wyniki, nie ma sensu używać filtrów tasklist. Po prostu zrób listę zadań znajdź „myprog.exe”> nul: && goto foundit lub somesuch. Do listy zadań może być potrzebna opcja / v (pełna).
Denis Howe
61

Oto jak to wypracowałem:

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

Powyższe spowoduje otwarcie Notatnika, jeśli jeszcze nie jest uruchomiony.

Edycja: Pamiętaj, że nie znajdzie to aplikacji ukrytych przed listą zadań. Obejmie to wszelkie zaplanowane zadania uruchomione jako inny użytkownik, ponieważ są one automatycznie ukryte.

Matt Lacey
źródło
2
Zmiana formatu listy zadań na CSV lub cokolwiek innego niż tabela jest ważna, ponieważ domyślny układ (tabela) tasklisty obcina długie nazwy obrazów, co psuje logikę.
Scott White
4
To rozwiązanie nie będzie działać w systemie Vista, ponieważ TASKLIST generuje dane wyjściowe, nawet jeśli proces nie zostanie znaleziony. Zakładam, że to samo dotyczy systemu Windows 7.
dbenham
nie działa w systemie Windows 10. search.log zawiera „INFO: Nie są uruchomione żadne zadania, które spełniają podane kryteria”. i nie uruchomiono notatnika
Sergey
46

Podoba mi się rozwiązanie Chaosmaster! Ale szukałem rozwiązania, które nie uruchamia inny program zewnętrzny (jak Find.exe lub Findstr.exe ). Dodałem więc pomysł z rozwiązania Matta Laceya, który tworzy również plik tymczasowy, którego można uniknąć. Na koniec mogłem znaleźć dość proste rozwiązanie, więc dzielę się nim ...

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

To mi ładnie działa ...

Prawda
źródło
To rozwiązanie działa dobrze przetestowane w systemie Windows 8.1. Zauważyłem, że wielkość liter ma znaczenie.
oliver-clare
@ LordScree Jak pracuję na systemach un * x, rozróżnianie wielkości liter jest dla mnie dobre! Ustawiłem nawet system plików, aby włączał nazwy plików z rozróżnianiem wielkości liter. ;)
TrueY
Działa dobrze dla mnie - przetestowane w Windows 7 X64
Mr Rubix
Nie działa to, jeśli aplikacja ma spację w nazwie, ponieważ% x kończy się częścią nazwy aplikacji aż do pierwszej spacji.
Chris
Możliwym rozwiązaniem byłoby sprawdzenie, czy aplikacja nie została znaleziona, poprzez sprawdzenie, czy% x == INFO: ale nie wiem, na których wersjach systemu Windows to działałoby lub czy jest lepsze rozwiązanie.
Chris
21

Sugestia npocmaka, aby użyć QPROCESS zamiast TASKLIST, jest świetna, ale jej odpowiedź jest tak duża i złożona, że ​​czuję się zobowiązany do opublikowania dość uproszczonej wersji, która, jak sądzę, rozwiąże problem większości nie zaawansowanych użytkowników:

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

Powyższy kod został przetestowany w systemie Windows 7 z użytkownikiem z uprawnieniami administratora.

aldemarcalazans
źródło
Właśnie wykorzystałem ten pomysł, aby dwukrotnie zatrzymać automatyczny proces strzelania i zadziałało to jak urok!
Davy C
Muszę powiedzieć, że w przeciwieństwie do tego polecenia, rozwiązania Tasklist nie tylko wyglądają na zbyt skomplikowane dla tak prostego zapytania, ale także uruchamiają sekundę lub więcej i wykorzystują mnóstwo procesora! Jest to o wiele lepsze, działało również bez uprawnień administratora (Windows Server 2012).
Eugene Marin
To wydaje się być najprostszym i najlepszym rozwiązaniem (przynajmniej dla mnie), ponieważ działa tak, jak jest, gdy aplikacja ma spacje w nazwie. Jestem ciekawy, jakie są ograniczenia tego rozwiązania i dlaczego nie ma on więcej głosów.
Chris
20

W systemie Windows można użyć Instrumentacji zarządzania Windows (WMI), aby upewnić się, że nie zostaną uruchomione żadne aplikacje z określonym wierszem poleceń, na przykład:

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
źródło
Pamiętaj, że WMIC wymaga uprawnień administracyjnych; jeśli go nie masz, a Only the administrator group members can use WMIC.EXE.następnieReason:Win32 Error: Access is denied.
Jeroen Wiert Pluimers
myślę, że to najlepsze rozwiązanie, ponieważ wmic daje pełny wiersz poleceń i milion innych informacji ...
Glavić
13
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
Riccardo La Marca
źródło
3
To naprawdę działa świetnie. Prosty! Pamiętaj tylko, że wielkość liter ma znaczenie, chyba że dodasz /i.
Jason
8

Używam PV.exe z http://www.teamcti.com/pview/prcview.htm zainstalowanego w Program Files \ PV z plikiem wsadowym takim jak ten:

@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

źródło
1
to działa dla mnie w systemie Windows 7. 2. linia to katalog zawierający program, a nie sam program.
Fabio Cionini
8

Odpowiedź TrueY wydawała się najbardziej eleganckim rozwiązaniem, musiałem jednak trochę popsuć, ponieważ nie rozumiałem, co się właściwie dzieje. Pozwólcie, że wyjaśnię wszystko, aby, mam nadzieję, zaoszczędzić trochę czasu dla następnej osoby.

Zmodyfikowana odpowiedź 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!

W każdym razie mam nadzieję, że to pomoże. Wiem, że czasami czytanie partii / wiersza poleceń może być mylące, jeśli jesteś rodzajem początkującym, takim jak ja.

kayleeFrye_onDeck
źródło
6

Odpowiedź udzielana przez Matt Lacey działa na systemie Windows XP. Jednak w Windows Server 2003 linia

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

zwroty

INFORMACJE: Nie są uruchomione żadne zadania, które spełniają określone kryteria.

który jest następnie odczytywany podczas działania procesu.

Nie mam zbyt wielu doświadczeń ze skryptami wsadowymi, więc moją duszą jest wyszukiwanie nazwy procesu w search.logpliku i pompowanie wyników do innego pliku i wyszukiwanie dowolnego wyniku.

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

Mam nadzieję, że to pomaga komuś innemu.

benmod
źródło
Działa to dla Win 2008. +1 dla Nie są uruchomione żadne zadania, które spełniają określone kryteria.
Mangesh Pimpalkar,
5

Lubię narzędzia WMICi TASKLIST, ale nie są one dostępne w domowych / podstawowych edycjach systemu QPROCESSWindows. Innym sposobem jest użycie polecenia dostępnego na prawie każdym komputerze z systemem Windows (dla tych, które mają usługi terminalowe - myślę, że wygrywam tylko XP bez SP2, więc praktycznie każdy maszyna z systemem 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

QPROCESSpolecenie nie ma tak dużej mocy TASKLISTi jest ograniczone do wyświetlania tylko 12 symboli nazwy procesu, ale należy je wziąć pod uwagę, jeśli TASKLISTnie jest dostępne.

Prostsze użycie, gdy używa nazwy, jeśli proces jest argumentem ( .exesufiks jest obowiązkowy w tym przypadku, gdy przekazujesz nazwę pliku wykonywalnego):

@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

Różnica między dwoma sposobami QPROCESSużycia polega na tym, że QPROCESS *wyświetla listę wszystkich procesów, a QPROCESS some.exefiltruje tylko procesy dla bieżącego użytkownika.

Używanie WMIobiektów przez exe hosta skryptu Windows zamiast WMICjest również opcją. Powinien on działać również na każdym komputerze z systemem Windows (z wyjątkiem tych, w których WSH jest wyłączony, ale jest to rzadki przypadek). Oto plik nietoperzy, który zawiera listę wszystkich procesów za pośrednictwem WMI klas i mogą być używane zamiast QPROCESSw powyższym skrypcie (jest to hybryda jscript / bat i powinna zostać zapisana jako .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 );
}

I modyfikacja, która sprawdzi, czy proces jest uruchomiony:

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

Dwie opcje mogą być używane na komputerach, które nie mają TASKLIST.

Wykorzystuje się najlepszą technikę MSHTA. Działa to na każdym komputerze z systemem Windows od XP i nowszych i nie zależy od ustawień hosta skryptu Windows. wywołanie MSHTAmoże nieco obniżyć wydajność (ponownie należy zapisać jako nietoperz):

@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
źródło
2

Nie wiem, jak to zrobić z wbudowanym CMD, ale jeśli masz grep , możesz spróbować:

tasklist /FI "IMAGENAME eq myApp.exe" | grep myApp.exe
if ERRORLEVEL 1 echo "myApp is not running"
Motti
źródło
2

Wystarczy wspomnieć, że jeśli nazwa zadania jest naprawdę długa, to wynik nie pojawi się w całości tasklist, więc może być bezpieczniej (poza lokalizacją) sprawdzić, czy jest odwrotnie.

Odmiana tej odpowiedzi :

:: 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
źródło
0

Zakładam, że tutaj są okna. Musisz więc użyć WMI, aby uzyskać te informacje. Przejrzyj archiwa The Scripting Guy, aby znaleźć wiele przykładów używania WMI ze skryptu.

Nie ja
źródło
0

Użyłem skryptu dostarczonego przez Matta (02.10.2008). Jedyne, z czym miałem problem, to to, że nie usunąłby search.logpliku. Spodziewam się, ponieważ musiałem cdwybrać inną lokalizację, aby uruchomić program. Jestem cd„d z powrotem do miejsca, gdzie plik bat i search.logsą, ale to nadal nie będzie usunąć. Rozwiązałem więc ten problem, usuwając search.logplik najpierw zamiast ostatniego.

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
źródło
1
@Sebastian: Dodano tu trochę dodatkowych informacji, więc jestem skłonny zostawić to jako odpowiedź.
Bill the Lizard
0

Powinieneś sprawdzić nazwę procesu nadrzędnego, zobacz artykuł Code Project o rozwiązaniu opartym na .NET ** .

Nieprogramowy sposób sprawdzenia:

  1. Uruchom Cmd.exe
  2. Uruchom aplikację (na przykład c:\windows\notepad.exe)
  3. Sprawdź właściwości procesu Notepad.exe w Process Explorer
  4. Sprawdź proces nadrzędny (pokazuje cmd.exe)

To samo można sprawdzić, uzyskując nazwę procesu nadrzędnego.

prakash
źródło
0

Opierając się na odpowiedź vtrz za i odpowiedzi w sprawie Samuela Renkert innym temacie , wpadłem na następujący skrypt, który działa tylko %EXEC_CMD%jeśli nie jest już uruchomiony:

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

Jak powiedziano wcześniej, wymaga to uprawnień administracyjnych.

Calimo
źródło
nie działało dla mnie i używam konta administratora. Node - (computer name) ERROR: Description = Invalid query
Okno
1
Działa dobrze dla mnie.
Mark Duncan
1
Działa świetnie na Windows 7 tutaj. Nie ma problemów.
galacticninja
0

Potrzebowałem rozwiązania z ponowną próbą. Ten kod będzie działał do momentu znalezienia procesu, a następnie go zabije. Możesz ustawić limit czasu lub cokolwiek, jeśli chcesz.

Uwagi:

  • „.Exe” jest obowiązkowe
  • Możesz uruchomić plik z parametrami, wersja poniżej
    :: 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
        )

Biegnij z .\taskkill.bat ProgramToKill.exe

Patrick
źródło
-2

Zwykle wykonuję następujące polecenie w wierszu polecenia cmd, aby sprawdzić, czy mój program.exe jest uruchomiony, czy nie:

tasklist | grep program
Rajeev Jayaswal
źródło