Reputation: 427
I have pretty simple code that iterates over the output of Get-Service | Select Name, DisplayName, Status
and then formats it into a json object. The problem I am facing is running that command outside of my powershell script returns the actual textual status (RUNNING, STOPPED, etc), but in the script the status is numeric (1-4). I am currently running PS Version 5.1.18362.145
Script:
$services = Get-Service | Select Name, DisplayName, Status
$services.ForEach({
Add-Member -NotePropertyName 'table' -NotePropertyValue 'Status' -InputObject $_;
})
$payload = @{
metrics = @($services)
} | ConvertTo-Json
Write-Output ($payload)
Example Output:
{
"Name": "WPDBusEnum",
"DisplayName": "Portable Device Enumerator Service",
"Status": 1,
"table": "Status"
},
{
"Name": "WpnService",
"DisplayName": "Windows Push Notifications System Service",
"Status": 4,
"table": "Status"
},
{
"Name": "WpnUserService_8be1a",
"DisplayName": "Windows Push Notifications User Service_8be1a",
"Status": 4,
"table": "Status"
}
I would prefer for Status
to remain textual instead of numeric. Is this something specific to PS 5?
Upvotes: 2
Views: 4319
Reputation: 440337
The .Status
property of the [System.ServiceProcess.ServiceController]
instances that cmdlet Get-Service
outputs is of type [System.ServiceProcess.ServiceControllerStatus]
, which is an enumeration type (derived from [System.Enum]
): that is, it associates symbolic names with numeric values; e.g., symbolic name Stopped
is associated with the number 1
.
ConvertTo-Json
serializes such enumeration values as numbers:
invariably in Windows PowerShell.
by default in PowerShell Core; you can opt to use the symbolic names (as strings) instead by using the -EnumsAsStrings
switch.
In Windows PowerShell you therefore have to explicitly convert the symbolic names to strings before calling ConvertTo-Json
, which you can achieve with a calculated property; here's a simplified example:
Get-Service |
Select-Object Name,
DisplayName,
@{ n='Status'; e={ $_.Status.ToString() } },
@{ n='table'; e={ 'Status' } } |
ConvertTo-Json
The above yields something like the following; note that the "Status"
property now contains strings representing the symbolic names of the enumeration type:
{
"Name": "AppIDSvc",
"DisplayName": "Application Identity",
"Status": "Stopped",
"table": "Status"
},
{
"Name": "Appinfo",
"DisplayName": "Application Information",
"Status": "Running",
"table": "Status"
}
...
Applied to your scenario:
[pscustomobject] @{
metrics = @(
Get-Service |
select Name,
DisplayName,
@{ n='Status'; e={ $_.Status.ToString() } },
@{ n='table'; e={ 'Status' } }
)
} | ConvertTo-Json
Note how use of a single pipeline is sufficient.
Upvotes: 3
Reputation: 576
You could do something like this:
$services = New-Object System.Collections.ArrayList
foreach ($service in (Get-Service)){
$services.Add(@{"Name"= $service.Name; "DisplayName" = $service.DisplayName; "Status" = $service.Status.ToString()}) | Out-Null
}
$payload = @{
metrics = @($services)
} | ConvertTo-Json
Write-Output ($payload)
Upvotes: 3