2

I have the following code, It's work when I use directly within powershell:

Get-WmiObject win32_operatingsystem | select @{LABEL=’LastBootUpTime’;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)

And it returns:

LastBootUpTime
--------------
14/09/2019 10:41:50

But when I use the command within a Powershell script .ps1 with invoke-command the output returns more informations:

LastBootUpTime        PSComputerName RunspaceId                          
--------------        -------------- ----------                          
9/14/2019 10:41:50 AM 192.168.0.20   af08d2d8-c4f1-4f85-9d6c-e3f4ffe475c6

Why this happen?

If possible, I'd like without the header LastBootUpTime too.

2
  • 1
    Invoke-Command will always return additional information, in this case where the command was run and the runspace id. Commented Sep 14, 2019 at 21:14
  • 1
    As an aside: The CIM cmdlets (e.g., Get-CimInstance) superseded the WMI cmdlets (e.g., Get-WmiObject) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell Core, where all future effort will go, doesn't even have them anymore. For more information, see this answer. Commented Sep 15, 2019 at 19:02

3 Answers 3

4

Since you're ultimately only interested in the (transformed) property value, there's no need to use Select-Object (whose alias is select) at all - use ForEach-Object instead:

Get-WmiObject Win32_OperatingSystem |
  ForEach-Object { $_.ConvertToDateTime($_.LastBootUpTime) }

Note: The extra properties you saw, added by a remote Invoke-Command call with a -ComputerName argument (described below), are still technically present on the result, but they won't display.

That said, the WMI cmdlets were deprecated in PowerShell version 3. Using Get-CimInstance in lieu of Get-WmiObject actually makes the .ConvertToDateTime() call unnecessary (the .LastBootUpTime now directly contains a [datetime] instance), in which case you can simply use Select-Object's -ExpandProperty parameter in order to return the property value only (rather than a [pscustomobject] instance with the requested property):

Get-CimInstance CIM_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime

Note: Get-CimInstance directly supports a -ComputerName argument, so you don't need Invoke-Command -ComputerName for the invocation; unlike the firewall-unfriendly DCOM protocol that the WMI cmdlets use, the CIM cmdlets use the same, firewall-friendly transport as PowerShell remoting.

Or, more succinctly and efficiently, especially in a case such as this where the command returns only a single object, use direct property access:

(Get-CimInstance CIM_OperatingSystem).LastBootUpTime

This answer contrasts the pros and cons of these two approaches and shows other alternatives.


As for what you tried, which generally relates to:

Managing the origin properties automatically added by remote operations:

In remoting scenarios, PowerShell decorates the objects returned with additional properties that provide origin information. These properties are (mostly) of type NoteProperty and are added:

  • when PowerShell remoting is involved - such as via Invoke-Command -ComputerName in your case.

  • when CIM cmdlets such as Get-CimInstance are directly used remotely, such as with the
    -ComputerName parameter.

These properties are:

  • .PSComputerName (the name of the remote computer on which the code was executed)

    • Note: On objects returned from remote CIM calls, .PSComputerName appears as a regular property (type Property), not a NoteProperty.
  • The associated hidden .PSShowComputerName property, which defaults to $true, which explains why you saw a PSComputerName column in the display output.

    • If you capture the objects before printing them to the screen, you can set the property to $false on them, in which case their .PSComputerName property won't show (but will still be there) - however, the .RunspaceId property may - situationally - still show, and would have to be explicitly excluded - see below.
  • PowerShell remoting only (not remote CIM calls): .RunspaceId (the ID of the remote runspace)

To exclude these from local display / presence on the object, use the following techniques:

  • If you're only interested in select properties, make the Select-Object call locally, which, by virtue of locally constructing new [pscustomobject] instances with the properties of interest only, implicitly excludes the remoting-added properties:
Invoke-Command -ComputerName ... { ... } |
  Select-Object Name, LastBootUpTime  # LOCAL call to Select-Object
  • If you're interested in all properties except the remoting-added ones, use
    Select-Object -ExcludeProperty to eliminate them explicitly:
# Get remote output, then locally exclude the remoting-added properties.
Invoke-Command -ComputerName ... { ... } |
  Select-Object * -ExcludeProperty PSComputerName, PSShowComputerName, RunSpaceId

Note: Select-Object generally returns [pscustomobject] instances whose properties are static copies of the input objects and which lack the input type's methods.

Sign up to request clarification or add additional context in comments.

Comments

4

Invoke-Command will always return additional information, in this case where the command was run and the runspace id. You can always get results into a variable and simply print out the property you want.E.g.

$result = invoke-command {your-command}
$result.LastBootUpTime

or for short

(invoke-command {your-command}).LastBootupTime

Note that when you are using wmi, you do not need to necessarily use invoke-command, you can also directly pass -computer parameter to it to run the command against a remote computer:

Get-WmiObject win32_operatingsystem -computer "remote_computer_name"

1 Comment

Nice; worth adding: The WMI cmdlets were superseded by the CIM cmdlets in PowerShell version 3, and, unlike the WMI cmdlets, which use the firewall-unfriendly DCOM remoting, the CIM cmdlets (with the -ComputerName and -CimSession parameters) use the same firewall-friendly remoting transport as PowerShell's general-purpose remoting. On a minor note: Invoke-Command only decorates the output objects when actual remoting is involved (with -ComputerName or -Session[Name] arguments - though there's rarely a good reason to use Invoke-Command for local execution).
0

I found one way! if someone to need here is:

Get-WmiObject win32_operatingsystem | select @{LABEL=’LastBootUpTime’;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}|Select-Object -ExpandProperty  lastbootuptime

Here is how I used (I'm creating a report in HTML for my database)

write-output "<p> Horario do Ultimo boot: $(Get-WmiObject win32_operatingsystem | select @{LABEL=’LastBootUpTime’;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}|Select-Object -ExpandProperty  lastbootuptime)</p>"

The output was (in my language and region):

Horario do Ultimo boot: 09/14/2019 10:41:50

1 Comment

That works, but is inefficient (and verbose, with duplication); you can do without Select-Object altogether, if all you're interested in is the value of the $_.ConvertToDateTime($_.lastbootuptime) method call: simply use ForEach-Object instead: Get-WmiObject win32_operatingsystem | ForEach-Object { $_.ConverttoDateTime($_.lastbootuptime) }.

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.