Я пытаюсь найти способ получить свой собственный PID из командной строки (для последующего использования в сценариях bat).
До сих пор я нашел единственный полезный способ - использовать getpids.exe
отсюда : http://www.scheibli.com/projects/getpids/index.html, но я ищу команду, которая "встроена" в Windows.
Я ищу "пуленепробиваемый" способ. Никаких предположений о том, что мой процесс является единственным cmd.exe или чем-то еще.
Поскольку ни одно из других решений не является пуленепробиваемым и встроенным, я решил предложить следующее решение, но обратите внимание, что вам нужно как-то проанализировать / сохранить результаты:
title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
Расширяя ответ Тони Рота:
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"
потому что заголовок окна фактически содержит текущую команду (таким образом, она будет продолжаться и продолжаться, если вы попытаетесь полностью сопоставить ее).
Я считаю, что нижеследующее является пуленепробиваемым, если у пользователя есть доступ к 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.
Используя PowerShell + WMI:
powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
если вы знаете, что запущен только один 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%
Это должно помочь:
список задач / v
Если вы хотите найти PID образа "notepad.exe", то вам подойдет следующий код:
for /F "tokens=1,2" %i in ('tasklist') do (
if "%i" equ "notepad.exe" (set x=%j)
)
echo %x%
Если у вас есть набор ресурсов 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
Взгляните на это маленький трюк с партиями. Он устанавливает в заголовке cmd специальное значение, а затем использует список задач для его поиска. Изобретательный
\\ Грег
ЭТО КОРОТКИЙ СПОСОБ ПОЛУЧИТЬ ИДЕНТИФИКАТОР ПРОЦЕССА ДЛЯ OPEN CMD
tasklist /v /fi "imagename EQ cmd.exe" /FO LIST | FIND "PID:"
Этот ответ даст вам ТОЛЬКО идентификатор процесса и ничего лишнего, что не включает в себя верхний ответ.
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%
Пояснение:
-для cmd.exe не будет PID, который больше 18100, поэтому проверьте, превышает ли PID2 8100, чтобы мы знали, является ли это 4-значным или 5-значным числом
случай 1: пятизначный PID, например 17504, имеет значение PID1 17504 и значение PID2 1750, поэтому мы используем PID1
случай 2: четырехзначный PID, например 8205, имеет значение PID1, равное 8205 ", и значение PID2, равное 8205, поэтому мы используем PID2
случай 3: четырехзначный PID, например 4352, имеет значение PID1, равное 4352 ", и значение PID2, равное 4352, поэтому мы используем PID2.
вы можете попробовать с getcmdPid.bat - это самокомпилированное .net-приложение, встроенное в сценарий bat и возвращающее PID в качестве уровня ошибки:
call getcmdPid
echo %errorlevel%
В окне командной строки введите список заданий и нажмите Enter. Затем на экране отображаются сведения о запущенных процессах или службах, включая PID. проверить pid в cmd
То же самое и с Powershell. Вы также можете проверить PID в Powershell. Кроме того, вы также можете проверить PID в диспетчере задач. Нажмите Ctrl + Shift + Esc одновременно, чтобы открыть окно диспетчера задач. В окне диспетчера задач щелкните вкладку Сведения. Затем на экране отображается PID каждого запущенного процесса. Более подробную информацию можно найти в этом посте: Как узнать PID (идентификатор процесса) в Windows