Author Posts

August 25, 2015 at 6:36 am

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

August 25, 2015 at 6:48 am

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.

August 25, 2015 at 7:19 am

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

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

is being referenced as @distin, in your Update command

August 25, 2015 at 7:45 am

$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,

August 25, 2015 at 10:28 pm

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

August 25, 2015 at 10:32 pm

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

August 25, 2015 at 10:39 pm

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