23

我有服务命名WinDefend,它在进程上运行svchost.exe
还有其他许多svchost.exe进程,我需要找到一种方法来获取它的 ID。
当我跑步时,tasklist /svc我可以看到: 在此处输入图像描述

我不知道我怎么能得到它。
我找到了这个命令,但是当我尝试它时select "PID"它给了我一个空列。 在此处输入图像描述

我需要将进程的 PID 变为变量。

4

8 回答 8

35

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

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

$process = Get-Process -Id $id

PowerShell 核心更新

在版本 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
于 2014-10-13T00:00:01.457 回答
8
$p=Tasklist /svc /fi "SERVICES eq windefend" /fo csv | convertfrom-csv
$p.PID
于 2014-10-13T01:47:52.997 回答
3

烦人的是,如果您想要当前进程的 pid,它需要您为脚本设置一个唯一的标题。然后在进程列表中搜索该唯一标题。值得庆幸的是,标题命令允许您这样做。另请参阅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 一次又一次地做到这一点。选择你的毒药——在 Windows 平台上都是一样的。

我通过 powershell 找到了一个更好的方法: $pid 返回当前进程的进程 ID。

于 2016-08-16T20:53:48.493 回答
1
# 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

谢谢,

于 2018-08-25T13:51:06.580 回答
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 '["]'

假设您已更改$serviceNameWinDefend而不是svchost.exe.

于 2017-11-09T12:18:29.333 回答
0
Get-Process -Id ((Get-WmiObject -Class Win32_Service -Filter "Name -eq 'WinDefend'").ProcessId)
于 2021-04-27T14:07:51.903 回答
0

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

执行该命令,即使它在 svchost 中,它也会设置指定的服务。

编辑:您只是在寻找 PID。只需执行相同的命令减去优先级设置即可。我假设您将使用它来设置优先级。呵呵

于 2022-01-01T10:18:24.203 回答
-1

我用过这个,它工作正常。YMMV

$ProcessName = "SomeProcessName"

$pidnumber = Get-Process -Name $ProcessName | Select -expand ID
于 2018-11-01T16:51:06.397 回答