Как проверить, запущен ли процесс через пакетный скрипт

260

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

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

Также приложение может работать как любой пользователь.

Мэтт Лэйси
источник
12
дубликат вопроса, заданного пять лет спустя?
Мэтт Лэйси
@ LưuVĩnhPhúc они даже не относительно близко.
Кардинал - Восстановить Монику
@JackKirby, кто сказал, что это не связано?
phuclv
3
@oopsdazie, да, я могу ошибаться в этом случае, но общее правило состоит в том, чтобы сохранить вопрос с лучшим набором ответов и закрыть другой как дубликат , независимо от времени
phuclv

Ответы:

330

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

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

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

pkamb
источник
7
это работало для меня хорошо (Windows XP SP3). ИМХО, это самый элегантный способ из всех предложенных здесь, с использованием только инструментов, поставляемых с Windows
hello_earth
2
У меня была проблема с синтаксисом этой командной строки. Я изменил его на tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunningдля того, чтобы заставить его работать (подозревая цитату вокруг частей if
Стив B
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

Это хорошо работает для меня ...

TrueY
источник
Это решение хорошо работает - проверено в Windows 8.1. Я заметил, что он чувствителен к регистру.
Оливер-Клэр
@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 с пользователем с правами администратора.

aldemarcalazans
источник
Я просто использовал эту идею, чтобы дважды остановить автоматизированный процесс, и это сработало как шарм!
Дэви К,
Должен сказать, что в отличие от этой команды, решения для списка задач не только выглядят слишком сложными для такого простого запроса, но и запускают примерно секунду и используют тонны процессора! Это намного лучше, также работает без прав администратора (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)

vtrz
источник
Обратите внимание, что WMIC требует административных привилегий; если у вас его нет, а Only the administrator group members can use WMIC.EXE.затемReason:Win32 Error: Access is denied.
Йерун Вирт Плюймерс
я думаю, что это лучшее решение, потому что wmic дает вам полную запущенную командную строку и предоставляет другую информацию ...
Glavić
14
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
Риккардо Ла Марка
источник
3
Это на самом деле прекрасно работает. Просто! Только знайте, что это чувствительно к регистру, если вы не добавите /i.
Джейсон
8

Я использую 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

источник
1
это работает для меня в Windows 7. 2-я строка - это каталог, в котором находится программа, а не сама программа.
Фабио Чионини
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!

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

kayleeFrye_onDeck
источник
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

Я надеюсь, что это помогает кому-то еще.

benmod
источник
Это работает для Win 2008. +1 для Нет запущенных задач, которые соответствуют указанным критериям.
Мангеш Пимпалкар
5

Я вроде WMICи TASKLISTинструментов , но они не доступны в доме / основные изданиями windows.Another способа является использование QPROCESSкоманд доступны на почти каждое окно машины (для тех , которые имеют терминальные услуги - Я думаю , что только выиграть XP без SP2, так practialy каждого окна машины):

@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объектов через exe- WMICфайл сценария Windows вместо этого также является опцией. Его следует запускать также на каждой машине 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();
npocmaka
источник
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
)
drzaus
источник
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
Nin
источник
1
@Sebastian: здесь добавлено немного дополнительной информации, поэтому я склонен оставить ее в качестве ответа.
Билл Ящерица
0

Вам следует проверить имя родительского процесса, см . Статью « Проект кода» о решении на основе .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.
)

Как было сказано ранее, это требует административных привилегий.

Calimo
источник
не работал для меня, и я использую учетную запись администратора. Окно DOS появляется сNode - (computer name) ERROR: Description = Invalid query
khaverim
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
Раджив Джаясвал
источник