首页 > 解决方案 > Powershell Add-Member to Object(如果存在),否则为 New-Object

问题描述

我正在尝试更好地了解 PowerShell 以便更好地工作,并且在我的一个小项目中遇到了问题。我想遍历一组性能计数器并获取cookedvalue(例如:\memory\available mbytes 的cooked 值为4096,以显示4GB 可用内存)。

我希望我的输出采用 JSON 格式,其结构如下:

PERFORMANCE
    MEMORY
       PAGE_FAULTS/SEC = 673
       %_COMMITED_MEMORY_IN_USE = 12
       AVAILABLE_MBYTES = 4096
       COMMITTED_BYTES = 3243
    PROCESS(*)
       %_PROCESSOR_TIME = 54
    LOGICALDISK(C:)
       DISK_READS/SEC = 462

这是下面我的脚本的当前状态。我正在努力掌握对象管理,并且真的可以朝着正确的方向轻推。该脚本工作正常(它使用 Get-Counter 获取cookedvalues,我可以打印结果)它只是以我遇到问题的逻辑方式将数据添加到对象。

$CounterPathList = "\Memory\Page Faults/sec", "\Memory\% Committed Bytes In Use", "\Memory\Available MBytes", "\Memory\Committed Bytes", "\Process(*)\% Processor Time", "\LogicalDisk(C:)\Disk Reads/sec" 

$Performance = New-Object –TypeName PSObject

ForEach($CounterPath in $CounterPathList){

    $PathRoot = ($CounterPath.split('\')[1]).ToUpper()
    $Name = (($CounterPath -replace '.*\\') -replace " ","_").ToUpper()
    $Value=((Get-Counter($CounterPath)).countersamples | select -property cookedvalue).cookedvalue

    if(!($Performance | Where-Object -Property Name -eq $PathRoot)){
        Add-Member -InputObject $Performance -MemberType NoteProperty –Name $PathRoot –Value "" -force
    }else{
        Add-Member -InputObject $Performance.$PathRoot -MemberType NoteProperty –Name $Name –Value $Value -force
    }

}

$Performance | ConvertTo-JSON

上面的脚本当前输出:

$Performance | ConvertTo-JSON
{
    "MEMORY":  "",
    "PROCESS(*)":  "",
    "LOGICALDISK(C:)":  ""
}

标签: powershellobject

解决方案


恕我直言,PowerShell JSON cmdlet ( -lt 5.1) 过于不灵活 - 通常它们与 s 一起工作得更好PSCustomObject。(一个例子见这篇文章的结尾,另一个例子是 V6ConvertFrom-Json添加了一个-AsHashtable开关)这是一种使用简单的方法来获得你想要的东西Hashtable

$counters = Get-Counter $wanted | select -ExpandProperty CounterSamples;
$toJson = @{ 'PERFORMANCE' = @{}};
foreach ($c in $counters) {
    $computerName, $key, $subKey = $c.Path.Replace('\\', '') -split '\\';
    $key = $key.ToUpper();
    $subKey = ($subKey -replace '\s+', '_').ToUpper();
    # each process has unique name => group by the common prefix
    if ($key -match '^process\(') {
        $subKey = $key;
        $key = 'PROCESS(*)';
    }
    if (!$toJson.'PERFORMANCE'.ContainsKey($key)) {
        $toJson.'PERFORMANCE'.$key = @{};  
    }
    $toJson.'PERFORMANCE'.$key.$subKey = $c.CookedValue;       
}

$serializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer;
$serializer.Serialize($toJson) |  Out-File $outfile;
# ConvertTo-JSON @($toJson) -Depth 10 | Out-File $outfile;

请注意,代码片段中的最后一行已被注释掉。虽然文档说明声明ConvertTo-Json通过使用JavaScriptSerializer 类实现的,但当我运行 cmdlet 时,JSON 嵌套Hashtablearray. 如果您关心空格/格式,潜在的缺点是JavaScriptSerializer.Serialize()将所有内容转储到单行字符串中。


推荐阅读