Search code examples
windowspowershellpowershell-2.0windows-server-2008-r2event-log

Powershell - Add (default display) object property values from pipe to string


Update 2: I ended up figuring this out while writing it. I figured I'd post it for anyone else muddling through. See sub-heading 'Resolution - Get only default properties', or the answer. Please feel free to respond with alternate (especially better!) methods or comments.

Update 1: I started out without a way to do this, I've since found a way for ALL properties. I've left the build-up for anyone else confused like I was, but my current problem is that I want JUST the default display properties - see sub-heading 'Get all Properties'

Let's say I have a collection of objects in powershell - the specific example I'm working with is a collection of events acquired using the get-winevent cmdlet.

Does anyone know an elegant way to get the values of all the (default) properties of each object, from the pipeline, and add them to the end of a string? Especially a way that doesn't involve needing to know which properties you want.

For example, using variable $events containing some event log entries, if I simply call $events powershell will make some assumptions about the properties I want and format them as a list:

PS C:\> $events
TimeCreated         ProviderName                         Id Message
-----------         ------------                         -- -------
11/09/2014 3:59:... Microsoft-Window...                4634 An account was l...
11/09/2014 3:58:... Microsoft-Window...                4634 An account was l...

However, if I try to precede the returned entries with a string, I get the property names rather than values:

PS C:\> $events | %{"NEW RECORD" + $_}
NEW RECORDSystem.Diagnostics.Eventing.Reader.EventLogRecord
NEW RECORDSystem.Diagnostics.Eventing.Reader.EventLogRecord
PS C:\> $events | %{"NEW RECORD" + $_.properties}
NEW RECORDSystem.Diagnostics.Eventing.Reader.EventProperty System.Diagnostics.E
venting.Reader.EventProperty System.Diagnostics.Eventing.Reader.EventProperty S
ystem.Diagnostics.Eventing.Reader.EventProperty System.Diagnostics.Eventing.Rea
der.EventProperty

The easiest work around I could think of involved using (and therefore knowing) the property values, and also losing the notation that format-table or format-list would provide:

PS C:\> $events | %{"NEW RECORD - TimeCreated: " + $_.TimeCreated + "; ProviderName: "`
 + $_.ProviderName + "; ID: " + $_.ID + "; Message: " + $_.message}
NEW RECORD - TimeCreated: 09/11/2014 15:58:08; ProviderName: Microsoft-Windows-
Security-Auditing; ID: 4672; Message: Special privileges assigned to new logon.

Subject:
        Security ID:            S-*-*-**-*********-**********-**********-*****
        Account Name:           **********
        Account Domain:         **********
        Logon ID:               0x**********

Privileges:             SeSecurityPrivilege

Get all Properties

So I've discovered I CAN get ALL the properties, and their names, like this:

PS C:\> $events | %{"NEW RECORD" + ($_.psobject.properties | %{$_.name ; ":" ; $_.value})}
NEW RECORDMessage : Special privileges assigned to new logon.

Subject:
        Security ID:            S-*-*-**-*********-**********-**********-*****
        Account Name:           **********
        Account Domain:         **********
        Logon ID:               0x**********

Privileges:             SeSecurityPrivilege Id : 4672 Version : 0 Qualifiers :
Level : 0 <and so on>

However, I'm now pulling a bunch of stuff the consumers of my data won't need, since I only need the default properties and their names, plus a self-defined delimiter.

Is anyone aware of a notation that will return all values of all default display properties without said properties needing to be spelled out? Either a generic container for values (eg. $_.properties.value, though I tried that and it didn't work), or something like expand-property only without needing to specify a particular property name?

Resolution - Get only default properties

So it turns out I was overthinking this. FOREACH (%{}) can obviously preserve data from the pipeline across statements, so if I use two statements I can achieve the desired effect:

PS C:\> $events | format-list | %{"NEW RECORD" ; $_}
NEW RECORD
Message              : An account was successfully logged on.
<and etc>

Solution

  • I answered this while writing it, the details are above. In order to collect all properties from an object and their values, and include both as part of a string:

    PS C:\> $events | %{"NEW RECORD" + ($_.psobject.properties | %{$_.name ; ":IMASTRING:" ; $_.value})}
    

    The above method owes a lot to the answer by Shay Levy to this question.

    To include only the default properties and their values, preceded by a string:

    PS C:\> $events | format-list | %{"NEW RECORD" ; $_}
    

    To include all properties and their values, preceded by a string but retain the default formatting:

    PS C:\> $events | select-object * | format-list | %{"NEW RECORD"; $_}