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

Powershell 如何使用脚本变量通过其服务名称获取进程id,powershell,windows-7,process,tasklist,Powershell,Windows 7,Process,Tasklist,我有一个名为windefind的服务,它运行在进程svchost.exe 还有许多其他的svchost.exe进程,我需要找到一种方法来获取它的ID。 当我运行tasklist/svc时,我可以看到: 我不知道怎样才能得到它。 我找到了这个命令,但是当我尝试选择“PID”时,它给了我空列。 我需要将进程的PID设置为变量。tasklist只是返回文本,而不是具有您可以访问的属性的实际对象。您可以使用WMI来获取此信息: $id = Get-WmiObject -Class Win32_Ser

我有一个名为
windefind
的服务,它运行在进程
svchost.exe

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

我不知道怎样才能得到它。
我找到了这个命令,但是当我尝试
选择“PID”
时,它给了我空列。


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

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

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

$process = Get-Process -Id $id

尽管这很烦人,但如果需要当前进程的pid,则需要为脚本设置唯一的标题。然后在进程列表中搜索该唯一标题。谢天谢地,Title命令允许您这样做。也可以看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。

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

编辑: 由于WinDefend是程序的一个子服务(在本例中为
svchost.exe
),您可能需要将
任务列表的详细标志切换为
/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
更改为
windefind
,而不是
svchost.exe

# 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

谢谢,

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

$ProcessName = "SomeProcessName"

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

当我运行
$servicename='windefind'$pidArgumentPlacement=1时,调用详细版本的tasklist并将其筛选为包含服务名称的行$serviceAsCSVString=tasklist/v/fo csv | findstr/i$serviceName
$serviceScsvString
为空。抱歉,我的脚本中有一个输入错误<代码>$serviceName
在第一行拼写错误。再试一次,确保变量名匹配;powershell区分大小写。它不工作,而且powershell不区分大小写。如果您将运行
$a=“a”$A
您将看到它将打印相同的值。你在你的机器上检查过这个代码吗?只运行:
$serviceName='WinDefend'$pidArgumentPlacement=1 tasklist/v/fo csv | findstr/i$serviceName
它将找不到任何内容。问题在于您没有使用显示服务名称的
/svc
开关。因此,它不显示
windefind
服务。修复代码:只需将
/v
替换为
/svc
Btw
svchost.exe
不是一个好例子,因为它不是一项服务。我已更新了答案,我似乎误解了你在寻找什么。虽然这个答案可能会解决这个问题,但如果你解释一下它是如何工作的,它会更有用,但我的情况不同。进程名为
svchost.exe
,它在任务管理器中出现了几次。然后,您只需要找到与WinDefend服务相关的一个“仅仅显示所有
svchost.exe
的id并不能解决此问题。我试图在服务上执行此操作,我似乎无法将-expand id与get服务一起使用。我认为您误解了这个问题。虽然此代码可能会回答此问题,提供关于此代码为什么和/或如何回答此问题的附加上下文可提高其长期价值。
$ProcessName = "SomeProcessName"

$pidnumber = Get-Process -Name $ProcessName | Select -expand ID
Get-Process -Id ((Get-WmiObject -Class Win32_Service -Filter "Name -eq 'WinDefend'").ProcessId)