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

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"

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.


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


6

Usando o PowerShell + WMI:

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId

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 .

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%

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


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%

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

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


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

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

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.