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
# 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,
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
.
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
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.
I have used this and it works fine. YMMV
$ProcessName = "SomeProcessName"
$pidnumber = Get-Process -Name $ProcessName | Select -expand ID
$p=Tasklist /svc /fi "SERVICES eq windefend" /fo csv | convertfrom-csv
$p.PID