Як отримати власний pid процесу з командного рядка у Windows


26

Я намагаюся знайти спосіб отримати власний PID з командного рядка (для подальшого використання в сценаріях bat), поки єдиним корисним способом, який я знайшов, було використання getpids.exe звідси: http://www.scheibli.com/ Проекти / getpids / index.html, але я шукаю команду, яка "вбудована" у Windows

редагувати: я шукаю спосіб "куленепробиваність" - жодних припущень про те, що мій процес є єдиним cmd.exe або чим-небудь іншим

Відповіді:


36

Оскільки жодне з інших рішень не є куленепроникним та вбудованим, я подумав, що пропоную наступне рішення, але зауважте, що вам потрібно буде якось проаналізувати / зберегти результати:

title mycmd
tasklist /v /fo csv | findstr /i "mycmd"

це дійсно акуратно. я майже впевнений, що поточний час + якесь випадкове згенероване число можна встановити як заголовок, щоб наблизитись до куленепробивної
radai

3
Не використовуйте% random% +% time%, якщо у вас планувальник викликає пакетний сценарій двічі одночасно. У мене виникло питання, що той самий скрипт викликався з різними параметрами одночасно. Насіння для випадкових випадків було однаковим, і я зіткнувся зіткненням під час створення тимчасового каталогу. Тоді не було можливості обробити помилку під час створення тимчасового каталогу. Якщо коротко розповісти, якщо ви можете припустити, що ваш сценарій не звільняється двічі одночасно, цей трюк повинен працювати.
Пітер Шуетце

Може бути (не глибоко перевірено), що отримання більш точної часової позначки (включаючи microseconds, а не 1/100 секунд, як у% час%), було б у цьому випадку більш надійним: wmic os get LocalDateTime(YearMonthDayHourMinuteSecond.Microsecond + Timezone). Якщо тільки планувальник не зможе запустити дві речі в точно такі ж мікросекунди ...
Готьє Боаліо

Це не спрацює, якщо процес запущений в іншому сеансі на комп’ютері, оскільки заголовок відображається як N / A
FrinkTheBrave

Це дає PID батьківського процесу.
access_granted

7

Я вважаю, що наступне є куленебезпечним, за умови, що користувач має доступ до WMIC і TEMP вказує на дійсний шлях, де користувач має права доступу. Це кінцевий результат спільної роботи за адресою 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

Сценарій встановлює ексклюзивний замок у тимчасовому файлі, який включає в себе ім'я поточного часу. Зіткнення може відбутися лише в тому випадку, якщо два подібні пакетні процеси намагаються отримати PID протягом одного і того ж інтервалу 0,01 секунди, і в цьому випадку лише один матиме успіх.

Будь-який процес, який завершився невдачею, буде повторно циклічно повертатися та повторити спробу з новим контуром файлу блокування, поки це не вдасться.

Повний шлях до файлу блокування перетворюється на унікальний ідентифікатор, який може бути використаний у WMIC-запиті. WMIC запускається в команді FOR / F, що означає, що він працює в дочірньому процесі cmd.exe. Ось чому отримується ParentProcessID процесу cmd.exe.


7

Розгортання відповіді Тоні Рота:

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

Використання фільтра WINDOWTITLE дозволяє уникнути труби, тому ви можете помістити його в цикл for і призначити його змінній за допомогою SET, якщо вам подобається:

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

Видалення /vробить це швидше, і /NHпозбавляється від рядка заголовка. Підстановочний знак вам знадобиться після того, "uniqueTitle"як заголовок вікна насправді містить поточну команду (таким чином, вона продовжуватиметься та увімкнеться, якщо ви спробуєте її повністю відповідати).


6

Використання PowerShell + WMI:

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

Ніцца; якщо у вас є PowerShell Core , це стає ще простіше (хоча жодна команда не буде швидкою ):pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
mklement

5
  1. Диспетчер завдань Windows, вам потрібно буде перейти до Перегляд -> Вибрати стовпці .. та вибрати PID.
  2. "tasklist / v", щоб отримати детальну інформацію про завдання в командному рядку.
  3. Провідник процесів від live.sysinternals.com .

2
@Vivek, з командного рядка ... і ти
копіюєш

Я просто дав усі можливі варіанти .. і жодного дублювання .. Я міг би також згадати PowerShell, але я стримав себе, оскільки це не за замовчуванням в XP та 2003 році. .
Vivek Kumbhar

5

якщо ви знаєте, що працює лише один cmd.exe, ви можете отримати PID таким чином:

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

echo %pid%

Це звучить як неправдоподібне припущення, ваш код може бути невмілим
Рауль Салінас-Монтеагудо,

Рауле, я розумію, що ти кажеш. У багатьох випадках це небезпечно, але в деяких безпечно - наприклад, система кіоску або ВМ, де ви повністю контролюєте, які процеси починаються, а ні
zumalifeguard

4

Для цього слід зробити фокус:

список завдань / v


3

Якщо ви хочете знайти PID імені зображення "notepad.exe", тоді вам підійде наступний код:

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

2

Якщо у вас є комплект ресурсів Windows 2003, натисніть його через qgrep, щоб отримати лише потрібну лінію. Потім ви можете витягнути pid звідси (це передбачає, що у вас є лише один cmd одночасно),

tasklist /v | qgrep cmd

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


0

ЦЕ КОРОТКИЙ ШЛЯХ ОКОНУВАТИ ІД ІД ПРОЦЕСУ НА ВІДКРИТИЙ CMD

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

0

Ця відповідь дасть ТІЛЬКИ ідентифікатор процесу, і жоден із зайвих матеріалів, до яких відповідь не відповідає.

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%

Пояснення:

-не буде PID для cmd.exe, який перевищує 18100, тому перевірте, чи PID2 більше 8100, тому ми знаємо, чи це чотиризначний чи п'ятизначний

випадок 1: у 5-значного PID типу 17504 є PID1 val 17504 та PID2 val 1750, тому ми використовуємо PID1

випадок 2: 4-значний PID, як 8205, має PID1 val 8205 "і PID2 val 8205, тому ми використовуємо PID2

випадок 3: 4-значний PID типу 4352 має PID1 val 4352 "і PID2 val 4352, тому ми використовуємо PID2

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.