it-swarm.com.ru

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

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

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

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

238
Matt Lacey

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

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

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

298
Chaosmaster

Вот как я это сделал:

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

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

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

59
Matt Lacey

Мне нравится решение 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

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

37
TrueY

В 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)

21
vtrz

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

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

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

18
aldemarcalazans

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

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

8
kayleeFrye_onDeck

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

ответ предоставлен Мэттом Лэйси работает для 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

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

6
benmod
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
6
Riccardo La Marca

Мне нравятся инструменты 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 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();
5
npocmaka

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

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

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

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

0
NotMe

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

Вы должны проверить имя родительского процесса, см. The Code Project статью о решение на основе .NET ** .

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

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

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

0
prakash