locked
ForEach-Object not getting items, $_ is the collection RRS feed

  • Question

  • First I run this line:

    ([adsi]'WinNT://MyComputer').psbase.Properties

    cool, it returns:

    PropertyName                                      Value                                                                                    Capacity                                            Count
    ------------                                      -----                                                                                    --------                                            -----
    OperatingSystem                                   Windows NT                                                                                      4                                                1
    OperatingSystemVersion                            6.1                                                                                             4                                                1
    Owner                                             [redacted]                                                                                           4                                                1
    Division                                          Microsoft                                                                                       4                                                1
    ProcessorCount                                    Multiprocessor Free                                                                             4                                                1
    Processor                                         Intel64 Family 6 Model 42 Stepping 7                                                            4                                                1
    Name                                              [redacted]                                                                                            4                                                1

    now I want to do something with those objects...

    ([adsi]'WinNT://MyComputer').psbase.Properties | % {$_.Value}

    The above line returns nothing BECAUSE...

    ([adsi]'WinNT://MyComputer').psbase.Properties | % {$_.GetType()}

    tells me that $_ is System.DirectoryServices.PropertyCollection... What? Why not some DirectoryEntryProperty object or something? Why the collection itself? Is it a bug? Is it that PowerShell can't handle that this collection implements non-generic IDictionary, ICollection and IEnumerable? I mean $_ SHOULD be the item, not the collection through which I'm enumerating, right?

    I'm loosing my mind because of this. Please help.

    Sunday, July 15, 2012 11:01 PM

Answers

  • This code will "unpack" the properties, and populate an array of psObjects, which can be easily manipulated:

    $results = @()
    $props = ([adsi]'WinNT://Grant-PC').psbase.Properties
    $propnames = $props.propertynames
    foreach ($prop in $propnames) {
        $results += New-Object psObject -Property @{'Property'=$prop;'Value'=($props.item($prop) | Out-String).trim()}
        }
    $results | select property, value


    Grant Ward, a.k.a. Bigteddy

    • Proposed as answer by Bigteddy Wednesday, July 18, 2012 2:47 PM
    • Marked as answer by Yan Li_ Monday, July 23, 2012 2:20 AM
    Tuesday, July 17, 2012 9:43 AM

All replies

  • You can get to the values like this:

    ([adsi]'WinNT://Grant-PC').psbase.properties.values


    Grant Ward, a.k.a. Bigteddy

    Monday, July 16, 2012 4:44 AM
  • Hi,

    Run:

    ([adsi]'WinNT://MyComputer').psbase

    We will find that properties is a collection property which has seven items including:

    OperatingSystem
    OperatingSystemVersion
    Owner
    Division
    ProcessorCount
    Processor
    Name

    Run:

    ([adsi]'WinNT://MyComputer').psbase.Properties|%{$_.values}
    Or
    ([adsi]'WinNT://MyComputer').psbase.Properties.values

    They have the same result, because the object is only one, not multy.

    Regards,

    Yan Li


    Yan Li

    TechNet Community Support

    Monday, July 16, 2012 7:07 AM
  • What I want to do is have a collection of adsi object 'flattened' to have these properties as it's own members.

    Is there a way to do that in a simple one-liner without creating helper functions?

    Besides what I want to know is why
    ([adsi]'WinNT://MyComputer').PSBase.Properties | % {$_.GetType()}
    shows
    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     False    PropertyCollection                       System.Object

    while
    ([adsi]'WinNT://MyComputer').PSBase.Properties.GetEnumerator() | % {$_.GetType()}
    returns
    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     False    PropertyValueCollection                  System.Collections.CollectionBase
    True     False    PropertyValueCollection                  System.Collections.CollectionBase
    True     False    PropertyValueCollection                  System.Collections.CollectionBase
    True     False    PropertyValueCollection                  System.Collections.CollectionBase
    True     False    PropertyValueCollection                  System.Collections.CollectionBase
    True     False    PropertyValueCollection                  System.Collections.CollectionBase
    True     False    PropertyValueCollection                  System.Collections.CollectionBase

    Shouldn't ForEach-Object use GetEnumerator() ?

    Tuesday, July 17, 2012 8:20 AM
  • In this example:

    ([adsi]'WinNT://MyComputer').PSBase.Properties | % {$_.GetType()}

    ...you are just testing one object, even though you send it through a foreach-object.  Notice the type is PropertyCollection.  When calling the Enumerator, each of the values is passed to Gettype(), so you get 7 lines output.  Notice that this type is different, it is a PropertyValueCollection.

    The problem that you are encountering is that although it seems like you should get an array of seven properties, but really you get  just one object.


    Grant Ward, a.k.a. Bigteddy


    • Edited by Bigteddy Tuesday, July 17, 2012 9:15 AM
    Tuesday, July 17, 2012 9:13 AM
  • This code will "unpack" the properties, and populate an array of psObjects, which can be easily manipulated:

    $results = @()
    $props = ([adsi]'WinNT://Grant-PC').psbase.Properties
    $propnames = $props.propertynames
    foreach ($prop in $propnames) {
        $results += New-Object psObject -Property @{'Property'=$prop;'Value'=($props.item($prop) | Out-String).trim()}
        }
    $results | select property, value


    Grant Ward, a.k.a. Bigteddy

    • Proposed as answer by Bigteddy Wednesday, July 18, 2012 2:47 PM
    • Marked as answer by Yan Li_ Monday, July 23, 2012 2:20 AM
    Tuesday, July 17, 2012 9:43 AM