如何使用变量脚本通过服务名称获取进程ID

问题描述 投票:0回答:9

我有一个名为

WinDefend
的服务,它在进程
svchost.exe

上运行 还有其他很多
svchost.exe
进程,我需要找到一种方法来获取它的ID。
当我运行
tasklist /svc
时我可以看到: enter image description here

我不知道如何才能得到它。
我找到了这个命令,但是当我尝试

select "PID"
时,它给了我空列。 enter image description here

我需要获取进程的 PID 变量。

powershell windows-7 process tasklist
9个回答
41
投票

tasklist
只是返回文本,而不是具有您可以访问的属性的实际对象。您可以使用 WMI 来获取此信息:

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

$process = Get-Process -Id $id

PowerShell Core 更新

在版本 6 中,Windows PowerShell 开始向基于 .NET Core 的 PowerShell Core 提供跨平台支持。这导致 cmdlet 发生了许多以 Windows 为中心的更改,有些则完全被排除在外。 WMI 是仅限 Windows 的技术,因此其 cmdlet(例如 Get-WmiObject)未移植。但是,它的功能可通过 CIM cmdlet(例如 Get-CimInstance)使用,这是一个可在 PowerShell 6+ 上运行的版本:

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

$process = Get-Process -Id $id

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

3
投票

尽管这很烦人,但如果您想要当前进程的 pid,它要求您为脚本设置一个唯一的标题。然后在进程列表中搜索该唯一标题。值得庆幸的是,“标题”命令可以让您做到这一点。另请参阅 MagicAndi 的 response...

这是我的批处理文件解决方案:

@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 返回当前进程的进程 id。


2
投票
# 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

谢谢,


0
投票

获取进程 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
匹配的服务,如果您运行的服务运行其自身的多个实例 (例如 slack),您将只能获得第一个 pid。
tasklist /v /fi "IMAGENAME eq slack.exe" /fo csv
将返回一个数组,其中每个 CSV 行都是一个数组条目。您还可以使用
findstr
进行过滤,以避免获取列名称。

编辑: 由于 WinDefend 是程序的子服务(在本例中为

svchost.exe
),您可能需要将
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


0
投票
Get-Process -Id ((Get-WmiObject -Class Win32_Service -Filter "Name -eq 'WinDefend'").ProcessId)

0
投票

答案很简单。 (gps -id (get-wmiobject -query "select * from win32_service where name='servicename'").processid).priority class="priority"

执行该命令,它将设置指定的服务,即使它位于 svchost 中。

编辑:您只需要查找 PID。只需执行相同的命令减去优先级设置即可。我假设你会用它来设置优先级。呵呵


0
投票

很抱歉回答一个老问题,但我必须做一些与此非常类似的事情,并在整个过程中发现了这个问题。

虽然 WMI 选项很好,但我想要在单个 PS 命令中包含某些内容,以便我可以轻松地将其插入到我公司使用的 RMM 工具的相当笨拙的脚本工具集中。

我想到的是:

(tasklist /FI "Services eq WinDefend"/FO LIST | findstr /B "PID:") -replace "[^0-9]" , ''

您可以通过将其包装到 taskkill 命令中来得出我所做的结论:

taskkill /f /pid ((tasklist /FI "Services eq WinDefend"/FO LIST | findstr /B "PID:") -replace "[^0-9]" , '')


-1
投票

我用过这个,效果很好。 YMMV

$ProcessName = "SomeProcessName"

$pidnumber = Get-Process -Name $ProcessName | Select -expand ID
© www.soinside.com 2019 - 2024. All rights reserved.