Como verificar se um processo está sendo executado por meio de um script em lote


260

Como posso verificar se um aplicativo está sendo executado a partir de um arquivo em lote (cmd)?

Preciso não iniciar outra instância se um programa já estiver sendo executado. Não consigo alterar o aplicativo para torná-lo apenas uma instância.

Além disso, o aplicativo pode estar sendo executado como qualquer usuário.



12
duplicado de uma pergunta feita cinco anos depois?
Matt Lacey

@ LưuVĩnhPhúc eles nem são relativamente próximos.
Cardinal - Restabelece Monica

@JackKirby, que disse que não está relacionado?
phuclv

3
@oopsdazie sim eu posso estar errado neste caso, mas a regra geral é a de manter a questão com a melhor coleção de respostas, e fechar o outro como uma duplicata , independentemente do tempo
phuclv

Respostas:


330

Outra possibilidade que surgiu, inspirada no uso do grep , é:

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

Como não é necessário salvar um arquivo extra, prefiro esse método.


7
isso funcionou muito bem para mim (Windows XP SP3). IMHO esta é a maneira mais elegante de todos aqui proposto, usando apenas as ferramentas fornecido com o Windows
hello_earth

2
Eu tive um problema de sintaxe com esta linha de comando. Eu mudei para tasklist /FI "IMAGENAME eq winword.exe" 2>NUL | find /I /N "winword.exe">NUL/ if %ERRORLEVEL%==1 goto wordnotrunningde modo a torná-lo funciona (suspeitar da citação em torno das Se as peças
Steve B

4
Lembre-se de que em versões do XP em outros idiomas os nomes dos filtros foram traduzidos em código, mas não na /?tela de ajuda . Então, por exemplo, IMAGENAMEna versão polonesa é NAZWA_OBRAZU.
rsk82

3
No Win7, tive que alterá-lo para tasklist /FI "IMAGENAME eq myapp.exe" /NH | find /I /N "myapp.exe" >NUL O primeiro NUL parece desnecessário, não tenho idéia para que serve o '2', o / NH é opcional.
Jan Doggen

12
A lista de tarefas sempre sai com o status 0, independentemente de encontrar ou não tarefas correspondentes, e é por isso que é inútil por si só. Como você precisa usar o find (ou findstr) para verificar sua saída de qualquer maneira, não faz sentido usar os filtros da lista de tarefas. Basta fazer a lista de tarefas | encontre "myprog.exe"> nul: && vá para o encontrado ou algo assim. Você pode precisar da opção / v (detalhada) na lista de tarefas.
Denis Howe

61

Aqui está como eu resolvi isso:

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

O exemplo acima abrirá o Bloco de Notas se ainda não estiver em execução.

Editar: observe que isso não encontrará aplicativos ocultos da lista de tarefas. Isso incluirá todas as tarefas agendadas em execução como um usuário diferente, pois elas serão ocultadas automaticamente.


2
Alterar o formato da lista de tarefas para CSV ou qualquer coisa, menos a tabela, é importante porque o layout padrão da tabela de tarefas (tabela) trunca nomes longos de imagens que quebram a lógica.
Scott White

4
Esta solução não funcionará no Vista porque o TASKLIST produz alguma saída, mesmo que o processo não seja encontrado. Eu presumo que o mesmo é verdadeiro para o Windows 7.
dbenham

não funciona no Windows 10. search.log contém "INFO: Nenhuma tarefa em execução corresponde aos critérios especificados". e nenhum bloco de notas é iniciado #
Sergey

46

Eu gosto da solução do Chaosmaster! Mas eu olhei para uma solução que não iniciar outro programa externo (como Find.exe ou findstr.exe ). Então, adicionei a idéia da solução de Matt Lacey, que cria um arquivo temporário também evitável. No final, pude encontrar uma solução bastante simples, então eu a compartilho ...

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

Isso está funcionando muito bem para mim ...


Esta solução funciona bem testada no Windows 8.1. Notei que faz distinção entre maiúsculas e minúsculas.
oliver-clare

@ LordScree Enquanto trabalho nos sistemas un * x, a sensibilidade é boa para mim! Até defini o sistema de arquivos para ativar os nomes de arquivo que diferenciam maiúsculas de minúsculas. ;)
TrueY

Funciona bem para mim - testado no Windows 7 x64
Sr. Rubix

Isso não funciona se o aplicativo tiver um espaço no nome, pois% x acaba fazendo parte do nome do aplicativo até o primeiro espaço.
22419 Chris

Uma solução possível seria verificar se o aplicativo não foi encontrado, verificando se% x == INFO: mas não sei em quais versões do Windows isso funcionaria ou se há uma solução melhor.
22419 Chris

21

A sugestão do npocmaka de usar o QPROCESS em vez do TASKLIST é ótima, mas sua resposta é tão grande e complexa que me sinto obrigado a postar uma versão bastante simplificada do mesmo, que eu acho que resolverá o problema da maioria dos usuários não avançados:

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

O código acima foi testado no Windows 7, com um usuário com direitos de administrador.


Eu apenas usei essa idéia para parar um processo automatizado de disparar duas vezes e funcionou como um encanto!
Davy C

Devo dizer que, diferentemente deste comando, as soluções da lista de tarefas não apenas parecem muito complicadas para uma consulta tão simples, mas também executam um segundo ou mais e usam toneladas de CPU! Isso é muito melhor, também funcionou sem permissões de administrador (Windows Server 2012).
Eugene Marin

Essa parece ser a melhor e mais simples solução (pelo menos para mim), pois funciona como está quando o aplicativo tem espaços no nome. Estou curioso para saber quais são as limitações desta solução e por que ela não tem mais votos.
22419 Chris

20

No Windows, você pode usar a WMI (Instrumentação de Gerenciamento do Windows) para garantir que nenhum aplicativo com a linha de comando especificada seja iniciado, por exemplo:

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)


Observe que o WMIC requer privilégios administrativos; se você não o tiver, então Only the administrator group members can use WMIC.EXE.seguido porReason:Win32 Error: Access is denied.
Jeroen Wiert Pluimers

eu acho que essa é a melhor solução, porque wmic dá-lhe uma linha de comando completa lançado e milion outras informações ...
Glavic

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

3
Isso realmente funciona muito bem. Simples! Lembre-se de que diferencia maiúsculas de minúsculas, a menos que você adicione /i.
25419 Jason

8

Eu uso o PV.exe em http://www.teamcti.com/pview/prcview.htm instalado em Program Files \ PV com um arquivo em lotes como este:

@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
isso funciona para mim no Windows 7. A segunda linha é o diretório que contém o programa, não o próprio programa.
Fabio Cionini 16/04

8

A resposta de TrueY parecia a solução mais elegante; no entanto, eu tinha que fazer algumas brincadeiras, porque não entendia exatamente o que estava acontecendo. Deixe-me esclarecer as coisas, espero economizar algum tempo para a próxima pessoa.

Resposta modificada de 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!

Enfim, espero que ajude. Eu sei que às vezes ler lote / linha de comando pode ser meio confuso, às vezes, se você é um novato, como eu.


6

A resposta fornecida por Matt Lacey funciona no Windows XP. No entanto, no Windows Server 2003, a linha

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

retorna

INFO: Nenhuma tarefa em execução corresponde aos critérios especificados.

que é então lido enquanto o processo está em execução.

Como não tenho muita experiência com scripts em lote, minha ação é procurar o nome do processo no search.logarquivo e bombear os resultados para outro arquivo e procurar por qualquer saída.

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

Espero que isto ajude alguém.


Isso funciona no Win 2008. +1 em Nenhuma tarefa em execução que atenda aos critérios especificados.
Mangesh Pimpalkar

5

I como o WMICe TASKLISTferramentas, mas eles não estão disponíveis na home / edições básicas de windows.Another maneira é usar QPROCESScomandos disponíveis em quase todos os máquina Windows (para os que têm serviços de terminal - Eu acho que só tem a ganhar XP sem SP2, assim practialy cada máquina de janelas):

@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

QPROCESSO comando não é tão poderoso quanto TASKLISTé limitado e mostra apenas 12 símbolos do nome do processo, mas deve ser levado em consideração se TASKLISTnão estiver disponível.

Uso mais simples em que ele usa o nome se o processo como argumento (o .exesufixo é obrigatório neste caso em que você passa o nome do executável):

@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

A diferença entre duas formas de QPROCESSuso é que QPROCESS *listará todos os processos e QPROCESS some.exefiltrará apenas os processos para o usuário atual.

Usar WMIobjetos através do Windows Script Host Exe em vez de WMICtambém é uma opção. Ele deve ser executado também em todas as máquinas Windows (excluindo aquelas em que o WSH está desativado, mas este é um caso raro) .Aqui está o arquivo bat que lista todos os processos através do WMI classes e pode ser usado no lugar do QPROCESSscript acima (é um híbrido jscript / bat e deve ser salvo como .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 );
}

E uma modificação que verificará se um processo está em execução:

@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 );
}

As duas opções podem ser usadas em máquinas que não possuem TASKLIST.

A técnica final está usando MSHTA. Isso será executado em todas as máquinas Windows a partir do XP e acima e não depende das configurações do host de scripts do Windows. a chamada de MSHTApoderia reduzir um pouco o desempenho (novamente deve ser salvo como bastão):

@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

Não sei como fazer isso com o CMD embutido, mas se você tiver grep, tente o seguinte:

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

2

Apenas mencionando, se o nome da sua tarefa for realmente longo, ele não aparecerá na íntegra no tasklistresultado; portanto, pode ser mais seguro (além da localização) verificar o oposto.

Variação desta resposta :

:: 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

Estou assumindo janelas aqui. Portanto, você precisará usar o WMI para obter essas informações. Confira os arquivos da Equipe de Scripts para ver muitos exemplos de como usar o WMI a partir de um script.


0

Eu usei o script fornecido por Matt (02-10-2008). A única coisa com a qual tive problemas foi que ele não excluiria o search.logarquivo. Espero porque precisei ir cdpara outro local para iniciar meu programa. Eu cdvoltei para onde o arquivo BAT search.logestá e , mas ele ainda não foi excluído. Então, resolvi isso excluindo o search.logarquivo primeiro e não o último.

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: Há um pouco de informação extra adicionada aqui, então estou inclinado a deixar como resposta.
Bill the Lizard

0

Você deve verificar o nome do processo pai, consulte o artigo The Code Project sobre uma solução baseada em .NET ** .

Uma maneira não programática de verificar:

  1. Iniciar o Cmd.exe
  2. Iniciar um aplicativo (por exemplo, c:\windows\notepad.exe)
  3. Verifique as propriedades do processo Notepad.exe no Process Explorer
  4. Verificar processo pai (mostra cmd.exe)

O mesmo pode ser verificado obtendo o nome do processo pai.


0

Com base na resposta de vtrz e resposta de Samuel Renkert em um outro tópico , eu vim com o seguinte script que é executado somente %EXEC_CMD%se ele não estiver em execução:

@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.
)

Como foi dito antes, isso requer privilégios administrativos.


não funcionou para mim e estou usando uma conta de administrador. Uma caixa do DOS aparece comNode - (computer name) ERROR: Description = Invalid query
khaverim

1
Funciona muito bem para mim.
Mark Duncan

1
Funciona muito bem para o Windows 7 aqui. Sem problemas.
galacticninja

0

Eu precisava de uma solução com uma nova tentativa. Esse código será executado até que o processo seja encontrado e depois o mate. Você pode definir um tempo limite ou qualquer coisa, se quiser.

Notas:

  • O ".exe" é obrigatório
  • Você pode tornar um arquivo executável com parâmetros, versão abaixo
    :: 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
        )

Correr com .\taskkill.bat ProgramToKill.exe


-2

Normalmente, executo o seguinte comando no prompt do cmd para verificar se o meu program.exe está executando ou não:

tasklist | grep program
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.