-->

How to get process id by its service name with a s

2020-03-01 05:28发布

问题:

I have service named WinDefend and it runs on process svchost.exe
There other many svchost.exe processes and I need to find a way to get its ID.
when I run tasklist /svc I can see:

I am not sure how can I get it.
I found this command but when I tried the select "PID" it gave me empty column.

I need to get the PID of the process to variable.

回答1:

tasklist is just returning text, not actual objects that have properties you can access. You can use WMI to get this information instead:

$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:

Annoying as this is, it requires you to set a unique title for your script if you want the pid for the current process. Then search for that unique title within the list of processes. Thankfully, the Title command allows you to do just that. Also see MagicAndi's response...

Here is my batch file solution:

@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

BTW, I've had the 'pleasure' of doing this time and time again over the years, via API, or batch, or ps. Pick your poison - on a Windows platform it's all the same.

I found an even better way via powershell: $pid returns the current process' process id.



回答4:

I have used this and it works fine. YMMV

$ProcessName = "SomeProcessName"

$pidnumber = Get-Process -Name $ProcessName | Select -expand ID


回答5:

An alternative way to get a process 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]

Or you can sum it up to:

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

Note: This will grab the first service that matches your $serviceName, if you run a service that runs several instances of itself (e.x. slack) you'll only get the first pid. tasklist /v /fi "IMAGENAME eq slack.exe" /fo csv will return an array with each CSV line being an array entry. You can also filter this with findstr to avoid getting the column names.

EDIT: As WinDefend is a subservice of a program (In this case svchost.exe) you may need to swap the verbose flag for tasklist to /svc like so:

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

alternatively search for the service's name through a filter:

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

And taking into account that the filter returns a row of column names as well as the line you were looking for:

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

Assuming you've changed $serviceName to WinDefend instead of svchost.exe.



回答6:

# 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

Thanks,