PowerShell脚本开发:对比进程文件与当前进程并提取新进程信息
解决你的PowerShell进程对比脚本疑问
嘿,作为PowerShell新手能梳理出这么清晰的思路真的很不错!我来一步步帮你解决每个疑问,最后给你完整的可运行脚本。
疑问1:如何从文本文件中仅读取进程名称?
用Get-Process > proc.txt生成的文件是默认的表格输出,前3行是标题和分隔线,后面才是进程数据。我们可以这样精准提取名称:
# 读取文件,跳过标题行,过滤空行,分割每行取名称列 $savedProcessNames = Get-Content $inputFile | Select-Object -Skip 3 | Where-Object { $_ -match '\S' } | ForEach-Object { # 按任意空白字符分割,取第二个元素(对应Name列) ($_ -split '\s+')[1] }
这里-Skip 3跳过无用的标题和分隔线,Where-Object过滤掉可能的空行,-split '\s+'处理每行的空格分隔逻辑,确保准确拿到进程名称。
疑问2:如何仅保留新进程(而非所有差异进程)到变量中?
Compare-Object确实会返回两边的差异,但它的SideIndicator属性可以帮我们精准筛选:=>表示**仅存在于右边集合(当前运行进程)**的项,也就是你要找的新进程。我们可以这样过滤:
$currentProcessNames = (Get-Process).Name # 对比两个名称集合,只保留当前有但文件里没有的进程 $newProcessNames = Compare-Object -ReferenceObject $savedProcessNames -DifferenceObject $currentProcessNames | Where-Object { $_.SideIndicator -eq '=>' } | Select-Object -ExpandProperty InputObject
用-ExpandProperty InputObject把结果直接转换成名称字符串的集合,方便后续直接调用进程查询命令。
疑问3:如何根据进程名称获取所需的其余进程信息?
直接用Get-Process -Name $newProcessNames就能获取这些进程的完整对象,然后我们可以提取需要的属性,还能计算运行时长:
$newProcesses = Get-Process -Name $newProcessNames | Select-Object Id, Name, @{Name='StartTime'; Expression={ $_.StartTime.ToString('yyyy-MM-dd HH:mm:ss') }}, @{Name='RunningTime'; Expression={ $runtime = (Get-Date) - $_.StartTime # 格式化运行时长为友好的天/时/分格式 "{0}天 {1}小时 {2}分钟" -f $runtime.Days, $runtime.Hours, $runtime.Minutes }}
这里用计算属性(@{Name=; Expression=})来格式化启动时间,以及计算并展示易读的运行时长,比直接输出原始TimeSpan对象更直观。
疑问4:如何将信息整齐地整合到一个文件中?
有两种实用方式,按需选择:
- 格式化表格输出:适合直接查看,用
Format-Table配合Out-File:
$newProcesses | Format-Table -AutoSize | Out-File -FilePath "NewProcesses_$(Get-Date -Format 'yyyyMMddHHmmss').txt" -Encoding UTF8
- CSV文件输出:适合后续用Excel等工具分析,用
Export-Csv:
$newProcesses | Export-Csv -FilePath "NewProcesses_$(Get-Date -Format 'yyyyMMddHHmmss').csv" -NoTypeInformation -Encoding UTF8
同时我们也可以把结果输出到控制台,方便实时查看:
$newProcesses | Format-Table -AutoSize
完整的脚本实现
把上面的步骤整合起来,做成可以接受文件参数的完整脚本:
<# .SYNOPSIS 对比保存的进程列表和当前运行进程,找出新增的进程并输出详细信息 .PARAMETER InputFile 由`Get-Process > proc.txt`生成的进程列表文本文件路径 #> param( [Parameter(Mandatory=$true)] [string]$InputFile ) # 1. 验证文件存在并提取保存的进程名称 if (-not (Test-Path $InputFile)) { Write-Error "文件 $InputFile 不存在!" exit 1 } $savedProcessNames = Get-Content $InputFile | Select-Object -Skip 3 | Where-Object { $_ -match '\S' } | ForEach-Object { ($_ -split '\s+')[1] } # 2. 获取当前运行的进程名称 $currentProcessNames = (Get-Process).Name # 3. 找出仅当前存在的新进程名称 $newProcessNames = Compare-Object -ReferenceObject $savedProcessNames -DifferenceObject $currentProcessNames | Where-Object { $_.SideIndicator -eq '=>' } | Select-Object -ExpandProperty InputObject if (-not $newProcessNames) { Write-Host "没有发现新增的进程!" exit 0 } # 4. 获取新进程的详细信息并格式化 $newProcesses = Get-Process -Name $newProcessNames | Select-Object Id, Name, @{Name='StartTime'; Expression={ $_.StartTime.ToString('yyyy-MM-dd HH:mm:ss') }}, @{Name='RunningTime'; Expression={ $runtime = (Get-Date) - $_.StartTime "{0}天 {1}小时 {2}分钟" -f $runtime.Days, $runtime.Hours, $runtime.Minutes }} # 5. 输出到控制台并写入文件 Write-Host "发现以下新增进程:" $newProcesses | Format-Table -AutoSize $outputFileName = "NewProcesses_$(Get-Date -Format 'yyyyMMddHHmmss').txt" $newProcesses | Format-Table -AutoSize | Out-File -FilePath $outputFileName -Encoding UTF8 Write-Host "详细信息已保存到文件:$outputFileName"
使用方法
- 先运行
Get-Process > proc.txt生成基准进程列表 - 运行脚本:
.\Find-NewProcesses.ps1 -InputFile .\proc.txt
内容的提问来源于stack exchange,提问作者Patai
相关产品推荐
相关产品推荐

