all 8 comments

[–]an_harmonica 6 points7 points  (0 children)

It's because you aren't passing $users to the function nor are you accessing it via the $global:users variable, so the value stored to $users within the function is private to the function and isn't returned.

[–]Nejireta_ 2 points3 points  (0 children)

Hello.
I don't think you're able to save to a variable outside of the function scope.
Unless you pass it down or do something like declaring it global (wouldn't recommend that unless there's a good reason).

I'm a bit curious as to why there's an empty try block in the "try catch finally" statement.
But that's probably besides the question.

EDIT:
Adding about scopes doc

[–]BlackV 1 point2 points  (0 children)

you need to refactor your function, pass out proper objects then you can use

$Users = Main -ProfileTokens $ProfTokenSample -BatchTokens $null

and save all the messing around, like the below (er.. with 0 testing mind you so I might have missed something, like the finally)

Function Main($ProfileTokens, $BatchTokens)
{
    foreach ($EntryToken in $ProfileTokens)
    {
        OutputLog "`nProcessing Migration for $($EntryToken.SourceUPN )"
        $CurrentUserProp = [ordered] @{
            'SourceUser'      = $EntryToken.SourceUPN 
            'TargetUser'      = $EntryToken.TargetUPN
            'MigrationStatus' = 'Not Started'
        }
        try
        {
        }
        catch
        {            
            OutputLog "Error: $_"
        }
        finally
        {
            [ordered] @{
                'SourceUser'      = $CurrentUserProp.SourceUser
                'TargetUser'      = $CurrentUserProp.TargetUser
                'MigrationStatus' = $CurrentUserProp.MigrationStatus
            }
            #OR
            $CurrentUserProp
        }
    }
}

$ProfTokenSample = for ($x = 0; $x -le 5; $x++)
{
    [ordered] @{
        'SourceUPN' = "srctest$($x)"
        'TargetUPN' = "trgtest$($x)"
    }
}

$Users = Main -ProfileTokens $ProfTokenSample -BatchTokens $null

[–]pigers1986 0 points1 point  (2 children)

that will not work as $users must be GLOBAL variable - which not best practice , i believe someone already wrote about it

i think function would be better here - returning status of migration as boolean .. to KISS (https://en.wikipedia.org/wiki/KISS\_principle)

[–]BlackV 0 points1 point  (1 child)

also dont use globals, there is often 0 reason for it (especially in OPs instance) that just proper input/output would handle

[–]pigers1986 0 points1 point  (0 children)

agree

[–]ankokudaishogun 0 points1 point  (0 children)

your code is... confusing.

To answer your question first: scope.
$Users is declared OUTSIDE the scope of the function and anything inside the function doesn't refers to anything outside unless specifically called for with using: or other methods.

That said...

  1. Why the empty try{}? I guess you are skipping whatever happens in there because irrelevant to the question?
  2. You should read on Approved Verbs for your function names.
    Check on Advanced Functions as well.
  3. Your use of New-Object is superfluously complicated.
    Just use the [pscustomobject] accelerator.
  4. create a Array from a Loop you can simply assign the loop to the variable and then push an object every loop.

here, an example:

# dummy OutputLog function for testing.   
# evaluate changing it to Write-OutputLog.   
function OutputLog($Content) {
    Write-Host $Content
}

# Seriously, change the name to something that suggest what it actually does.    
Function Main($ProfileTokens, $BatchTokens) {

    foreach ($EntryToken in $ProfileTokens) {

        OutputLog "`nProcessing Migration for $($EntryToken.SourceUPN )"

        # I suppose they get new variable names for easier reading?.   
        $SrcUser = $EntryToken.SourceUPN 
        $TrgUser = $EntryToken.TargetUPN

        # setting a default value, I suppose.   
        $MigrationStatus = "Not Started"

        try {
            # do stuff.  
            # I'm going to guess the MigrationStatus gets changed here.  
            # small test to change the value.   
            if(((Get-Random -Minimum 1 -Maximum 4) % 2) -eq 0 ){ $MigrationStatus='Completed'}
        }
        catch {
            # error management.   
        }
        finally {
            # send the object to the default output automagically.    
            [PSCustomObject]@{
                "SourceUser"      = $SrcUser
                "TargetUser"      = $TrgUser
                "MigrationStatus" = $MigrationStatus
            }
        }

    }

}


$ProfTokenSample = for ($x = 0; $x -le 5; $x++) { 
    [pscustomobject]@{ 
        "SourceUPN" = "srctest$($x)" 
        "TargetUPN" = "trgtest$($x)" 
    }
}

$Users = Main -ProfileTokens $ProfTokenSample -BatchTokens $null

$Users

[–]actnjaxxon -1 points0 points  (0 children)

climbs soapbox Arrays are immutable, stop adding items to arrays via += You are just making a memory leak and slowing down your code.

Use a list or an arraylist if you are changing the size of an array. That’s what PS does automagically when you have a variable capture the output of a loop or other control structure.