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
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.