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

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

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

мне нужно получить PID процесса для переменной.

5 ответов


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

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

$process = Get-Process -Id $id

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

раздражает, как это, это требует, чтобы вы установили уникальный заголовок для своего сценария, если вы хотите 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. Выберите свой poison-на платформе Windows это все равно.

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


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

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

# Call for the verbose version of tasklist and filter it for the line with your service's 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 чтобы избежать получения столбца имена.

изменить: Как WinDefend является subservice программы (в данном случае svchost.exe) вам может потребоваться поменять флаг verbose на tasklist to /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 to WinDefend вместо svchost.exe.


# Enter servicename. (instead of 'netman')
$service = Get-CimInstance -class win32_service | Where-Object name -eq 'netman' | select name, processid
$process = Get-Process | Where-Object ID -EQ $service.processid
Clear-Host
Write-Host '********* ServiceName, PID and ProcessName ******'
Write-Host 'ServiceName:' $service.name 
Write-Host 'ID:' $process.Id 
Write-Host 'ProcessName:' $process.Name

спасибо,