como obter o próprio processo pid no prompt de comando no Windows

26

Estou tentando encontrar uma maneira de obter meu próprio PID em um prompt de comando (para uso posterior em scripts bat) até agora, a única maneira útil que encontrei foi usar o getpids.exe a partir daqui: http://www.scheibli.com/ projects / getpids / index.html, mas estou procurando por um comando "incorporado" no Windows

edit: estou procurando uma maneira "à prova de balas" - sem suposições sobre o meu processo ser o único cmd.exe ou algo assim

radai
fonte

Respostas:

36

Como nenhuma das outras soluções é à prova de balas e integrada, imaginei oferecer a seguinte solução, mas observe que você precisará analisar / salvar os resultados de alguma forma:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
Tony Roth
fonte
isso é realmente legal. im certeza que a hora atual + algum número gerado aleatoriamente pode ser definida como o título para chegar perto à prova de balas
radai
3
Não use% random% +% time% se você tiver um agendador que chame seu script em lote duas vezes ao mesmo tempo. Eu tive o problema de que o mesmo script foi chamado com parâmetros diferentes ao mesmo tempo. A semente aleatória era a mesma e tive colisões ao criar um diretório temporário. Não havia como evitar o erro ao criar o diretório temporário. Para encurtar a história, se você puder supor que seu script não seja acionado duas vezes ao mesmo tempo, esse truque deve funcionar.
Peter Schuetze
Pode ser (não testado profundamente) que obter um registro de data e hora mais preciso (incluindo microseconds, em vez de 1/100 segundos como em% time%), seria mais confiável neste caso: wmic os get LocalDateTime(YearMonthDayHourMinuteSecond.Microsecond + Timezone). A menos que o planejador seja capaz de executar duas coisas exatamente no mesmo microssegundo ...
Gauthier Boaglio
Isso não vai funcionar se o processo está sendo executado em outra sessão no computador como o título é mostrado como N / A
FrinkTheBrave
Isso fornece o PID do processo pai.
ACCESS_GRANTED
7

Eu acredito que o seguinte é à prova de balas, desde que o usuário tenha acesso aos pontos WMIC e TEMP para um caminho válido em que o usuário tenha privilégios de gravação. Este é o resultado final de alguns trabalhos colaborativos em http://www.dostips.com/forum/viewtopic.php?f=3&t=6133 .

@echo off

:getPID  [RtnVar]
::
:: Store the Process ID (PID) of the currently running script in environment variable RtnVar.
:: If called without any argument, then simply write the PID to stdout.
::
setlocal disableDelayedExpansion
:getLock
set "lock=%temp%\%~nx0.%time::=.%.lock"
set "uid=%lock:\=:b%"
set "uid=%uid:,=:c%"
set "uid=%uid:'=:q%"
set "uid=%uid:_=:u%"
setlocal enableDelayedExpansion
set "uid=!uid:%%=:p!"
endlocal & set "uid=%uid%"
2>nul ( 9>"%lock%" (
  for /f "skip=1" %%A in (
    'wmic process where "name='cmd.exe' and CommandLine like '%%<%uid%>%%'" get ParentProcessID'
  ) do for %%B in (%%A) do set "PID=%%B"
  (call )
))||goto :getLock
del "%lock%" 2>nul
endlocal & if "%~1" equ "" (echo(%PID%) else set "%~1=%PID%"
exit /b

O script estabelece um bloqueio exclusivo em um arquivo temporário que incorpora a hora atual no nome. Só pode haver uma colisão se dois processos em lote nomeados tentarem obter o PID dentro do mesmo intervalo de 0,01 segundo, caso em que apenas um será bem-sucedido.

Qualquer processo que falhar será repetidamente repetido e tentará novamente com um novo caminho de arquivo de bloqueio até que seja bem-sucedido.

O caminho completo para o arquivo de bloqueio é transformado em um ID exclusivo que pode ser usado na consulta WMIC. O WMIC é executado dentro de um comando FOR / F, o que significa que está sendo executado em um processo filho cmd.exe. É por isso que o ParentProcessID do processo cmd.exe é recuperado.

dbenham
fonte
7

Expandindo a resposta de Tony Roth:

title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do echo %f

O uso do filtro WINDOWTITLE evita o pipe, para que você possa colocá-lo em um loop for e atribuí-lo a uma variável com SET, se desejar:

title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do set ourPID=%f

Removendo o /vtorna mais rápido, e /NHse livra da linha de cabeçalho. Você precisa do curinga depois "uniqueTitle"porque o título da janela realmente contém o comando atual (portanto, ele continuaria se você tentasse correspondê-lo completamente).

David
fonte
6

Usando o PowerShell + WMI:

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
Nicolas Melay
fonte
Agradável; se você possui o PowerShell Core , fica ainda mais fácil (embora nenhum dos comandos seja rápido ):pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
mklement
5
  1. No Gerenciador de tarefas do Windows, você precisará ir para Exibir -> Selecionar colunas ... e selecionar PID.
  2. "tasklist / v" para obter informações detalhadas da tarefa no prompt de comando.
  3. Process Explorer do live.sysinternals.com .
Vivek Kumbhar
fonte
2
@Vivek, a partir de um prompt de comando ... e você está enganando respostas
WooYek
Eu apenas dei todas as opções possíveis ... e sem duplicação. Eu também poderia ter mencionado o PowerShell, mas me contive, pois isso não vem por padrão no XP e 2003. Se isso for para o sistema operacional Vista, o PowerShell teria sido a minha preferência. .
Vivek Kumbhar
5

se você sabe que há apenas um cmd.exe em execução, é possível obter o PID desta maneira:

for /F "tokens=1,2" %%i in ('tasklist /FI "IMAGENAME eq cmd.exe" /fo table /nh') do set pid=%%j

echo %pid%
zumalifeguard
fonte
Isso soa como uma suposição improvável, seu código pode ser instável
Raúl Salinas-Monteagudo
Raul, eu entendo o que você está dizendo. É inseguro em muitos casos, mas é seguro em alguns - como um sistema de quiosque ou uma VM em que você está no controle total de quais processos estão iniciando e não
zumalifeguard
4

Isso deve fazer o truque:

tasklist / v

WooYek
fonte
3

Se você deseja encontrar o PID do nome da imagem "notepad.exe", o seguinte código funcionará para você:

for /F "tokens=1,2" %i in ('tasklist') do (
 if "%i" equ "notepad.exe" (set x=%j)
)
echo %x%
Minchurl
fonte
2

Se você possui o kit de recursos do Windows 2003, passe-o pelo qgrep para obter a linha desejada. Você pode extrair o pid daqui (isso pressupõe que você tenha apenas um cmd em execução por vez),

tasklist /v | qgrep cmd

cmd.exe 2040 RDP-Tcp#447 0 1,804 K Running MACHINE\Administrator  0:00:00 Command Prompt
Guppy
fonte
1

Dê uma olhada neste pequeno truque de lote . Ele define o título de cmd como um valor especial e, em seguida, usa a lista de tarefas para encontrá-lo. Inventivo

\\ Greg

uSlackr
fonte
0

Esta é uma maneira curta de obter o ID do processo para CMD aberto

tasklist /v /fi "imagename EQ cmd.exe" /FO LIST | FIND "PID:"
hollopost
fonte
0

Esta resposta fornecerá APENAS o ID do processo e nenhum dos itens extras incluídos na resposta principal.

title mycmd
tasklist /v /fo csv | findstr /i "mycmd" > PIDinfo.txt

set /p PIDinfo=<PIDinfo.txt
set PID1=%PIDinfo:~11,5%
set PID2=%PIDinfo:~11,4%

if %PID2% gtr 8100 (
    set PID=%PID2%
) else (
    set PID=%PID1%
)

echo %PID%

Explicação:

-não haverá um PID para cmd.exe maior que 18100, portanto, verifique se o PID2 é maior que 8100 para saber se é um número de 4 ou 5 dígitos

caso 1: um PID de 5 dígitos como 17504 possui um PID1 val 17504 e um PID2 val 1750, portanto, usamos PID1

caso 2: um PID de 4 dígitos, como 8205, tem um valor PID1 de 8205 "e um valor PID2 de 8205, então usamos o PID2

caso 3: um PID de 4 dígitos, como 4352, tem um valor PID1 de 4352 "e um valor PID2 de 4352, por isso usamos o PID2

Collin Fox
fonte