Adding Member to JSON

Hello Everyone,

I have been searching high and low for a way to add a value to a JSON object. I havent found something that works, but it might just be my lack of understanding.

What I am trying to do is have a JSON object, that has the Date/Time, the Applications Currently Running, The application CPU %, and the current Disk Utilization.

 

I want to run the script every 30 minutes, and keep appending to the JSON file.

 

I think I want my JSON to look like this:

[{
“DateTime”: CurrentTime1
“Applications”:[{
“Application”: “AppName#1”,
“CPU Utilization”: “%CPU”
},
{
“Application”: “AppName#1”,
“CPU Utilization”: “%CPU”
}
]
}]

 

And the next time it runs it adds another member with the next date time, and whatever the new applications/CPU% are.

The code I wrote is below and it does not do what I want it to do.
Any thoughts?

 

$jobj= ""
$jobj += get-wmiobject Win32_PerfFormattedData_PerfProc_Process |where {$.PercentProcessorTime -gt 1 -and $.name -ne "Idle" -and $.name -ne "Total"}| select @{n="Application";e={$.name}},@{n="CPU";e={$.PercentProcessorTime}} | Sort-Object CPU -Descending | ConvertTo-Json ;
$toAdd = (get-counter -counter "\physicaldisk(_total)% disk time").countersamples.cookedvalue
$jobj | Add-Member -MemberType AliasProperty -Name 'DiskUtilization' -Value $toAdd

 

 

You will not want to convert to JSON and then add new members. Add the new members while it is still a PowerShell Object (deserialized). If you are only running this every 30 minutes, you could just write your JSON to disk. Then read the JSON and convert to a PowerShell Object using ConvertFrom-Json on each subsequent run.

If you do not do it this way, you will be stuck with doing JSON string appends or keeping the script running forever to keep the JSON in memory.

It is more complex to manipulate JSON rather than manipulate a PSObject. If you are storing it externally, then Export-CliXml will export the object as-is and maintain the nested structure. Basically, this does 5 runs importing\exporting each iteration and at the end you import the xml and convert it to json:

for ($i=1;$i -le 5;$i++) {
    'Performing run {0}...' -f $i
    $path = 'C:\Scripts\apps.xml'

    $results = @()
    if (Test-Path -Path $path) {
        $results += Import-Clixml -Path $path
    }

    $apps = get-wmiobject Win32_PerfFormattedData_PerfProc_Process |
            where {$_.PercentProcessorTime -gt 1 -and $_.name -ne 'Idle' -and $_.name -ne '_Total'} | 
            select @{n='Application';e={$_.name}},@{n='CPU';e={$_.PercentProcessorTime}} | 
            Sort-Object CPU -Descending 

    $results += [pscustomobject]@{
        ComputerName    = $env:COMPUTERNAME
        DateTime        = (Get-Date)
        DiskUtilization = (get-counter -counter '\physicaldisk(_total)\% disk time').countersamples.cookedvalue
        Applications    = @($apps)
    }

    $results | Export-Clixml -Path $path

    Start-Sleep -Seconds 10
}

Import-Clixml -Path $path | ConvertTo-Json

[quote quote=253580]It is more complex to manipulate JSON rather than manipulate a PSObject. If you are storing it externally, then Export-CliXml will export the object as-is and maintain the nested structure. Basically, this does 5 runs importing\exporting each iteration and at the end you import the xml and convert it to json:

<style class=“darkreader darkreader–sync” media=“screen”></style> <style class=“darkreader darkreader–sync” media=“screen”></style>

PowerShell
<textarea class="urvanov-syntax-highlighter-plain print-no" style="tab-size: 4; font-size: 14px !important; line-height: 18px !important; z-index: 1; opacity: 1; height: 486px;" readonly="readonly" data-settings="dblclick">for ($i=1;$i -le 5;$i++) { 'Performing run {0}...' -f $i $path = 'C:\Scripts\apps.xml'$results = @() if (Test-Path -Path $path) { $results += Import-Clixml -Path $path }

$apps = get-wmiobject Win32_PerfFormattedData_PerfProc_Process |
where {$.PercentProcessorTime -gt 1 -and $.name -ne ‘Idle’ -and $.name -ne 'Total’} |
select @{n=‘Application’;e={$
.name}},@{n=‘CPU’;e={$
.PercentProcessorTime}} |
Sort-Object CPU -Descending

$results += [pscustomobject]@{
ComputerName = $env:COMPUTERNAME
DateTime = (Get-Date)
DiskUtilization = (get-counter -counter ‘\physicaldisk(_total)% disk time’).countersamples.cookedvalue
Applications = @($apps)
}

$results | Export-Clixml -Path $path

Start-Sleep -Seconds 10
}

Import-Clixml -Path $path | ConvertTo-Json</textarea>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
for ($i=1;$i -le 5;$i++) {
'Performing run {0}...' -f $i
$path = 'C:\Scripts\apps.xml'
$results = @()
if (Test-Path -Path $path) {
$results += Import-Clixml -Path $path
}
$apps = get-wmiobject Win32_PerfFormattedData_PerfProc_Process |
where {$_.PercentProcessorTime -gt 1 -and $_.name -ne 'Idle' -and $_.name -ne '_Total'} |
select @{n='Application';e={$_.name}},@{n='CPU';e={$_.PercentProcessorTime}} |
Sort-Object CPU -Descending
$results += [pscustomobject]@{
ComputerName = $env:COMPUTERNAME
DateTime = (Get-Date)
DiskUtilization = (get-counter -counter '\physicaldisk(_total)\% disk time').countersamples.cookedvalue
Applications = @($apps)
}
$results | Export-Clixml -Path $path
Start-Sleep -Seconds 10
}
Import-Clixml -Path $path | ConvertTo-Json
[/quote]

 

This looks to do exactly what I am looking for. I was able to store it as JSON.

Thank you for writing all that!

Trying to look over what you did… it is so confusing!

I am having a hard time understanding how powershell treats convertFrom-JSON… because when I convert from JSON it wont let me add any new objects (says the system object does not support ADD).

There are no really clear JSON powershell tutorials out there.

 

It just seems like there is some piece to the puzzle I am missing on getting this stuff to work correctly.

 

Is there a powershell.org discord where I could ask more rapid fire questions or hire a tutor?