[玩转系统] 构建 PowerShell 进程内存工具
作者:精品下载站 日期:2024-12-14 07:53:55 浏览:11 分类:玩电脑
构建 PowerShell 进程内存工具
本周我一直在测试一款新浏览器 Brave,它可能是 Firefox 的替代品。我从 Chrome 转向 Firefox 的原因之一是性能和更好的资源利用率。 Brave 现在可能是更好的选择,但这不是本文的主题。为了评估资源利用率,我使用了 Get-Process PowerShell cmdlet。因为我发现自己需要获得一些非常具体的结果,所以我决定编写一个 PowerShell 函数来简化该过程。这就是为什么您应该学习和使用PowerShell,以构建您自己的工具来解决您的业务需求。这是我的开发过程的一些故事。
我首先使用核心 PowerShell 表达式来使用工作集属性来显示进程信息。
Get-Process brave | Measure-Object Workingset -sum -average |
Select-object Count,Sum,Average
替换为您想要的任何进程(例如 Chrome)以看到类似的结果。这个简单的表达式获取所有勇敢的进程并将它们传输到 Measure-Object,该对象计算工作集属性的总和和平均值。在输出中查看进程名称会很有帮助,特别是因为我打算与 Firefox 进行比较。如果我这样做:
Get-Process brave,firefox | Measure-Object Workingset -sum -average |
Select-object Count,Sum,Average
我得到了两个浏览器的总和。不,我需要为每个进程运行 Get-Process 和 Measure-Object。一种方法是使用 ForEach-Object。
"brave","firefox" | foreach-object {
Get-Process -name $_ -PipelineVariable pv |
Measure-Object Workingset -sum -average |
Select-object @{Name="Name";Expression = {$pv.name}},
Count,Sum,Average
}
这个更好。我使用通用 PipelineVariable 参数来检索进程名称。 Measure-Object 的输出不包含 Get-Process 中的进程名称,因此为了使 Select-Object 正常工作,我需要一种方法来访问管道早期的内容。这就是 PipelineVariable 所实现的目标。
我不了解你,但我无法轻易地将所有这些字节转换成更有意义的东西。但 PowerShell 可以。
"brave","firefox" | foreach-object {
Get-Process -name $_ -PipelineVariable pv |
Measure-Object Workingset -sum -average |
Select-object @{Name="Name";Expression = {$pv.name}},
Count,
@{Name="SumMB";Expression = {[math]::round($_.Sum/1MB,2)}},
@{Name="AvgMB";Expression = {[math]::round($_.Average/1MB,2)}}
}
我现在有了可以生成我需要的友好结果的代码。
但我需要使其灵活且可重用。这就是函数发挥作用的地方。我可以快速将其变成一个函数。
Function Get-MyProcess {
[cmdletbinding()]
Param([string[]]$Name)
$Name | foreach-object {
Get-Process -name $_ -PipelineVariable pv |
Measure-Object Workingset -sum -average |
Select-object @{Name="Name";Expression = {$pv.name}},
Count,
@{Name="SumMB";Expression = {[math]::round($_.Sum/1MB,2)}},
@{Name="AvgMB";Expression = {[math]::round($_.Average/1MB,2)}}
}
}
它有效。
至此我可以认为这已经完成了。但是,当我编写 PowerShell 函数时,尤其是获取值或数据的函数时,我通常希望能够使其与远程计算机一起工作。我最初的想法是,因为 Get-Process 有一个 -Computername 参数,所以我所要做的就是将其添加到我的函数中并在代码中传递它。这种方法的潜在缺点是,当您以这种方式连接到远程计算机时,您是通过旧的远程连接进行连接。我试图尽可能避免使用旧连接,这意味着我需要利用 PowerShell 远程处理。一种解决方案是将 Get-Process 命令包装在 Invoke-Command 表达式中。
Function Get-MyProcess {
[cmdletbinding()]
Param([string[]]$Name,[string]$Computername = $env:computername)
Invoke-Command -ScriptBlock {
$using:Name | foreach-object {
Get-Process -name $_ -PipelineVariable pv |
Measure-Object Workingset -sum -average |
Select-object @{Name="Name";Expression = {$pv.name}},
Count,
@{Name="SumMB";Expression = {[math]::round($_.Sum/1MB,2)}},
@{Name="AvgMB";Expression = {[math]::round($_.Average/1MB,2)}}
}
} -ComputerName $computername
}
这越来越接近成熟的 PowerShell 功能。
如您所见,该函数不包含任何错误处理。由于我永远不需要查看 RunspaceID 属性,因此我始终必须将函数包装在另一个 PowerShell 表达式中才能将其删除。如果该函数将一个仅包含我想要查看的值的对象写入管道,那就更好了。另一个潜在的缺点是我的总和和平均值的格式为 MB。我做了一个限制这个函数灵活性的假设。起初我很懒。更好的方法是使用原始的、未格式化的数据将对象写入管道。
当我修改该函数时,这成为脚本块的核心:
foreach ($item in $ProcessName) {
Get-Process -Name $item -PipelineVariable pv -OutVariable ov |
Measure-Object -Property WorkingSet -Sum -Average |
Select-Object -Property @{Name = "Name"; Expression = {$pv.name}},
Count,
@{Name = "Threads"; Expression = {$ov.threads.count}},
Average, Sum,
@{Name = "Computername"; Expression = {$env:computername}}
}
输出值现在恢复为字节。但你知道,我真的很希望看到它们默认格式化为 MB。 PowerShell 可以做到这一点,而且事实上一直都是这样做的。当您运行 Get-Process 时,系统会为您设置默认显示格式。您看到的并不是底层流程对象的原始值。 PowerShell 使用格式指令。你也可以。
首先,您需要为输出对象指定类型名称。我可以使用 PowerShell 类构建一个函数。但插入类型名称也同样容易。
Invoke-Command @PSBoundParameters | Select-Object -Property * -ExcludeProperty RunspaceID,PS* |
ForEach-Object {
#insert a custom type name for the format directive
$_.psobject.typenames.insert(0, "myProcessMemory") | Out-Null
$_
}
现在是棘手的部分。格式指令是与 .ps1xml 文件一起保存的特殊 XML 文件。我可以做的一件事是定义自定义标题和值。
<TableColumnItem>
<ScriptBlock>[math]::Round($_.average/1MB,4)</ScriptBlock>
</TableColumnItem>
默认输出使用格式指令,但我仍然可以使用底层的实际属性名称。
顺便说一下,不要过多地解读这些结果,因为 Firefox 有很多扩展,而 Brave 有几个打开的选项卡。
我没有创建单独的 .ps1xml 文件,而是使用函数将内容作为此处字符串包含在脚本文件中,并创建一个临时文件,然后使用 Update-FormatData 导入该临时文件。完整的文件位于 Github 上。
Get-ProcessMemory.ps1:
Function Get-ProcessMemory {
get-processmemory code,powershell*
Name Count Threads AvgMB SumMB Computername
---- ----- ------- ----- ----- ------------
Code 9 154 112.8199 1015.3789 BOVINE320
powershell 3 77 179.1367 537.4102 BOVINE320
powershell_ise 1 21 242.0586 242.0586 BOVINE320
The default output displays the process name, the total process count, the total number of threads, the average workingset value per process in MB and the total workingset size of all processes also formatted in MB.
.EXAMPLE
PS C:\> get-processmemory -computername srv1,srv2,dom1 -Name lsass -cred company\artd
Name Count Threads AvgMB SumMB Computername
---- ----- ------- ----- ----- ------------
lsass 1 30 60.1719 60.1719 DOM1
lsass 1 7 10.8594 10.8594 SRV1
lsass 1 7 9.6953 9.6953 SRV2
.EXAMPLE
PS C:\> get-processmemory *ActiveDirectory* -Computername dom1 | select-object *
Name : Microsoft.ActiveDirectory.WebServices
Count : 1
Threads : 10
Average : 46940160
Sum : 46940160
Computername : DOM1
This example uses a wildcard for the process name because the domain controller only has one related process. The output shows the raw values.
.EXAMPLE
PS C:\> get-processmemory *edge*,firefox,chrome | sort sum -Descending
Name Count Threads AvgMB SumMB Computername
---- ----- ------- ----- ----- ------------
firefox 6 189 180.4134 1082.4805 BOVINE320
chrome 8 124 67.1377 537.1016 BOVINE320
MicrosoftEdgeCP 4 171 66.1846 264.7383 BOVINE320
MicrosoftEdge 1 37 70.1367 70.1367 BOVINE320
MicrosoftEdgeSH 1 10 8.2734 8.2734 BOVINE320
Get browser processes and sort on the underlying SUM property in descending order.
.NOTES
Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/
.LINK
Get-Process
Invoke-Command
.INPUTS
[string[]]
#>
[CmdletBinding()]
[OutputType("myProcessMemory")]
Param
(
[Parameter(Mandatory, ValueFromPipeline, Position = 0)]
[string[]]$Name,
[ValidateNotNullOrEmpty()]
[string[]]$Computername = $env:COMPUTERNAME,
[PSCredential]$Credential,
[switch]$UseSSL,
[Int32]$ThrottleLimit,
[ValidateSet('Default', 'Basic', 'Credssp', 'Digest', 'Kerberos', 'Negotiate', 'NegotiateWithImplicitCredential')]
[ValidateNotNullorEmpty()]
[string]$Authentication = "default"
)
Begin {
Write-Verbose "Starting $($MyInvocation.Mycommand)"
$sb = {
Param([string[]]$ProcessName)
# a process might have multiple instances so get each one by name
#group the processes to accomodate the use of wildcards
$data = Get-Process -Name $ProcessName | Group-Object -Property Name
foreach ($item in $data) {
$item.group | Measure-Object -Property WorkingSet -Sum -Average |
Select-Object -Property @{Name = "Name"; Expression = {$item.name}},
Count,
@{Name = "Threads"; Expression = {$item.group.threads.count}},
Average, Sum,
@{Name = "Computername"; Expression = {$env:computername}}
}
} #close ScriptBlock
#update PSBoundparamters so it can be splatted to Invoke-Command
$PSBoundParameters.Add("ScriptBlock", $sb) | Out-Null
$PSBoundParameters.add("HideComputername", $True) | Out-Null
} #begin
Process {
$PSBoundParameters.Remove("Name") | Out-Null
Write-Verbose "Querying processes $($name -join ',') on $($Computername -join ',')"
#need to make sure argument is treated as an array
$PSBoundParameters.ArgumentList = , @($Name)
if (-Not $PSBoundParameters.ContainsKey("Computername")) {
#add the default value if nothing was specified
$PSBoundParameters.Add("Computername", $Computername) | Out-Null
}
$PSBoundParameters | Out-String | Write-Verbose
Invoke-Command @PSBoundParameters | Select-Object -Property * -ExcludeProperty RunspaceID, PS* |
ForEach-Object {
#insert a custom type name for the format directive
$_.psobject.typenames.insert(0, "myProcessMemory") | Out-Null
$_
}
} #process
End {
Write-Verbose "Ending $($MyInvocation.Mycommand)"
} #end
} #close function
#region formatting directives for the custom object
[xml]$format = @'
default
myProcessMemory
Name
20
left
Count
7
right
Threads
7
right
AvgMB
10
right
SumMB
10
right
Computername
16
right
Name
TableColumnIt
Count
TableColumnIt
Threads
TableColumnIt
是的,这花了一点时间来开发,但我现在有了一个可重用且灵活的 PowerShell 功能。以及我可以用于未来功能的模型。我认为了解开发过程和最终产品是有帮助的。如果您有反馈或疑问,请随时发表评论。享受!
2019 年 1 月 2 日更新
我更新了 Github gist 中的代码,以更好地处理通配符的使用。我还调整了格式指令。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag