Як перевірити, чи працює процес за допомогою пакетного сценарію


260

Як я можу перевірити, чи програма працює з пакетного (добре cmd) файлу?

Мені не потрібно запускати інший екземпляр, якщо програма вже запущена. (Я не можу змінити додаток, щоб зробити його лише одним екземпляром.)

Також програма може працювати як будь-який користувач.


Можливий дублікат програми Batch, щоб перевірити, чи існує процес
phuclv

12
дублікат запитання, заданого через п’ять років?
Метт Лейсі

@ LưuVĩnhPhúc вони навіть не відносно близькі.
Кардинал - Відновіть Моніку

@JackKirby хто сказав, що це не пов'язано?
phuclv

3
@oopsdazie Так, я можу помилитися в цьому випадку, але загальне правило - тримати питання найкращою колекцією відповідей, а інший закривати як дублікат , незалежно від часу
phuclv

Відповіді:


330

Ще одна можливість, яку я придумав, натхненний використанням грепу , - це:

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

Тут не потрібно зберігати зайвий файл, тому я віддаю перевагу цьому методу.


7
це працювало для мене чудово (Windows XP SP3). ІМХО - це найелегантніший спосіб із усіх запропонованих тут, використовуючи лише інструменти, що постачаються з вікнами
hello_earth

2
У мене була проблема синтаксису з цим командним рядком. Я змінив його на tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunningдля того, щоб він працював (підозрюючи цитату навколо деталей if
Стів Б,

4
Пам'ятайте, що в інших мовних версіях XP імена фільтрів були переведені в код, але не, але на довідковий /?екран. Так, наприклад, IMAGENAMEу польській версії є NAZWA_OBRAZU.
rsk82

3
Під Win7 я повинен був змінити його на tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL Перший NUL здається непотрібним, я не маю поняття, що таке "2", / NH не є обов'язковим.
Ян Догген

12
Список завдань завжди залишається зі статусом 0, незалежно від того, чи знаходить він відповідні завдання, і саме тому він марний сам по собі. Оскільки вам доведеться використовувати find (або findstr), щоб перевірити його вихід у будь-який спосіб, немає сенсу використовувати фільтри списку завдань. Просто робіть список завдань | знайдіть "myprog.exe"> nul: && goto foundit або somesuch. Вам може знадобитися параметр / v (багатослівний) до списку завдань.
Денис Хоу

61

Ось як я це розробив:

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

Вищенаведене відкриє Блокнот, якщо він ще не працює.

Редагувати: Зауважте, що це не знайде програм, прихованих зі списку завдань. Сюди входитимуть будь-які заплановані завдання, які виконуються як інший користувач, оскільки вони автоматично приховуються.


2
Змінення формату списку завдань на CSV або що-небудь, окрім таблиці, важливо, оскільки воно за замовчуванням макет списку завдань (таблиця) обрізає довгі імена зображень, що порушує логіку.
Скотт Уайт

4
Це рішення не працюватиме на Vista, оскільки TASKLIST виробляє деякий вихід, навіть якщо процес не знайдено. Я припускаю, що це стосується Windows 7.
dbenham,

не працює в Windows 10. search.log містить "INFO: Не виконуються завдання, які відповідають заданим критеріям." і не запущено блокнот
Сергій

46

Мені подобається рішення Chaosmaster! Але я шукав рішення, яке не запускає іншу зовнішню програму (наприклад, find.exe або findstr.exe ). Тому я додав ідею з рішення Метта Лейсі, який створює також темп-файл, який можна уникнути. Наприкінці я міг знайти досить просте рішення, тому поділяюсь цим ...

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

Це чудово працює для мене ...


Це рішення добре перевірено в Windows 8.1. Я помітив, що це враховує регістри.
oliver-clare

@LordScree Оскільки я працюю над системами un * x, чутливість регістру для мене хороша! Я навіть встановив файлову систему, щоб вона включала регістри імен файлів. ;)
TrueY

Мені добре підходить тестування в Windows 7 X64
Містер Рубікс

Це не працює, якщо у додатку є пробіл в імені, оскільки% x в кінцевому підсумку є частиною імені програми до першого пробілу.
Кріс

Можливим рішенням буде перевірити, чи не знайдено додаток замість цього, перевіривши, чи% x == INFO: але я не знаю, на яких версіях Windows це працювало б чи є краще рішення.
Кріс

21

Пропозиція npocmaka використовувати QPROCESS замість TASKLIST є чудовою, але її відповідь настільки велика і складна, що я вважаю, що я зобов'язаний опублікувати досить спрощену її версію, яка, напевно, вирішить проблему більшості непросунутих користувачів:

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

Код, викладений вище, був протестований у Windows 7 із користувачем з адміністраторськими правами.


Я просто використав цю ідею, щоб зупинити автоматичний процес стрільби двічі, і це спрацювало як принадність!
Деві С

Треба сказати, що на відміну від цієї команди, рішення списку завдань не тільки виглядають надто складними для такого простого запиту, але вони також запускають секунду або близько того і використовують тонни процесора! Це набагато краще, він також працював без дозволів адміністратора (Windows Server 2012).
Євген Марін

Це здається найпростішим і найкращим рішенням (принаймні для мене), оскільки воно працює таким, як є, коли програма має пробіли в назві. Мені цікаво, які обмеження мають це рішення і чому він не має більше голосів.
Кріс

20

У Windows можна використовувати інструмент управління Windows (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)


Зауважте, що для WMIC потрібні адміністративні пільги; якщо у вас його немає, тоді Only the administrator group members can use WMIC.EXE.слідReason:Win32 Error: Access is denied.
Jeroen Wiert Pluimers

я думаю, що це найкраще рішення, тому що wmic дає вам повний командний рядок, запускаючи та мільйон іншої інформації ...
Glavić

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

3
Це насправді чудово працює. Просто! Просто пам’ятайте, що це чутливі регістри, якщо ви не додасте /i.
Джейсон

8

Я використовую PV.exe з http://www.teamcti.com/pview/prcview.htm, встановленого у файлах програми \ PV із пакетним файлом, як це:

@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
це працює для мене у Windows 7. Другий рядок - це каталог, який містить програму, а не сама програма.
Фабіо Сіоніні

8

Відповідь 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!

У будь-якому випадку, я сподіваюся, що це допомагає. Я знаю, що іноді читання пакетного / командного рядка може бути дещо заплутаним, якщо ти такий собі новачок, як я.


6

Відповідь надається 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

Я сподіваюся, що це допомагає комусь іншому.


Це працює для Win 2008. +1 для Не виконуються завдання, які відповідають заданим критеріям.
Мангеш Пімпалкар

5

Мені подобаються WMICі TASKLISTінструменти, але вони недоступні в домашніх / базових виданнях windows.Інший спосіб - використовувати QPROCESSкоманду, доступну майже на кожній машині Windows (для тих, у кого є термінальні сервіси - я думаю, виграю лише XP без SP2, тому практично кожен віконна машина):

@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 some.exeбуде фільтрувати лише процеси для поточного користувача.

Використання WMIоб'єктів через Windows скрипт хоста exe замість WMICтакож - це також варіант. Він повинен працювати також на всіх машинах 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. Це буде працювати на всіх машинах Windows від XP і вище і не залежить від налаштувань хоста скрипту 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();

2

Я не знаю, як це зробити зі вбудованим CMD, але якщо у вас є grep, ви можете спробувати наступне:

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

2

Зауважимо лише, що якщо назва вашого завдання дійсно довге, воно в результаті не з’явиться в повному обсязі 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
)

0

Я припускаю, що тут вікна. Отже, вам потрібно буде використовувати WMI для отримання цієї інформації. Ознайомтеся з архівами хлопців-сценаріїв для численних прикладів використання WMI зі сценарію.


0

Я використовував сценарій, наданий Меттом (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

1
@Sebastian: Тут додано трохи додаткової інформації, тому я схильний залишити це як відповідь.
Білл Ящірка

0

Ви повинні перевірити ім'я батьківського процесу, див . Статтю The Code Project про рішення на базі .NET ** .

Непрограмний спосіб перевірити:

  1. Запустіть Cmd.exe
  2. Запустіть програму (наприклад, c:\windows\notepad.exe)
  3. Перевірте властивості процесу Notepad.exe у Process Explorer
  4. Перевірка батьківського процесу (це показує cmd.exe)

Те саме можна перевірити, отримавши ім’я батьківського процесу.


0

Спираючись на відповідь vtrz в і відповідь Семюеля 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.
)

Як було сказано раніше, для цього потрібні адміністративні пільги.


не працював для мене, і я використовую обліковий запис адміністратора. З'явиться вікно DOS зNode - (computer name) ERROR: Description = Invalid query
хаверим

1
Для мене працює чудово.
Марк Дункан

1
Тут чудово працює для Windows 7. Немає питань.
galacticninja

0

Мені потрібно було рішення з повторним спробою. Цей код працюватиме до тих пір, поки процес не буде знайдений, а потім знищити його. Ви можете встановити тайм-аут або будь-що, якщо хочете.

Примітки:

  • ".Exe" є обов'язковим
  • Ви можете зробити файл, який можна виконати з параметрами, версія нижче
    :: 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


-2

Зазвичай я виконую наступну команду в cmd-підказці, щоб перевірити, чи працює мій program.exe чи ні:

tasklist | grep program
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.