select -property and -expandProperty together

This topic contains 0 replies, has 1 voice, and was last updated by  Forums Archives 5 years, 10 months ago.

  • Author
    Posts
  • #5260

    by nohandle at 2012-11-05 01:24:06

    Hi,
    user on Powershell com forum asked why is the original object modified when using select -property and -expandProperty . At first I thought there must be an error in the source code but I rewrote it and was able to replicate the issue. I was trying to figure it out, but it seems like a bug to me (I cannot find anyone mentioning it or reporting it on Microsoft Connect.)

    Is there any explanation for that behavior or should I report it?

    Here is an example:
    $hash = @{category="Users";objects=""}
    $category = New-Object psobject -Property $hash

    Function Create-UserObject ([string]$userName)
    {
    New-object psObject -Property @{name=$userName}
    }
    $category.objects= (create-userObject "john"),(create-userObject "jane")
    cls
    "`n:::original Object:::"
    $category | fc

    $category | Select-Object -Property "WhyOhWhy" -ExpandProperty objects > $null
    "`n:::modified object:::"
    ($category.objects[0]).whyOhWhy = "this works"
    $category | fc

    ($category.objects[0]).nonExistingProperty = "this will produce error"

    :::original Object:::

    class PSCustomObject
    {
    objects =
    [
    class PSCustomObject
    {
    name = john
    }
    class PSCustomObject
    {
    name = jane
    }
    ]

    category = Users
    }

    :::modified object:::

    class PSCustomObject
    {
    objects =
    [
    class PSCustomObject
    {
    name = john
    WhyOhWhy = this works
    }
    class PSCustomObject
    {
    name = jane
    WhyOhWhy =
    }
    ]

    category = Users
    }

    Exception setting "nonExistingProperty": "Property 'nonExistingProperty' cannot be found o
    n this object; make sure it exists and is settable."
    At line:19 char:1
    + ($category.objects[0]).nonExistingProperty = "this will produce error"
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting

    by DonJ at 2012-11-05 12:10:41

    I'm not entirely sure I'm following what you're after. But, let me try.

    By design, Select-Object won't barf if you ask it to select a property which doesn't exist. This can be confusing, but it's intentional, and not a bug. Select-Object will implicitly create the "missing" property. That's why, after Selecting the property, you can subsequently access it. That's what Select-Object does.

    However, that behavior doesn't extend globally throughout the shell – it's a behavior of Select-Object (and Where-Object, and a couple of others). When you try to do $object.BadProperty, you get an error because PowerShell looks for a Get method on $object, doesn't find one, and barfs. Again, that's expected behavior.

    So it isn't a bug, but it's darned confusing. I get this all the time when I teach classes:

    Get-Process | Select -Property Nmae,ID,PM,VM

    Notice the typo in Name? Select won't complain – it just creates a blank column called "Nmae." Confusing. But, once you realize what's happening, it's less likely to trip you up.

    by nohandle at 2012-11-05 13:36:40

    Hi Don thanks for the reply. I am aware of the standard behavior of the Select-Object cmdlet.
    The problem is that in this case the collection of custom objects is add a property and the change is not just output to pipeline, the original object is modified.

    If I have object $user that has property name and surname and I do Select name, surname, telephone the output is psobject that has all these three properties. If the output is not captured (assigned to property for example) it is lost. the $user still has only two properties (name, surname).

    In the described case I have custom (parent) object. one of its properties is a collection of custom objects. if the parent object is pipelined to select, and both property (name, surname, telephone) and expandproperty ($collection.objects) are specified then the not existing property "telephone" is STORED to the collection in the parent object.

You must be logged in to reply to this topic.