Get-Service via Invoke-Command and the "Status" property

Hi all,

First time poster but have been lurking for a while.
Anyway I stumbled upon this question and thought I should ask if there is quick way of solving this.

If you run the following line:

$data = Invoke-Command -ComputerName server1 {Get-Service | select name,displayname,status}

If you then do a

$data | get-member

You would see for the status property:
Name: Status
MemberType: NoteProperty
Definition: Deserialized.System.ServiceProcess.ServiceControllerStatus Status=Stopped

Is there an easy/quick way of just getting either the deserialized or the string version of the definition?

I can always recreate new objects and just picking one of them in a foreach loop.
But is there a quicker way to “get rid” of one of the definition values for Status?

Thanks in advance,

So… you’re running Get-Member, which is supposed to show you the definition.

What is it you’re after? Just “Stopped?”


$data | select name,displayname,@{n=‘def’;e={($_ |gm | ?{$ -eq ‘status’}).definition}}

Look at the answer by Boe Prox from

I think it has to do with the object being returned as a deserialized hash table. I had some issues access data that that object type in the past. I did some up with something similiar to what you are looking for, but it does have an extra step to make it into a hashtable that you can access.

$ret = Invoke-Command -computername comp1,comp2,comp3 -ScriptBlock {
New-Object PSObject -Property @{
Computer = hostname
IP = ipconfig
Pass_policy = net accounts
$hash = @{}
$ret | % {
$hash[$.computer]= $
You can then do something like $hash.‘computername’.ip and get the data.

The issue is this (in a condensed form):

$data | convertto-json | convertfrom-json

Will give you an error because status gets two values named ‘value’ which don’t work.

I have solved the problem by creating new objects but I wonder if its possible to just get one of those values from the first invoke statement. Rather than go through an extra loop.

the issue on my test lab was the returns from get-service had to be converted prior to sending the data back to the initiating system

this was on windows 10 1607 and powershell 5.1.14393.103

$data =Invoke-Command -ComputerName . {Get-Service | select name,displayname,status|convertto-json}|ConvertFrom-Json

Can you share a bit about the scenario, here?

I ask because the native XML serialization/deserialization should work - the back-and-forth in JSON shouldn’t be necessary. In general, it’s considered a good practice to get the entire XML object and select locally…

Invoke-Command { Get-Service } | Select name,status

So that the object being serialized isn’t a Selected subset. That just helps the ETS and formatting system make the right decisions. When you select remotely, you can indeed get some odd decisions being made, since the receiving computer doesn’t have a proper TypeName to match against. That’s when you’ll tend to get goofy hashtables.


Didn’t think of using the select after the return of the data, if it works then it would be a better solution.


Sorry I tried to keep the “scenario” as close to the core problem as possible but I guess it became too short :slight_smile:
I don’t want to convert the data straight away to json it was just a way to illustrate the problem.
Basically I’ve written a module that will inventory local and remote servers, according to our needs and then output the results to json.
Later on if we would like to use that information we could import the json file and convert it back to powershell objects or any other tool that can use json as a starting point.

Yes, doing the select after the invoked result, rather than in the scriptblock works.
Didn’t think it would be a difference but I guess I learn something every day :slight_smile:

And consider persisting the results in CliXML. It’s a better-fidelity format; you can always use PowerShell to import that and convert to JSON if some other tool needs that.

What I saw was the Status object had two values a numerical value and a Friendly string value when it is deserialized

Compare these two tests

Get-service Bits|Select name,displayname,status|ConvertTo-Json
    "Name":  "Bits",
    "DisplayName":  "Background Intelligent Transfer Service",
    "Status":  4

But the result is different when deserialized

Get-Service Bits |select name,displayname,status|Export-Clixml -path D:\test\Test_data.xml
$data = Import-Clixml -path D:\test\Test_data.xml
    "Name":  "Bits",
    "DisplayName":  "Background Intelligent Transfer Service",
    "Status":  {
                   "value":  4,
                   "Value":  "Running"

Yeah, right. There’s only a few instances where you’d see that, but Services is one of those instances. The actual value is 4, but there’s a translation mechanism in play that also gives you “Running.” There’s some PowerShell magic getting involved in the middle. I can see where that would be troubling for strict JSON.

And for the record, that’s not happening because you’re selecting a subset of properties. It’d do it with the entire object, too. There are some other translated properties that’ll do the same thing, in fact, like StartType. But technically, Status becomes a collection, having two child objects. In really truly strict JSON, “value” and “Value” are different (case sensitivity). I think .NET’s JSON implementation is a little fuzzier, though.

The difference is that with CliXML, PowerShell will behave “more normally” after an import; if you use JSON as your persistence format, you’ll lose some of PowerShell’s automagic when you re-import. Hopefully not a deal-breaker for you.

Will have a look at the difference between CliXML and JSON.

One thing I noticed while doing the workaround by looping through the returned results was the selection of either the deserialized or the string value.
The code I used was:

$serviceData = @()

foreach($s in $service)
     $status = $s.Status.Value
     $properties = @{ "Name" = $s.Name;
                      "DisplayName" = $s.DisplayName;
                      "Status" = $status;
     $serviceData += New-Object -TypeName PSObject -Property $properties

While trying to select one of the values I experimented and I could get the string value with the above $status = $s.Status.Value example.
To get just the numerical value I found I could do $s.Status[0]
But $s.Status[1] didn’t result in the string value, maybe I’m missing something but it seemed a bit strange.

Anyway doing the select localy fixed the issue I was having.