Function returning an array - not working why ?

function PopulateArrAD
{
      $ArrLocal = [System.Collections.ArrayList]@()

      $ArrLocal.Add(("StreetAddress",(GetItemFromAdUser $strUser "StreetAddress")))
      $ArrLocal.Add(("PostalCode",(GetItemFromAdUser $strUser "PostalCode")))
      $ArrLocal.Add(("City",(GetItemFromAdUser $strUser "City")))
      $ArrLocal.Add(("TelephoneNumber" ,(GetItemFromAdUser $strUser "TelephoneNumber")))
      $ArrLocal.Add(("Fax",(GetItemFromAdUser $strUser "Fax")))
      $ArrLocal.Add(("State", (GetItemFromAdUser $strUser "State")))
      $ArrLocal.Add(("ADOU", (GetOuUser $strUser)))
      $ArrLocal.Add(("SiteCode", (GetCustomAttribute $strUser "ExtensionAttribute1")))
      $ArrLocal.Add(("City", (GetItemFromAdUser $strUser "City")))
      $ArrLocal.Add(("Title", (GetItemFromAdUser $strUser "Title")))
      $ArrLocal.Add(("Department", (GetItemFromAdUser $strUser "Department")))
      $ArrLocal.Add(("Manager", (GetItemFromAdUser $strUser "Manager")))
      $ArrLocal.Add(("Contrat_Nb",(GetCustomAttribute $strUser "ExtensionAttribute6")))
$ArrLocal
Write-Host $ArrLocal[10][1]
Write-Host $ArrLocal[11][0]
}

This function is working well. inside the function  $ArrLocal[10][1]  return well the city and $ArrLocal[11][0] return well "Manager".


BUT, this is not working well

Function ManageArrAD()
{
      $ArrAD = [System.Collections.ArrayList]@()
        $ArrAD = PopulateArrAD
      Write-Host $ArrAD[10][1] DOES NOT RETURN CIty but 11
      Write-Host $ArrAD[11][0] return Runtime error...
}

Question : How to handle this ? How to have into a var of same type as created in PopulateArrAD into ManageArrAD ?

Thanks
François VDCIcT service DeskAsked:
Who is Participating?
 
oBdACommented:
Question : How to handle this ?
First thing on how to handle this: do yourself a favor and stop thinking in VBScript. Just don't apply any convention valid for VBScript or regular programming languages to PowerShell. Took me a while to get used to it, too.
* Don't use Hungarian Notation. There are several hundred (if not thousands) different object types in PowerShell. There's just no point.
* Use Pascal Casing for functions and variables.
* Use the <Verb>-<Noun> syntax for function names, and only use verbs found in "Get-Verb". More at "Approved Verbs for Windows PowerShell Commands", https://msdn.microsoft.com/en-us/library/ms714428.aspx
* When calling cmdlets/functions in a script, always use named arguments, not positional ones.
* When defining parameters for a function, use the same names as other cmdlets. For example, when expecting a file path to open, use "$Path" (as in Get-Content, Import-Csv, ...), not something like "$FilePath" or "$FileToProcess".
* Don't use multidimensional arrays where an object array will do.
* You didn't use any, so just in case: do not use aliases (gc, dir, %, ?, ...) in scripts. They're fine in the command line for quick one-liners, but never in a script.

PowerShell doesn't work like common programming languages. Everything written to stdout inside a function will be returned to the caller. Always and everywhere. The "Return <Whatever>" command is basically just a short form to write <Whatever> to stdout, and then leave the function. It is not a required command inside a function, like in a VBScript function.
As Qlemo already noted, every call to the Add() method will return the index of the added element, and since you're not voiding it, the indexes will end up in the pipeline and be passed to the caller.
And the problem with the multidimensional arrays becomes abundantly clear in the script example you posted:
You claim "inside the function  $ArrLocal[10][1]  return well the city and $ArrLocal[11][0] return well "Manager"" - can't be.
Index 11 for the Manager is (currently) correct, but "City" is not at index 10 (anymore), it's in the array even twice, but at index 2 and 8, not 10.
And where does $strUser in PopulateArrAD come from? You're encapsulating the property retrieval into a function, so don't rely on global variables. Pass it as argument.

Now that I've thrown all of this at you (sorry), here's a version that will return a proper custom object with the properties retrieved from AD.
There's a multitude of possibilities to create custom objects; this uses one introduced in PS 3.0, where the properties are taken from a simple hash table. Fast and easy.
You should still change the name of the functions you're calling to <Verb>-<Noun> syntax, and use named parameters for the call, and give the function formerly known as "ManageArrAD" a proper name. It's not managing an array.
Function Get-ADUserInformation {
Param(
	$Username
)
	[pscustomobject]@{
		"StreetAddress" =	GetItemFromAdUser $Username "StreetAddress"
		"PostalCode" =		GetItemFromAdUser $Username "PostalCode"
		"City" =			GetItemFromAdUser $Username "City"
		"TelephoneNumber" =	GetItemFromAdUser $Username "TelephoneNumber"
		"Fax" =				GetItemFromAdUser $Username "Fax"
		"State" =			GetItemFromAdUser $Username "State"
		"ADOU" =			GetOuUser $Username
		"SiteCode" =		GetCustomAttribute $Username "ExtensionAttribute1"
		"Title" =			GetItemFromAdUser $Username "Title"
		"Department" =		GetItemFromAdUser $Username "Department"
		"Manager" =			GetItemFromAdUser $Username "Manager"
		"Contrat_Nb" =		GetCustomAttribute $Username "ExtensionAttribute6"
	}
}

Function Set-Whatever {
Param(
	$Username
)
	$ADUser = Get-ADUserInformation -Username $Username
	Write-Host $ADUser.City
	Write-Host $ADUser.Manager
}

Open in new window

0
 
Dorababu MSenior Software EngineerCommented:
Try by returning in your first function and give a try
return $ArrLocal

Open in new window


function firstFunction {
    $array = 1,2,3
    return $array
}

function secondFunction {
    $array = firstFunction
    Write-Host $array
}

Open in new window

0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Using return $ArrLocal is correct. Why? Because $ArrLocal.Add returns the index of the newly added item. If you do not explicitly return something, everything dumped into the pipeline is returned.

Of course this a very bad way to keep object information. You really should work with custom objects and their properties, or hash tables if you like that more. Arrays are for uniform information with usually unknown amount of "rows".
Using something like $usr.City or $usr['City'] is certainly much more appealing.
0
On-Demand: Securing Your Wi-Fi for Summer Travel

Traveling this summer?Check out our on-demand webinar to learn about the importance of Wi-Fi security and 3 easy measures you can start taking immediately to protect your private data while using public Wi-Fi. Follow us today to learn more!

 
François VDCIcT service DeskAuthor Commented:
same behavior... not working.
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
If I convert your second array elements to strings containing the command
function PopulateArrAD
{
      $ArrLocal = [System.Collections.ArrayList]@() 

      [void] $ArrLocal.Add(("StreetAddress",'(GetItemFromAdUser $strUser "StreetAddress")'))
      [void] $ArrLocal.Add(("PostalCode",'(GetItemFromAdUser $strUser "PostalCode")'))
      [void] $ArrLocal.Add(("City",'(GetItemFromAdUser $strUser "City")'))
      [void] $ArrLocal.Add(("TelephoneNumber" ,'(GetItemFromAdUser $strUser "TelephoneNumber")'))
      [void] $ArrLocal.Add(("Fax",'(GetItemFromAdUser $strUser "Fax")'))
      [void] $ArrLocal.Add(("State", '(GetItemFromAdUser $strUser "State")'))
      [void] $ArrLocal.Add(("ADOU", '(GetOuUser $strUser)'))
      [void] $ArrLocal.Add(("SiteCode", '(GetCustomAttribute $strUser "ExtensionAttribute1")'))
      [void] $ArrLocal.Add(("City", '(GetItemFromAdUser $strUser "City")'))
      [void] $ArrLocal.Add(("Title", '(GetItemFromAdUser $strUser "Title")'))
      [void] $ArrLocal.Add(("Department", '(GetItemFromAdUser $strUser "Department")'))
      [void] $ArrLocal.Add(("Manager", '(GetItemFromAdUser $strUser "Manager")'))
      [void] $ArrLocal.Add(("Contrat_Nb",'(GetCustomAttribute $strUser "ExtensionAttribute6")'))
$ArrLocal
Write-Host $ArrLocal[10][1] 
Write-Host $ArrLocal[11][0]
}

Open in new window

your ManageArrAD function returns
(GetItemFromAdUser $strUser "Department")
Manager
 DOES NOT RETURN CIty but 11
11 return Runtime error...

Open in new window

with the first two lines coming from PopulateArrAD with correct results (as you stated), but the ManageArrAD output is different from what you told.
But nevertheless you are somehow correct, our recommendations do not change the output. I've explained why, but thought the intermediate results of the Add method would be dismissed if using return. That's not the case. You need to dismiss each unwanted return value. That is:
function PopulateArrAD
{
      $ArrLocal = [System.Collections.ArrayList]@() 

      $ArrLocal.Add(("StreetAddress",(GetItemFromAdUser $strUser "StreetAddress")))
      $ArrLocal.Add(("PostalCode",(GetItemFromAdUser $strUser "PostalCode")))
      $ArrLocal.Add(("City",(GetItemFromAdUser $strUser "City")))
      $ArrLocal.Add(("TelephoneNumber" ,(GetItemFromAdUser $strUser "TelephoneNumber")))
      $ArrLocal.Add(("Fax",(GetItemFromAdUser $strUser "Fax")))
      $ArrLocal.Add(("State", (GetItemFromAdUser $strUser "State")))
      $ArrLocal.Add(("ADOU", (GetOuUser $strUser)))
      $ArrLocal.Add(("SiteCode", (GetCustomAttribute $strUser "ExtensionAttribute1")))
      $ArrLocal.Add(("City", (GetItemFromAdUser $strUser "City")))
      $ArrLocal.Add(("Title", (GetItemFromAdUser $strUser "Title")))
      $ArrLocal.Add(("Department", (GetItemFromAdUser $strUser "Department")))
      $ArrLocal.Add(("Manager", (GetItemFromAdUser $strUser "Manager")))
      $ArrLocal.Add(("Contrat_Nb",(GetCustomAttribute $strUser "ExtensionAttribute6")))
Write-Host $ArrLocal[10][1] 
Write-Host $ArrLocal[11][0]
     return $ArrLocal
}

Open in new window

0
 
François VDCIcT service DeskAuthor Commented:
vey impressive and ... right... still thinking on vbscript.....
tks for this very valuable feedback !
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.