Function Returning object intead of value

This topic contains 6 replies, has 4 voices, and was last updated by Profile photo of Max Kozlov Max Kozlov 1 year, 11 months ago.

  • Author
    Posts
  • #28953
    Profile photo of Arestas
    Arestas
    Participant

    Hello all,
    Having a problem returning values from a function. Could realy use some help cause i cant manage to get this working.

    Function Process-ADObj($owner)
    {
    $ADObj = 0
    $aclType = $ACL_TYPE_LOCAL

    $Domain,$owner = $owner -split "\\",2

    $SamAccountName = Get-ADUser -identity $owner -Properties SamAccountName |select SamAccountName -ExpandProperty SamAccountname
    $UserPrincipalName = get-ADUser -identity $owner -Properties UserPrincipalName |select UserPrincipalName -ExpandProperty UserPrincipalName
    $DistinguishedName = get-ADUser -identity $owner -Properties DistinguishedName |select DistinguishedName -ExpandProperty DistinguishedName

    $sqlCmd = $sqlConn.CreateCommand()
    $sqlCmd.Parameters.AddWithValue("@login" ,$samAccountname)
    $sqlCmd.Parameters.AddWithValue("@domain" ,$GLOBALDOMAIN)
    $sqlCmd.Parameters.AddWithValue("@name" ,$DistinguishedName)
    $sqlCmd.Parameters.AddWithValue("@update" ,$date)
    $sqlCmd.Parameters.AddWithValue("@pincipal",$UserPrincipalName)
    $sqlCmd.CommandText = "INSERT INTO [USERINFO] ([LOGIN],[DOMAIN],[NAME],[UPDATE],[PINCIPAL]) VALUES (@user,@domain,@distin,@update,@pincipal)";
    $sqlCmd.ExecuteNonQuery();

    $ADObj = SqlSelectInteger "SELECT USER_ID FROM USERINFO where USER_LOGIN ='$owner'";
    #write-host $ADObj (IT writes the Id Correclty)

    return $aclType, $ADObj
    }

    $Ownerreturn = Process-ADObj($Owner)
    $folderOwner = $Ownerreturn[1]

    But instead of returning the ID stored in $ADObj it returns object information

  • #28954
    Profile photo of Don Jones
    Don Jones
    Keymaster

    The return keyword in PowerShell is misleading – honestly, I avoid it, because it doesn't work at all like most programming languages.

    Return simply executes a Write-Output, and then exits. That's important, because it tells us that the only way to output from a function is via the pipeline, which is what Write-Output writes to. The pipeline works best when it contains only a single kind of object. Without special handling, putting multiple, different objects into the pipeline can be difficult to work with.

    In your case, you are writing a comma-delimited list of objects, which PowerShell implicitly interprets as an array. That array contains two different objects. That right there violates PowerShell's native patterns – not that it's "wrong," but it isn't how the shell is intended to work. What you probably *should* do is create a new object of type PSObject, and then attach properties to it for whatever information you need to output. That way you're outputting ONE object, rather than an array.

    I'd like to offer some additional advice. Here, you're wasting a lot of processing and time:

    $SamAccountName = Get-ADUser -identity $owner -Properties SamAccountName |select SamAccountName -ExpandProperty SamAccountname
    $UserPrincipalName = get-ADUser -identity $owner -Properties UserPrincipalName |select UserPrincipalName -ExpandProperty UserPrincipalName
    $DistinguishedName = get-ADUser -identity $owner -Properties DistinguishedName |select DistinguishedName -ExpandProperty DistinguishedName
    

    Because you're executing the same query three times. Consider:

    $user = Get-ADUser -identity $owner -Properties SamAccountName,UserPrincipalName,DistinguishedName
    $sam = $user.SamAccountName
    $upn = $user.UserPrincipalName
    $dn = $user.DistinguishedName
    

    Executing the query only once, and getting everything you want all at once.

    This:

    $ADObj = SqlSelectInteger "SELECT USER_ID FROM USERINFO where USER_LOGIN ='$owner'";
    #write-host $ADObj (IT writes the Id Correclty)
    

    Is where I have to rely on you. When you say "it writes the ID correctly," do you mean it outputs a small table having a single "ID" column, with the ID underneath? That means it's outputting an object, which has a single property named ID. What you might want to output instead of $ADObj is $ADObj.ID – in other words, only outputting the ID property, rather than the entire object.

    $props = @{'ID'=$ADObj.ID
      'ACLType'=$acltype
    }
    $out = New-Object -Type PSObject -Prop $props
    Write-Output $out
    

    Hope that helps.

  • #28957
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    Another quick note, you have the wrong variable name used:

    $sqlCmd.Parameters.AddWithValue("@name" ,$DistinguishedName)
    

    is being referenced as @distin, in your Update command

  • #28958
    Profile photo of Arestas
    Arestas
    Participant

    $ADObj = SqlSelectInteger "SELECT USER_ID FROM USERINFO where USER_LOGIN ='$owner'";
    #write-host $ADObj (IT writes the Id Correclty)

    Here it just query the DB and returns an ID. For example 5 (its not an object).

    When i try to read it after i call the function

    #calling function
    $Ownerreturn = Process-ADObj($Owner)

    #reading function Output
    $folderOwner = $Ownerreturn[1]

    it returns me the object in position 1 from the :
    $sqlCmd.CommandText = "INSERT INTO [USERINFO] ([LOGIN],[DOMAIN],[NAME],[UPDATE],[PINCIPAL]) VALUES (@user,@domain,@distin,@update,@pincipal)";

    that is @domain...

    In debug mode i see return $aclType, $ADObj passing the correct IDs but when it returns to the function it is returning an object...

    Problem is that i want to return $aclType, $ADObj and it somehow keeps returning the object

    Thanks for the tip on how to get all the info from the AD at once.

    Rob Simmers, its just a "typo" in the script is ok. Tks anyway.

    Regards,

  • #28975
    Profile photo of Max Kozlov
    Max Kozlov
    Participant

    As already said Don, you use return and this mislead you in the wrong direction.

    Your $sqlCmd.ExecuteNonQuery();
    as written in https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery(v=vs.110).aspx already return int value to you
    and object you need will be in position 2, not 1.
    $folderOwner = $Ownerreturn[2]

    p.s. I can't guarantee that position will be 2 and not 3 or more 🙂 I just quickly overview you code

    start making PS objects, not arrays and you won't mix output from .net with your own values at least

  • #28976
    Profile photo of Max Kozlov
    Max Kozlov
    Participant

    btw it must be written in some powershell bible ;-), that any output inside powershell functions is equivalent to c# "yield return"

  • #28977
    Profile photo of Max Kozlov
    Max Kozlov
    Participant

    found it.
    Parameters.AddWithValue also doesn't [void]

You must be logged in to reply to this topic.