cómo obtener un proceso propio pid desde el símbolo del sistema en windows

26

Estoy tratando de encontrar una manera de obtener mi propio PID desde un símbolo del sistema (para su uso posterior en scripts de bat) hasta ahora, la única forma útil que encontré fue usar getpids.exe desde aquí: http://www.scheibli.com/ projects / getpids / index.html pero estoy buscando un comando que esté "integrado" en Windows

editar: estoy buscando una forma "a prueba de balas" - no hay suposiciones acerca de que mi proceso sea el único cmd.exe o algo

radai
fuente

Respuestas:

36

Como ninguna de las otras soluciones son a prueba de balas y están integradas, pensé que ofrecería la siguiente solución, pero tenga en cuenta que tendrá que analizar / guardar los resultados de alguna manera:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
Tony Roth
fuente
Eso es realmente genial. Estoy bastante seguro de que la hora actual + algún número generado aleatoriamente se puede establecer como el título para acercarse a prueba de balas
radai
3
No use% random% +% time% si tiene un planificador que llame a su secuencia de comandos por lotes dos veces al mismo tiempo. Tuve el problema de que se llamaba al mismo script con diferentes parámetros al mismo tiempo. La semilla para el azar fue la misma y me encontré con colisiones al crear un directorio temporal. No había forma de evitar el error al crear el directorio temporal. En pocas palabras, si puede suponer que su guión no se dispara dos veces al mismo tiempo, este truco debería funcionar.
Peter Schuetze
Podría ser (no probado en profundidad) que obtener una marca de tiempo más precisa (incluyendo microseconds, en lugar de 1/100 segundos, como en% time%), sería más confiable en este caso: wmic os get LocalDateTime(YearMonthDayHourMinuteSecond.Microsecond + Timezone). A menos que el planificador pueda ejecutar dos cosas exactamente en el mismo microsegundo ...
Gauthier Boaglio
Esto no funcionará si el proceso se ejecuta en otra sesión en la computadora ya que el título se muestra como N / A
FrinkTheBrave
Esto proporciona el PID del proceso padre.
access_granted
7

Creo que lo siguiente es a prueba de balas, siempre que el usuario tenga acceso a puntos WMIC y TEMP a una ruta válida donde el usuario tenga privilegios de escritura. Este es el resultado final de un trabajo de colaboración en 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

El script establece un bloqueo exclusivo en un archivo temporal que incorpora la hora actual en el nombre. Solo puede haber una colisión si dos procesos por lotes con nombre intentan obtener el PID dentro del mismo intervalo de tiempo de 0.01 segundos, en cuyo caso solo uno tendrá éxito.

Cualquier proceso que falle repetidamente repetirá e intentará nuevamente con una nueva ruta de archivo de bloqueo hasta que tenga éxito.

La ruta completa al archivo de bloqueo se transforma en una ID única que se puede utilizar en la consulta WMIC. WMIC se ejecuta dentro de un comando FOR / F, lo que significa que se ejecuta en un proceso hijo cmd.exe. Es por eso que se recupera el ParentProcessID del proceso cmd.exe.

dbenham
fuente
7

Ampliando la respuesta de Tony Roth:

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

El uso del filtro WINDOWTITLE evita la tubería para que pueda colocarlo en un bucle for y asignarlo a una variable con SET si lo desea:

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

Eliminarlo lo /vhace más rápido y /NHelimina la línea de encabezado. Necesita el comodín después "uniqueTitle"porque el título de la ventana realmente contiene el comando actual (por lo tanto, seguiría y seguiría si intentara coincidir completamente).

David
fuente
6

Usando PowerShell + WMI:

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
Nicolas Melay
fuente
Agradable; si tiene PowerShell Core , se pone aún más fácil (aunque ninguno de comandos será rápida ):pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
mklement
5
  1. Administrador de tareas de Windows, deberá ir a Ver -> Seleccionar columnas ... y seleccionar PID.
  2. "tasklist / v" para obtener información detallada de la tarea en el símbolo del sistema.
  3. Explorador de procesos de live.sysinternals.com .
Vivek Kumbhar
fuente
2
@Vivek, desde un símbolo del sistema ... y estás
duplicando
Acabo de dar todas las opciones posibles ... y no duplicar ... También podría haber mencionado PowerShell pero me contuve ya que eso no viene por defecto en XP y 2003. Si esto es para el sistema operativo Vista en adelante, sí, PowerShell hubiera sido mi preferencia .
Vivek Kumbhar
5

si sabe que solo hay un cmd.exe ejecutándose, puede obtener el PID de esta manera:

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

echo %pid%
zumalifeguard
fuente
Eso suena como una suposición improbable, su código podría ser falso
Raúl Salinas-Monteagudo
Raúl, entiendo lo que estás diciendo. Es inseguro en muchos casos, pero es seguro en algunos, como un sistema de quiosco o una máquina virtual donde usted tiene el control total de los procesos que se inician y no
zumalifeguard
4

Esto debería funcionar:

lista de tareas / v

WooYek
fuente
3

Si desea encontrar el PID del nombre de la imagen "notepad.exe", el siguiente código funcionará para usted:

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

Si tiene el kit de recursos de Windows 2003, introdúzcalo en qgrep para obtener la línea que desea. Luego puede extraer el pid desde aquí (esto supone que solo tiene un cmd ejecutándose a la vez),

tasklist /v | qgrep cmd

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

Echa un vistazo a este pequeño truco de lotes . Establece el título de cmd en un valor especial y luego usa la lista de tareas para encontrarlo. Inventivo

\\ Greg

uSlackr
fuente
0

ESTA ES LA FORMA CORTA DE OBTENER ID DE PROCESO PARA ABRIR CMD

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

Esta respuesta le dará SOLAMENTE la identificación del proceso, y ninguna de las cosas adicionales que incluye la respuesta 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%

Explicación:

-no habrá un PID para cmd.exe que sea mayor que 18100, así que verifique si PID2 es mayor que 8100 para saber si es un número de 4 o 5 dígitos

caso 1: un PID de 5 dígitos como 17504 tiene un PID1 val 17504 y un PID2 val de 1750, por lo que usamos PID1

caso 2: un PID de 4 dígitos como 8205 tiene un valor PID1 de 8205 "y un valor PID2 de 8205, por lo que utilizamos PID2

caso 3: un PID de 4 dígitos como 4352 tiene un valor PID1 de 4352 "y un valor PID2 de 4352, por lo que usamos PID2

Collin Fox
fuente