2

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?

2 Answers 2

3

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)
Sign up to request clarification or add additional context in comments.

Comments

3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.