nobrac
nobrac

Reputation: 427

Powershell Get-Service command outputs service code instead of text status?

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

Answers (2)

mklement0
mklement0

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

gabriwinter
gabriwinter

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

Related Questions