Parameter alias not working in pipeline

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Erik Sundin Erik Sundin 1 year, 3 months ago.

  • Author
    Posts
  • #32826
    Profile photo of Erik Sundin
    Erik Sundin
    Participant

    Hello,

    I´m fairly new to scripting/programming in general (including Powershell), trying to move away from being a GUI-based technician. While doing my best to get my first cmdlets to work I came across an unexpected behavior, I hope someone can give me an explanation for this. I made two nearly identical functions to illustrate my problem:

     function Test-Name
    {    
        Param
        (
            [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory=$true)]
            [Alias("Name")] 
            $ComputerName
        )
    
        $ComputerName
    }
    
    function Test-Name2
    {    
        Param
        (
            [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory=$true)]
            [Alias("ComputerName")] 
            $Name
        )
    
        $Name
    }  

    And then I tested a few things:

    PS U:\> Get-ADComputer Test | Test-Name
    Test-Name : Cannot bind argument to parameter 'ComputerName' because it is null.
    At line:1 char:23
    + Get-ADComputer Test | Test-Name
    + ~~~~~~~~~
    + CategoryInfo : InvalidData: (CN=Test,CN=Computers,DC=test,DC=ing:PSObject) [Test-Name], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Test-Name

    PS U:\> Get-ADComputer Test | Select-Object Name | Test-Name
    Test

    PS U:\> Get-ADComputer Test | Test-Name2
    Test

    PS U:\> (Get-ADComputer Test).gettype()

    IsPublic IsSerial Name BaseType
    ——– ——– —- ——–
    True False ADComputer Microsoft.ActiveDirectory.Management.ADAccount

    PS U:\> (Get-ADComputer Test | Select-Object *).gettype()

    IsPublic IsSerial Name BaseType
    ——– ——– —- ——–
    True False PSCustomObject System.Object

    I red in a post, that I unfortunately can´t find right now, that objects from ActiveDirectory module cmdlets acts weird in the pipeline and that using Select-Object was a way around it. I can see that the object types are different, but why does it work when the parameter name match the property name from the pipeline?

  • #32828
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Meet the ActiveDirectory module, one of the most annoying things ever produced for PowerShell. 🙂 The objects that come out of those commands behave very oddly. As you mentioned, piping the AD commands to "Select-Object *" first is a viable workaround, because it changes the type of the objects that you're piping into other functions.

    The reason for this is that the AD objects, when you try to _read_ any property, will automatically create a property on themselves of that name with no value. (They're essentially both an object and a hashtable, in terms of their interface). When you pipe in an object to your function with an aliased parameter, this is what would normally happen:

    – PowerShell checks the object for a property matching the actual parameter name "ComputerName"
    – That's not found, so instead it starts checking the aliases. It finds a property "Name", and binds that.

    But when you're using these goofy AD objects, instead it goes like this:

    – PowerShell checks the object for a property of type ComputerName. It didn't exist before this happened, but now suddenly the object has a "ComputerName" property with no value. PowerShell binds this to your parameter, and never bothers checking the aliases.

  • #32830
    Profile photo of Erik Sundin
    Erik Sundin
    Participant

    Thank you for your time and thorough explanation, my mind is at ease once again 🙂

You must be logged in to reply to this topic.