Как проверить, запущен ли процесс с помощью пакетного скрипта

Как я могу проверить, запущено ли приложение из пакетного (ну, cmd) файла?

Мне не нужно запускать другой экземпляр, если программа уже запущена. (Я не могу изменить приложение, чтобы сделать его только одним экземпляром.)

Также приложение может быть запущено от имени любого пользователя.

дубликат вопроса, заданного пятью годами позже?

Matt Lacey 07.12.2016 00:34

@ LưuVĩnhPhúc они даже не относительно близки.

Cardinal System 01.04.2017 21:00

@JackKirby, кто сказал, что это не связано?

phuclv 02.04.2017 04:32

@ LưuVĩnhPhúc Я сделал. Он спрашивает, как проверить, запущена ли программа из пакетного сценария, в то время как в другом вопросе спрашивается, как получить список задач.

Cardinal System 02.04.2017 05:41

@JackKirby, тогда тебе стоит прочитать еще раз. Где в другом вопросе, который ОП сказал, что хочет получить список задач? Он хочет проверить, запущен ли процесс

phuclv 02.04.2017 10:53

@ Lưu Vĩnh Phúc Он спросил первым.

oopsdazie 18.05.2017 16:58

@oopsdazie да, я могу ошибаться в этом случае, но общее правило - оставить вопрос с лучшим набором ответов и закрыть другой как дубликат, независимо от времени

phuclv 18.05.2017 17:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
273
8
632 260
18

Ответы 18

Вы должны проверить имя родительского процесса, см. Статью Кодовый проект о Решение на основе .NET **.

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

  1. Запустить Cmd.exe
  2. Запустить приложение (например, c:\windows\notepad.exe)
  3. Проверьте свойства процесса Notepad.exe в Процесс
  4. Проверьте родительский процесс (это показывает cmd.exe)

То же самое можно проверить, получив имя родительского процесса.

Я предполагаю, что окна здесь. Итак, вам нужно использовать WMI для получения этой информации. Посмотрите архивы от The Scripting Guy, где вы найдете множество примеров того, как использовать WMI из скрипта.

Вот как я это решил:

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

Вышеупомянутый откроет Блокнот, если он еще не запущен.

Обновлено: обратите внимание, что при этом не будут обнаружены приложения, скрытые в списке задач. Это будет включать любые запланированные задачи, запущенные от имени другого пользователя, поскольку они автоматически скрываются.

Изменение формата списка задач на CSV или что-то еще, кроме таблицы, важно, потому что его макет списка задач по умолчанию (таблица) обрезает длинные имена изображений, что нарушает логику.

Scott White 22.06.2011 18:56

Это решение не будет работать в Vista, потому что TASKLIST производит некоторый вывод, даже если процесс не найден. Я полагаю, то же самое верно и для Windows 7.

dbenham 28.01.2012 20:39

не работает в Windows 10. search.log содержит «ИНФОРМАЦИЯ: не запущено ни одной задачи, соответствующей указанным критериям». и блокнот не запускается

Sergey 30.05.2018 11:21

Я не знаю, как это сделать со встроенным CMD, но если у вас есть grep, вы можете попробовать следующее:

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

Я использую PV.exe из http://www.teamcti.com/pview/prcview.htm, установленного в Program Files \ 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

это работает для меня в Windows 7. 2-я строка - это каталог, содержащий программу, а не саму программу.

Fabio Cionini 17.04.2012 01:23

Другая возможность, которую я придумал, вдохновленная использованием grep, такова:

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

Не нужно сохранять дополнительный файл, поэтому я предпочитаю этот метод.

это сработало для меня хорошо (Windows XP SP3). ИМХО, это самый элегантный способ из всех предложенных здесь, с использованием только инструментов, поставляемых с окнами.

hello_earth 08.07.2010 19:30

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

Steve B 19.10.2011 11:17

У меня работает на Windows Server 2003! :)

Enrico 05.07.2012 17:36

Большое спасибо, человек гений, не могли бы вы предоставить код, если он запущен, закройте приложение.

Mowgli 16.09.2012 01:47

Помните, что в других языковых версиях XP имена фильтров были переведены в коде, но не в справочном экране /?. Так, например, IMAGENAME в польской версии - это NAZWA_OBRAZU.

rsk82 30.11.2012 19:44

Под Win7 мне пришлось изменить его на tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL. Первый NUL кажется ненужным, я понятия не имею, для чего нужна цифра «2», / NH не является обязательным.

Jan Doggen 08.11.2013 13:17

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

Denis Howe 07.06.2014 16:32

На самом деле вызова внешнего find.exe можно избежать. Смотри рядом мою уменьшенную версию ...

TrueY 21.08.2014 14:21

@ rsk82 В Win7 это снова кажется чисто английским (?) - по крайней мере, в польской Windows IMAGENAME работает, а NAZWA_OBRAZU - нет ...

akavel 08.01.2015 12:14

как заявил Ян Догген, у меня не работает как есть. Ответ ниже Мэтта Лейси работал у меня без изменений.

Fractal 18.02.2016 20:49

Что случилось с @ChaosMaster?

mtyson 30.09.2016 01:55

Понятия не имею, почему, но мне пришлось использовать if errorlevel 0 вместо if "%ERRORLEVEL%"= = "0". Как ни странно, использование %ERRORLEVEL% работает должным образом, если я запускаю команды непосредственно в cmd.exe, но если я попытаюсь сделать то же самое в сценарии .bat, %ERRORLEVEL% всегда будет равен нулю. FWIW, сценарий использует setlocal enableextensions; не уверен, связано ли это с наблюдаемым поведением. Это в Windows 7 x64.

Ben Johnson 10.07.2017 18:43
следует упомянуть that if your taskname is too long the whole name won't appear in the results, so check for the opposite message instead
drzaus 11.05.2018 22:40

Много лишнего. tasklist | find /i "notepad.exe" > nul более чем достаточно.

Jason 23.03.2019 01:57

Просто хотел отметить, что у меня установлен gitbash, и я вижу противоречивые результаты. В конце концов отследил его до VSCode, запустив команду узла, заменив system32 find на gitbash find. Решено после того, как я использовал C:\Windows\System32\find.exe, я знаю, что это немного многословно, но может быть самым безопасным в долгосрочной перспективе.

WORMSS 17.02.2020 03:14

@DenisHowe передача всего списка задач в Find заметно медленнее, чем при использовании фильтра TaskList.

Richard Payne 12.03.2020 18:34

@RichardPayne Когда именно разница в скорости стоит двойной сложности фильтрации?

Denis Howe 31.03.2020 13:29

@WORMSS Команда findstr в Windows с меньшей вероятностью будет конфликтовать с добавленными командами Unix.

Denis Howe 31.03.2020 13:32

Я использовал сценарий предоставлен Мэттом (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

@Sebastian: Здесь добавлена ​​небольшая дополнительная информация, поэтому я склонен оставить ее в качестве ответа.

Bill the Lizard 16.10.2010 07:55

В 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 14.02.2012 13:48

Я думаю, что это лучшее решение, потому что wmic дает вам полную запущенную командную строку и миллион другой информации ...

Glavić 23.05.2012 19:42

ответ предоставлен Мэттом Лейси работает в Windows XP. Однако в Windows Server 2003 строка

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

возвращается

INFO: No tasks are running which match the specified criteria.

который затем читается по мере выполнения процесса.

У меня нет опыта создания пакетных сценариев, поэтому я предпочитаю искать имя процесса в файле 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 за Нет запущенных задач, соответствующих указанным критериям.

Mangesh Pimpalkar 10.12.2014 04:04

Основываясь на ответ vtrz и Ответ Самуэля Ренкерта по другой теме, я придумал следующий сценарий, который запускает %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

khaverim 12.05.2014 23:14

У меня отлично работает.

Mark Duncan 06.03.2015 15:57

Здесь отлично работает для Windows 7. Без вопросов.

galacticninja 07.01.2020 09:33

Мне нравятся инструменты WMIC и TASKLIST, но они недоступны в домашних / базовых версиях Windows. Другой способ - использовать команду QPROCESS, доступную почти на каждом компьютере с Windows (для тех, у которых есть терминальные службы - я думаю, что выиграть XP без SP2 так что практически каждая машина 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 не так мощна, как 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 script host 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();

Мне нравится решение 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. Я заметил, что это чувствительно к регистру.

m-smith 02.12.2014 14:18

@LordScree Поскольку я работаю над системами un * x, мне подходит чувствительность к регистру! Я даже настроил файловую систему, чтобы имена файлов были чувствительны к регистру. ;)

TrueY 02.12.2014 15:42

У меня хорошо работает - протестировано в Windows 7 X64

Mr Rubix 15.03.2016 21:21

Это не работает, если в имени приложения есть пробел, поскольку% x оказывается частью имени приложения до первого пробела.

Chris 14.06.2019 17:21

Возможным решением было бы проверить, не найдено ли приложение вместо этого, проверив,% x == INFO: но я не знаю, с какими версиями Windows это будет работать, и есть ли лучшее решение.

Chris 14.06.2019 17:38

@ Крис: Это тоже хорошее решение. Если %x == INFO, это означает, что программа не найдена и Windows сообщает INFO: No tasks are running which match the specified criteria.. Но ИМХО это немного менее разговорчиво. Конечно, вы можете использовать оба решения!

TrueY 17.06.2019 15:21

Ответ 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!

В любом случае, я надеюсь, что это поможет. Я знаю, что иногда чтение пакета / командной строки может сбивать с толку, если вы такой новичок, как я.

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

Это действительно отлично работает. Простой! Просто помните, что это чувствительно к регистру, если вы не добавите /i.

Jason 25.03.2019 19:21

Обычно я выполняю следующую команду в командной строке, чтобы проверить, запущен ли мой program.exe или нет:

tasklist | grep program

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

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

Приведенный выше код был протестирован в Windows 7 с правами администратора.

Я просто использовал эту идею, чтобы дважды остановить автоматический процесс, и это сработало как шарм!

Davy C 14.03.2018 13:23

Я должен сказать, что, в отличие от этой команды, решения для списка задач не только выглядят слишком сложными для такого простого запроса, но они также работают примерно секунду и используют массу ЦП! Это намного лучше, также работает без прав администратора (Windows Server 2012).

Eugene Marin 21.06.2018 18:36

Это кажется самым простым и лучшим решением (по крайней мере, для меня), поскольку оно работает как есть, когда в имени приложения есть пробелы. Мне любопытно, каковы ограничения этого решения и почему у него нет большего количества голосов.

Chris 14.06.2019 17:41

простой и практичный

focus zheng 28.06.2020 13:36

Просто отметим, что если имя вашей задачи действительно длинное, то оно не будет полностью отображаться в результате 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
)

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

Заметки:

  • ".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

Другие вопросы по теме