jak uzyskać własny pid procesu z wiersza polecenia w systemie Windows

26

próbuję znaleźć sposób na uzyskanie własnego PID z wiersza polecenia (do późniejszego użycia w skryptach nietoperzy) do tej pory jedynym przydatnym sposobem, jaki znalazłem, było użycie getpids.exe tutaj: http://www.scheibli.com/ projects / getpids / index.html, ale szukam polecenia „wbudowanego” w Windows

edit: szukam "kuloodpornego" sposobu - nie zakładam, że mój proces jest jedynym cmd.exe lub czymkolwiek

Radai
źródło

Odpowiedzi:

36

Ponieważ żadne z pozostałych rozwiązań nie jest kuloodporne i wbudowane, pomyślałem, że zaoferuję następujące rozwiązanie, ale pamiętaj, że będziesz musiał jakoś przeanalizować / zapisać wyniki:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
Tony Roth
źródło
to naprawdę miłe. jestem prawie pewien, że aktualny czas + losowo wygenerowana liczba może być ustawiona jako tytuł, aby zbliżyć się do kuloodpornego
radai
3
Nie używaj% random% +% time%, jeśli planista wywołuje skrypt wsadowy dwa razy w tym samym czasie. Miałem problem, że ten sam skrypt został wywołany z różnymi parametrami w tym samym czasie. Ziarno losowe było takie samo i wpadłem na kolizje podczas tworzenia katalogu tymczasowego. Odtąd nie można było poradzić sobie z błędem podczas tworzenia katalogu tymczasowego. Krótko mówiąc, jeśli możesz założyć, że twój skrypt nie zostanie zwolniony dwa razy w tym samym czasie, ta sztuczka powinna zadziałać.
Peter Schuetze,
Może być (nie dogłębnie przetestowane), że uzyskanie bardziej precyzyjnego znacznika czasu (w tym microseconds, zamiast 1/100 sekund jak w% time%), byłoby bardziej niezawodne w tym przypadku: wmic os get LocalDateTime(YearMonthDayHourMinuteSecond.Microsecond + Strefa czasowa). Chyba że planista jest w stanie uruchomić dwie rzeczy w dokładnie tej samej mikrosekundie ...
Gauthier Boaglio
To nie zadziała, jeśli proces będzie działał w innej sesji na komputerze, ponieważ tytuł jest wyświetlany jako N /
D
Daje to PID procesu nadrzędnego.
access_granted 12.04.17
7

Uważam, że poniższe informacje są kuloodporne, pod warunkiem, że użytkownik ma dostęp do WMIC i TEMP wskazuje prawidłową ścieżkę, w której użytkownik ma uprawnienia do zapisu. Jest to wynik końcowy wspólnej pracy pod adresem 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

Skrypt ustanawia wyłączną blokadę pliku tymczasowego, który uwzględnia aktualny czas w nazwie. Kolizja może nastąpić tylko wtedy, gdy dwa podobnie nazwane procesy wsadowe spróbują uzyskać PID w tym samym przedziale czasowym 0,01 sekundy, w którym to przypadku tylko jeden się powiedzie.

Każdy proces, który się nie powiedzie, będzie wielokrotnie zapętlać i próbować ponownie z nową ścieżką do pliku blokady, dopóki się nie powiedzie.

Pełna ścieżka do pliku blokady jest przekształcana w unikalny identyfikator, którego można użyć w zapytaniu WMIC. WMIC jest uruchamiany w poleceniu FOR / F, co oznacza, że ​​działa w potomnym procesie cmd.exe. Dlatego pobierany jest ParentProcessID procesu cmd.exe.

dbenham
źródło
7

Rozwijając odpowiedź Tony'ego Rotha:

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

Użycie filtra WINDOWTITLE pozwala uniknąć potoku, dzięki czemu można umieścić go w pętli for i przypisać do zmiennej za pomocą SET, jeśli chcesz:

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

Usunięcie /vpowoduje, że jest szybszy, a /NHpozbywa się linii nagłówka. Potrzebny będzie symbol wieloznaczny po, "uniqueTitle"ponieważ tytuł okna faktycznie zawiera bieżące polecenie (a więc będzie się wyświetlać i włączać, jeśli spróbujesz go w pełni dopasować).

David
źródło
6

Korzystanie z PowerShell + WMI:

powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
Nicolas Melay
źródło
Miły; jeśli masz PowerShell Rdzeń , to staje się jeszcze łatwiejsze (choć ani komenda będzie szybko ):pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
mklement
5
  1. Menedżer zadań Windows, musisz przejść do Widok -> Wybierz kolumny .. i wybrać PID.
  2. „tasklist / v”, aby uzyskać szczegółowe informacje o zadaniu w wierszu polecenia.
  3. Process Explorer z live.sysinternals.com .
Vivek Kumbhar
źródło
2
@Vivek, z wiersza poleceń ... i
kopiujesz
właśnie podałem wszystkie możliwe opcje .. i nie powielam się. Mógłbym także wspomnieć o PowerShell, ale powstrzymałem się, ponieważ nie jest to domyślnie w XP i 2003. Jeśli to jest dla systemu operacyjnego Vista w przyszłości, tak, PowerShell byłby moim wyborem .
Vivek Kumbhar
5

jeśli wiesz, że działa tylko jeden plik cmd.exe, możesz uzyskać PID w ten sposób:

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

echo %pid%
zumalifeguard
źródło
To brzmi jak nieprawdopodobne założenie, twój kod może być niestabilny
Raúl Salinas-Monteagudo,
Raul, rozumiem co mówisz. W wielu przypadkach jest to niebezpieczne, ale w niektórych jest bezpieczne - na przykład w systemie kiosku lub maszynie wirtualnej, w której masz całkowitą kontrolę nad uruchomionymi procesami, a nie
zumalifeguard
4

To powinno załatwić sprawę:

tasklist / v

WooYek
źródło
3

Jeśli chcesz znaleźć PID imagename „notepad.exe”, następujący kod będzie dla Ciebie działał:

for /F "tokens=1,2" %i in ('tasklist') do (
 if "%i" equ "notepad.exe" (set x=%j)
)
echo %x%
Minchurl
źródło
2

Jeśli masz zestaw Windows 2003 Resource Kit, przepchnij go przez qgrep, aby uzyskać żądaną linię. Następnie możesz wyodrębnić pid stąd (zakłada to, że masz tylko jeden cmd na raz),

tasklist /v | qgrep cmd

cmd.exe 2040 RDP-Tcp#447 0 1,804 K Running MACHINE\Administrator  0:00:00 Command Prompt
Gupik
źródło
1

Spójrz na tę małą sztuczkę partii . Ustawia tytuł cmd na specjalną wartość, a następnie używa tasklist, aby go znaleźć. Wynalazczy

\\ Greg

uSlackr
źródło
0

TO KRÓTKI SPOSÓB UZYSKANIA ID PROCESU DLA OPEN CMD

tasklist /v /fi "imagename EQ cmd.exe" /FO LIST | FIND "PID:"
hollopost
źródło
0

Ta odpowiedź da TYLKO identyfikator procesu i żadna z dodatkowych rzeczy, które zawiera najlepsza odpowiedź.

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%

Wyjaśnienie:

- nie będzie PID dla cmd.exe, który jest większy niż 18100, więc sprawdź, czy PID2 jest większy niż 8100, więc wiemy, czy jest to 4 lub 5 cyfr

przypadek 1: 5-cyfrowy PID jak 17504 ma PID1 val 17504 i PID2 val 1750, więc używamy PID1

przypadek 2: 4-cyfrowy PID jak 8205 ma wartość PID1 8205 "i wartość PID2 8205, więc używamy PID2

przypadek 3: 4-cyfrowy PID jak 4352 ma wartość PID1 4352 "i wartość PID2 4352, więc używamy PID2

Collin Fox
źródło