Как проверить, запущен ли процесс через пакетный скрипт
Как я могу проверить, запущено ли приложение из пакетного (хорошо cmd) файла?
Мне не нужно запускать другой экземпляр, если программа уже запущена. (Я не могу изменить приложение, чтобы сделать его только один экземпляр.)
Также приложение может работать как любой пользователь.
20 ответов
Еще одна возможность, которую я придумал, вдохновленная использованием grep:
tasklist /FI "IMAGENAME eq myapp.exe" 2>NUL | find /I /N "myapp.exe">NUL
if "%ERRORLEVEL%"=="0" echo Program is running
Для этого не нужно сохранять дополнительный файл, поэтому я предпочитаю этот метод.
Вот как я это сделал:
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
Выше откроется Блокнот, если он еще не запущен.
Изменить: Обратите внимание, что это не найдет приложения, скрытые от списка задач. Это будет включать любые запланированные задачи, выполняемые от имени другого пользователя, поскольку они автоматически скрываются.
Мне нравится решение 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
Это хорошо работает для меня...
Предложение npocmaka использовать QPROCESS вместо TASKLIST велико, но его ответ настолько велик и сложен, что я чувствую себя обязанным опубликовать довольно упрощенную версию, которая, я думаю, решит проблему большинства неопытных пользователей:
QPROCESS "myprocess.exe">NUL
IF %ERRORLEVEL% EQU 0 ECHO "Process running"
Приведенный выше код был протестирован в Windows 7 с пользователем с правами администратора.
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
В 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)
Ответ 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!
Во всяком случае, я надеюсь, что это помогает. Я знаю, что иногда чтение пакетной / командной строки может сбивать с толку, если вы новичок, как я.
Я использую 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
Мне нравится WMIC
а также TASKLIST
инструменты, но они не доступны в домашних / основных выпусках Windows. Другой способ заключается в использовании QPROCESS
Команда доступна почти на каждой машине с Windows (для тех, у кого есть службы терминалов - я думаю, что только Win 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 сценарий хоста 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();
Ответ, предоставленный Мэттом Лэйси, работает для 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
Я надеюсь, что это помогает кому-то еще.
Я не знаю, как это сделать со встроенным CMD, но если у вас есть grep, вы можете попробовать следующее:
tasklist /FI "IMAGENAME eq myApp.exe" | grep myApp.exe
if ERRORLEVEL 1 echo "myApp is not running"
Просто упомянув, что если имя вашей задачи действительно длинное, то оно не будет отображаться полностью в 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-файлов с одинаковым именем, и вы хотите проверить только один из них (например, вам нужен C: \ MyProject \ bin \ release \ MyApplication.exe, но не C: \ MyProject \ bin \ debug \ MyApplication.exe), вы можете использовать следующее:
@echo off
set "workdir=C:\MyProject\bin\release"
set "workdir=%workdir:\=\\%"
setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
wmic process where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"' get CommandLine^,ProcessId /format:value
`) do (
for /f "tokens=* delims=" %%G in ("%%a") do (
if "%%G" neq "" (
rem echo %%G
set "%%G"
rem echo !ProcessId!
goto :TheApplicationIsRunning
)
)
)
echo The application is not running
exit /B
:TheApplicationIsRunning
echo The application is running
exit /B
Мне нужно было решение с повторной попыткой. Этот код будет работать до тех пор, пока процесс не будет найден, а затем уничтожит его. Вы можете установить тайм-аут или что угодно, если хотите.
Заметки:
- ".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
Я использовал скрипт, предоставленный Мэттом (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
Использование списка задач со стандартным выводом результатов по умолчанию приводит к обрезке имени изображения, поэтому при применении find/I оно не находит его.
Поэтому, чтобы список задач не обрезал длинные имена в столбце имени изображения, измените вывод на список, а затем найдите там полное имя приложения.
См. пример ниже:
@echo off
set "fullProcessName=myveryveryveryveryverylongappnameeeee.exe"
:: Check if the process is running and capture the output
:: Note we use /FO LIST
tasklist /FI "IMAGENAME eq %fullProcessName%" /FO LIST 2>NUL | find /I "%fullProcessName%" >NUL
if %errorlevel% equ 0 (
echo The process %fullProcessName% is running.
) else (
echo The process %fullProcessName% is not running.
)
Основываясь на ответе 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.
)
Как было сказано ранее, это требует административных привилегий.
Я предполагаю, что окна здесь. Итак, вам нужно использовать WMI, чтобы получить эту информацию. В архиве The Scripting Guy есть много примеров того, как использовать WMI из скрипта.
Я обычно выполняю следующую команду в командной строке cmd, чтобы проверить, запущен ли мой program.exe:
tasklist | grep program
Вам следует проверить имя родительского процесса, см . Статью " Проект кода" о решении на основе.NET **.
Непрограммный способ проверки:
- Запустите Cmd.exe
- Запустите приложение (например,
c:\windows\notepad.exe
) - Проверьте свойства процесса Notepad.exe в Process Explorer
- Проверьте родительский процесс (показывает cmd.exe)
То же самое можно проверить, получив имя родительского процесса.