想要将 PSList 包装在 Powershell 函数中以使用管道值
Posted
技术标签:
【中文标题】想要将 PSList 包装在 Powershell 函数中以使用管道值【英文标题】:Want to Wrap PSList in a Powershell function to use pipeline values 【发布时间】:2011-05-08 11:24:31 【问题描述】:我喜欢 PSList,并使用 CPU 和 Elapsed 时间来识别需要杀死的进程。我想将它包装在一个返回管道值的 powershell 函数中,以便我可以执行以下操作:
get-remoteprocess server1 | where $_.CPUMinutes -gt 4
我被困在从函数返回值 - 我知道这需要是一个对象数组。
这是我的第一个版本的样子:
function get-remoteproc
param ($hostname)
$results = pslist "\\$hostname"
for ($i= 3; $i -le $results.length; $i++)
$strline = $results[$i]
$StrWithPrefix = " "+$results[$i]
$trimmedline = $StrWithPrefix -replace '\s+', " ";
$Splitline = $trimmedline.Split(" ")
$ProcessName = $Splitline[1]
.
.
$ProcessCPUTime = ":"+[string]$Splitline[7]
$SplitCpuTime = $ProcessCPUTime.Split(":")
$CpuHours = $SplitCpuTime[1]
$CpuMinutes = $SplitCpuTime[2]
$CpuSeconds = $SplitCpuTime[3]
.
.
.
$obj = New-Object PSObject
$obj | Add-Member Noteproperty -Name "Name" -Value $Name
$obj | Add-Member Noteproperty -Name "PPid" -Value $Ppid
$obj | Add-Member Noteproperty -Name "Pri" -Value $Pri
采纳 Doug Finke 的建议,这个建议非常简洁,这是我稍作修改的版本,它适用于管道值。
function get-remoteproc
param ($hostname=$env:COMPUTERNAME)
$results = PsList "\\$hostname"
foreach($record in $results[3..($results.Count)])
# Remove spaces
while ($record.IndexOf(" ") -ge 0)
$record = $record -replace " "," "
$Name,$Processid,$Pri,$Thd,$Hnd,$Priv,$CPUTime,$ElapsedTime = $record.Split(" ")
$properties = @
Name = $Name
Pid = $Processid
Pri = $Pri
Thd = $Thd
Hnd = $Hnd
Priv = $Priv
CPUTime = $CPUTime
ElapsedTime = $ElapsedTime
New-Object PSObject -Property $properties |
Add-Member -PassThru ScriptProperty CPUH [int]$this.CPUTime.Split(":")[0] |
Add-Member -PassThru ScriptProperty CPUM [int]$this.CPUTime.Split(":")[1] |
Add-Member -PassThru ScriptProperty CPUS [int]$this.CPUTime.Split(":")[2] |
Add-Member -PassThru ScriptProperty ElaH [int]$this.ElapsedTime.Split(":")[0] |
Add-Member -PassThru ScriptProperty ElaM [int]$this.ElapsedTime.Split(":")[1] |
Add-Member -PassThru ScriptProperty ElaS [int]$this.ElapsedTime.Split(":")[2]
以及对函数的调用,这表明对象已正确展开以供管道使用:
get-remoteproc "Server1" | where (($_.CPUM * $_.CPUS) -gt 60) -and ($_.name -notmatch "Idle" )|
ft name, pid, pri, thd, hnd, priv, CPUH, cpuM, cpuS, ElaH, ElaM, ElaS -auto
谢谢大家!
【问题讨论】:
你的函数缺少一个右大括号,没有它很难说你的代码有什么问题 【参考方案1】:正如 empo 指出的那样,您需要将 $obj 发送回管道。这是将 plist 文本转换为 PowerShell 对象的另一种方法。
function get-remoteproc
param ($hostname=$env:COMPUTERNAME)
$results = PsList "\\$hostname"
foreach($record in $results[3..($results.Count)])
# Remove spaces
while ($record.IndexOf(" ") -ge 0)
$record = $record -replace " "," "
$Name,$Processid,$Pri,$Thd,$Hnd,$Priv,$CPUTime,$ElapsedTime = $record.Split(" ")
$properties = @
Name = $Name
Pid = $Processid
Pri = $Pri
Thd = $Thd
Hnd = $Hnd
Priv = $Priv
CPUTime = $CPUTime
ElapsedTime = $ElapsedTime
New-Object PSObject -Property $properties |
Add-Member -PassThru ScriptProperty CPUHours $this.CPUTime.Split(":")[0] |
Add-Member -PassThru ScriptProperty CPUMinutes $this.CPUTime.Split(":")[1] |
Add-Member -PassThru ScriptProperty CPUSeconds $this.CPUTime.Split(":")[2]
【讨论】:
【参考方案2】:要一个一个返回传递给管道的值数组,您只需要在函数中返回多个值。例如:
函数 get-remoteproc 参数($主机名) $results = pslist "\\$主机名" for ($i= 3; $i -le $results.length; $i++) # 你的员工到 $obj # 输出 $obj $obj函数结果是$obj
的数组。当连接到管道时,数组将被注册,所有值将被一一传递给流。
【讨论】:
为了输出一个对象,$obj
行就足够了。在这里使用$objs
无效(并且+=
对于此类数组的操作非常缓慢,仅供参考)。
$objs 不会有效,但我相信,$objs 会有效。
@Roman:我不这么认为。函数的工作方式与过滤器不同。在这里,函数必须返回一个数组,以便在后续管道中进行处理。
如果您返回 $objs,它将在返回时展开为对象流,而不是单个数组对象。如果你返回 ,$objs 它将把整个数组作为一个对象返回。
@empo,最后一行$objs
中的数组实际上已展开,结果与函数从循环内部输出$obs
相同,而不是首先收集项目(慢)然后将它们返回为$objs
。试试看。以上是关于想要将 PSList 包装在 Powershell 函数中以使用管道值的主要内容,如果未能解决你的问题,请参考以下文章
PowerShell Windows窗体包装器PowerShell表单控件包装器