So erhalten Sie eine eigene Prozess-PID über die Eingabeaufforderung in Windows

26

Ich versuche, einen Weg zu finden, um meine eigene PID von einer Eingabeaufforderung (für die spätere Verwendung in Fledermaus-Skripten) zu erhalten. Bisher war der einzige nützliche Weg, den ich fand, getpids.exe von hier aus zu verwenden: http://www.scheibli.com/ projects / getpids / index.html aber ich suche nach einem Befehl, der in Windows "eingebaut" ist

edit: ich bin auf der Suche nach einem "kugelsicheren" Weg - keine Vermutungen, dass mein Prozess die einzige cmd.exe ist oder so

radai
quelle

Antworten:

36

Da keine der anderen Lösungen kugelsicher und integriert ist, würde ich die folgende Lösung anbieten, aber beachten Sie, dass Sie die Ergebnisse irgendwie analysieren / speichern müssen:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
Tony Roth
quelle
Das ist wirklich ordentlich.
Ich bin
3
Verwenden Sie% random% +% time% nicht, wenn ein Scheduler Ihr Batch-Skript zweimal gleichzeitig aufruft. Ich hatte das Problem, dass das gleiche Skript gleichzeitig mit verschiedenen Parametern aufgerufen wurde. Der Ausgangswert für den Zufall war derselbe und ich bin beim Erstellen eines temporären Verzeichnisses auf Kollisionen gestoßen. Es gab damals keine Möglichkeit, den Fehler beim Erstellen des temporären Verzeichnisses zu behandeln. Um es kurz zu machen: Wenn Sie davon ausgehen können, dass Ihr Skript nicht zweimal gleichzeitig ausgelöst wird, sollte dieser Trick funktionieren.
Peter Schuetze
Möglicherweise ist es microsecondsin diesem Fall zuverlässiger , einen genaueren Zeitstempel (einschließlich 1/100 Sekunden wie in% time%) zu erhalten (nicht eingehend getestet) : wmic os get LocalDateTime(YearMonthDayHourMinuteSecond.Microsecond + Timezone). Es sei denn, der Scheduler kann zwei Dinge in genau derselben Mikrosekunde
ausführen
Dies funktioniert nicht, wenn der Prozess in einer anderen Sitzung auf dem Computer ausgeführt wird, da der Titel als N / A
FrinkTheBrave
Dies gibt die PID des übergeordneten Prozesses an.
access_granted
7

Ich glaube, das Folgende ist kugelsicher, vorausgesetzt, der Benutzer hat Zugriff auf WMIC und TEMP verweist auf einen gültigen Pfad, in dem der Benutzer über Schreibrechte verfügt. Dies ist das Endergebnis einer Zusammenarbeit unter 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

Das Skript richtet eine exklusive Sperre für eine temporäre Datei ein, die die aktuelle Uhrzeit in den Namen einbezieht. Es kann nur dann zu einer Kollision kommen, wenn zwei gleichnamige Batch-Prozesse versuchen, die PID innerhalb desselben Zeitintervalls von 0,01 Sekunden zu ermitteln. In diesem Fall ist nur einer erfolgreich.

Jeder fehlgeschlagene Prozess wird wiederholt wiederholt und versucht es erneut mit einem neuen Sperrdateipfad, bis er erfolgreich ist.

Der vollständige Pfad zur Sperrdatei wird in eine eindeutige ID umgewandelt, die in der WMIC-Abfrage verwendet werden kann. WMIC wird in einem FOR / F-Befehl ausgeführt. Dies bedeutet, dass es in einem untergeordneten cmd.exe-Prozess ausgeführt wird. Aus diesem Grund wird die ParentProcessID des Prozesses cmd.exe abgerufen.

dbenham
quelle
7

Erweitere Tony Roths Antwort:

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

Mit dem WINDOWTITLE-Filter wird die Pipe umgangen, sodass Sie sie in eine for-Schleife einfügen und mit SET einer Variablen zuweisen können, wenn Sie möchten:

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

Durch Entfernen von /vwird es schneller und /NHdie Kopfzeile wird entfernt. Sie benötigen den Platzhalter danach, "uniqueTitle"da der Fenstertitel tatsächlich den aktuellen Befehl enthält (er würde also immer weitergehen, wenn Sie versuchen würden, ihn vollständig abzugleichen).

David
quelle
6

Verwenden von PowerShell + WMI:

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
Nicolas Melay
quelle
Nett; Wenn Sie PowerShell Core haben , wird es noch einfacher (obwohl keiner der Befehle schnell sein wird ):pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
mklement
5
  1. Unter Windows Task Manager müssen Sie zu Ansicht -> Spalten auswählen ... gehen und PID auswählen.
  2. "Jobliste / v", um ausführliche Taskinformationen in der Eingabeaufforderung abzurufen.
  3. Verarbeiten Sie den Explorer von live.sysinternals.com .
Vivek Kumbhar
quelle
2
@ Vivek, an einer Eingabeaufforderung ... und Sie täuschen Antworten
WooYek
Ich gab nur alle möglichen Optionen .. und keine Duplizierung .. Ich hätte auch PowerShell erwähnen können, aber ich hielt mich zurück, da dies in XP und 2003 nicht standardmäßig vorkommt .
Vivek Kumbhar
5

Wenn Sie wissen, dass nur eine cmd.exe ausgeführt wird, können Sie die PID folgendermaßen ermitteln:

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

echo %pid%
Zumalifeguard
quelle
Das klingt nach einer unwahrscheinlichen Annahme, Ihr Code könnte flockig sein
Raúl Salinas-Monteagudo
Raul, ich verstehe, was du sagst. Es ist in vielen Fällen unsicher, aber in einigen Fällen auch sicher - beispielsweise in einem Kiosksystem oder einer VM, in der Sie die vollständige Kontrolle darüber haben, welche Prozesse
gestartet
4

Dies sollte den Trick machen:

Jobliste / v

WooYek
quelle
3

Wenn Sie die PID des Bildnamens "notepad.exe" ermitteln möchten, funktioniert der folgende Code für Sie:

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

Wenn Sie das Windows 2003 Resource Kit haben, drücken Sie es durch qgrep, um genau die Zeile zu erhalten, die Sie möchten. Sie könnten dann die pid von hier extrahieren (dies setzt voraus, dass Sie nur einen cmd auf einmal ausgeführt haben),

tasklist /v | qgrep cmd

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

Schauen Sie sich diesen kleinen Trick an . Es setzt den Titel von cmd auf einen speziellen Wert und verwendet dann die Jobliste, um ihn zu finden. Erfinderisch

Greg

uSlackr
quelle
0

DIES IST KURZER WEG, UM DIE PROZESS-ID FÜR OFFENES CMD ZU ERHALTEN

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

Diese Antwort enthält NUR die Prozess-ID und keine zusätzlichen Informationen, die in der oberen Antwort enthalten sind.

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%

Erläuterung:

-Es gibt keine PID für cmd.exe, die größer als 18100 ist. Überprüfen Sie daher, ob PID2 größer als 8100 ist, damit wir wissen, ob es sich um eine 4-stellige oder eine 5-stellige Zahl handelt

Fall 1: Eine 5-stellige PID wie 17504 hat einen PID1-Wert von 17504 und einen PID2-Wert von 1750, daher verwenden wir PID1

Fall 2: Eine 4-stellige PID wie 8205 hat einen PID1-Wert von 8205 "und einen PID2-Wert von 8205, daher verwenden wir PID2

Fall 3: Eine 4-stellige PID wie 4352 hat einen PID1-Wert von 4352 "und einen PID2-Wert von 4352, daher verwenden wir PID2

Collin Fox
quelle