Search code examples
powershellfunctionreturn-valueout-gridview

Powershell function return pscustomobject out-gridview show incorrectly results


This function:

    function Get-UserNameSIDfromAD {
        param(
            [string] $LoginName
        )
        
        [string] $domain
        [string] $username
    
        $domain, $username = $LoginName.split('\')
    
        $w32usracc = Get-CimInstance -ClassName win32_useraccount -Filter "Name='$username' and Domain='$domain'" | Select-Object -Property SID
    
        $res = [pscustomobject] @{
            ID      = 1
            SqlSID  = $w32usracc.SID
            Message = 'OK'
        }
    
        return $res
    }

    #Using the function and get the result in variable and show using out-gridview
    $val = Get-UserNameSIDfromAD -LoginName 'mydomain\user1'
    $val | out-gridview 

image of the output in powershell

Grid shows incorrectly the information, if run the code without function, the grid shows information correctly.

Please any advice, thank in advance.


Solution

  • Note that something like:

    # Does NOT declare a variable, outputs an empty string.
    [string] $domain
    

    is not a variable declaration.

    PowerShell has no concept of mere variable declarations (the only exceptions are parameter variables - see the relevant section of about_Functions).

    You can only "declare" a variable by implicitly creating it via assigning a value to it. (If the variable already exists, it will be updated.)

    In other words: it is the act of assigning a value that implicitly creates a variable, whether or not the LHS is prefixed with a type literal such as [string], which places a type constraint on the variable (e.g., [string] $domain = 42 ensures that the RHS is coerced to a string on assignment, both during the initial assignment and later ones; that is, the value that is stored is '42' in this case).

    By contrast, [string] $domain - without an assignment - is an expression that produces implicit output:

    • In this case, [string] acts as cast applied to the value of variable $domain
    • Since the variable doesn't exist yet, the stand-in value is $null. Converting $null to a string by virtue of the [string] cast yields the empty string ('')
    • Since the result of the expression is neither captured, sent to another command, nor redirected - it is implicitly sent to the success output stream and becomes part of the function's output ("return value"); see this answer for background information.

    Since you had two such expressions in your function, its output comprised two empty strings, followed by the argument passed to return, which explains the Out-GridView behavior you saw.


    The solution is to simply omit these expressions.

    You're later implicitly creating the variables with the following assignment statement:

    $domain, $username = $LoginName.Split('\')
    

    Given that the .Split() method returns an array of [string] elements and given that you're using a multi-assignment to assign the two resulting elements to individual variables, these variables will effectively be [string]-typed, given that a non-type-constrained variable stores any object assigned to it as-is.

    You may use a type constraint in this case:

    [string] $domain, [string] $username = $LoginName.Split('\')
    

    but there's no real benefit, unless you either want to explicitly signal the data type for conceptual reasons, or if you need to ensure that values used in later assignments to the same variables become [string]s, even if the values are of a different type.

    As an aside:

    • Another surprising aspect of variable assignments in PowerShell is that they implicitly create a local variable with the given name, even if a variable by that name already exists, but was defined in an ancestral scope - see this answer.