Как получить идентификатор процесса по имени своей службы с переменной script to variable

У меня есть служба с именем WinDefend, и она выполняется в процессе svchost.exe
Там еще много процессов svchost.exe, и мне нужно найти способ получить его идентификатор.
когда я запускаю tasklist /svc, я вижу: enter image description here

Я не уверен, как это получить. Я нашел эту команду, но когда я попробовал select "PID", она дала мне пустой столбец. enter image description here

Мне нужно, чтобы PID процесса был переменным.

Ответ 1

tasklist просто возвращает текст, а не фактические объекты, у которых есть свойства, к которым вы можете получить доступ. Вы можете использовать WMI для получения этой информации:

$id = Get-WmiObject -Class Win32_Service -Filter "Name LIKE 'WinDefend'" | 
      Select-Object -ExpandProperty ProcessId

$process = Get-Process -Id $id

Ответ 2

$p=Tasklist /svc /fi "SERVICES eq windefend" /fo csv | convertfrom-csv
$p.PID

Ответ 3

Раздражает, так как это требует, чтобы вы установили уникальный заголовок для script, если вы хотите pid для текущего процесса. Затем найдите этот уникальный заголовок в списке процессов. К счастью, команда Title позволяет вам сделать именно это. Также см. MagicAndi ответ...

Вот мое решение пакетного файла:

@ECHO OFF
:SetVars
    SET _Thread=%1
    title=ExecBatch_%_Thread%
    Set /A "_iPID=0"
:Main
    CALL :getPID _iPID %_Thread%
    ...
EXIT /b

::----------------
::---- GetPID ---- 
::----------------
:getPID 
    setlocal   
        set _getPIDcmd=tasklist /v /fo csv 
        for /f "tokens=2 delims=," %%i in ('%_getPIDcmd% ^| findstr /i "ExecBatch_%2"') do (
            echo %%~i
            set _pid=%%~i
        )
    endlocal & Set %~1=%_pid%
exit /b

Кстати, у меня было "удовольствие" делать это снова и снова с годами, через API, или пакет, или ps. Выберите свой яд - на платформе Windows все равно.

Я нашел еще лучший способ через powershell: $pid возвращает идентификатор процесса текущего процесса.

Ответ 4

Альтернативный способ получения PID процесса:

$serviceName = 'svchost.exe'
$pidArgumentPlacement = 1

# Call for the verbose version of tasklist and filter it for the line with your service name. 
$serviceAsCSVString = tasklist /v /fo csv | findstr /i $serviceName

# Remove the quotes from the CSV string
$serviceCSVStringWithoutQuotes = $serviceAsCSVString -replace '["]'
# Turn the string into an array by cutting at the comma
$serviceAsArray = $serviceCSVStringWithoutQuotes -split ","
# Get the pid from the array
$servicePID = $serviceAsArray[$pidArgumentPlacement]

Или вы можете суммировать его до:

$servicePID = $($($(tasklist /v /fo csv | findstr /i $serviceName) -replace '["]') -split ",")[$pidArgumentPlacement]

Примечание.. Это захватит первую службу, которая соответствует вашему $serviceName, если вы запустите службу, которая запускает несколько экземпляров самого себя (e.x. slack), вы получите только первый pid. tasklist /v /fi "IMAGENAME eq slack.exe" /fo csv возвращает массив с каждой строкой CSV, являющейся записью массива. Вы также можете отфильтровать это с помощью findstr, чтобы избежать получения имен столбцов.

EDIT: Поскольку WinDefend является подсервисом программы (в этом случае svchost.exe) вам может потребоваться заменить флаг verbose для tasklist на /svc следующим образом:

$serviceAsCSVString = tasklist /svc /fo csv | findstr /i $serviceName

альтернативно искать имя службы через фильтр:

$serviceAsCSVString = tasklist /svc /fi "SERVICES eq $serviceName" /fo csv | findstr /i $serviceName

И принимая во внимание, что фильтр возвращает строку имен столбцов, а также строку, которую вы искали:

$serviceCSVStringWithoutQuotes = $serviceAsCSVString[1] -replace '["]'

Предполагая, что вы изменили $serviceName на WinDefend вместо svchost.exe.