Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I want to have an array and add elements to it from different functions in my script. My example below illustrates where I might be misunderstanding something regarding scope. My understanding currently is that if an array is defined outside the function, and then elements are added inside the function, those elements should be available outside the function.

Function ListRunningServices
{
    $services+= Get-Service | ?{$_.Status -eq "Running"} | sort Name | select Name;
}

$services = @();
ListRunningServices;
$services;

What am I missing here? Perhaps my style is completely wrong.

share|improve this question

3 Answers 3

up vote 2 down vote accepted

The $services within the function block is scoped to the function. You can do something like the following instead:

Function ListRunningServices {
    Get-Service | ?{$_.Status -eq "Running"} | sort Name | select Name
}

$services = ListRunningServices
$services

Else, you may explicitly use global: to alter the scope:

Function ListRunningServices {
    $global:services = Get-Service | ?{$_.Status -eq "Running"} | sort Name | select Name
}

$services = @()
ListRunningServices
$services
share|improve this answer
    
I want to add to the services array from many different functions in my script. Which is the best practise way to do that? Use $global? –  Mark Allison Dec 11 '13 at 14:15
    
I would avoid using $global: if possible. Is there a reason you could not supply $services as a parameter to the other functions? It may help to see how you intend to interact with $services using the other functions. –  jscott Dec 11 '13 at 14:18
    
Just testing the $global solution you posted and it doesn't produce any output. –  Mark Allison Dec 11 '13 at 14:18
    
I've just copy/pasted the second example into a new PS session and it produces identical output to the first example. –  jscott Dec 11 '13 at 14:20
    
Interesting, if I paste into a Powershell window it works, but if I save into a file and then call the file as a script with .\file.ps1 I get no output. –  Mark Allison Dec 11 '13 at 14:27

$service in the scope of the function has nothing to do with the one outside the function.

Try :

Function ListRunningServices
{
    $services = @()
    $services+= Get-Service | ?{$_.Status -eq "Running"} | sort Name | select Name;
    return $services
}


$services = ListRunningServices
$services

Keeping most of your code you can use :

Function ListRunningServices
{
    $global:services+= Get-Service | ?{$_.Status -eq "Running"} | sort Name | select Name;
}

$services = @();
ListRunningServices;
$services;

You can read the full explanation in About_scope.

share|improve this answer

You can solve this with global variables, but using globals is genereally considered bad practice. If you use a generic collection type, like arraylist, instead of an array then you have an add() method that will update the collection in a parent scope without needing to explicitly scope it in the function:

Function ListRunningServices
{
    Get-Service | ?{$_.Status -eq "Running"} | sort Name | select Name |
     ForEach-Object {$services.add($_)}
}

$services = New-Object collections.arraylist
ListRunningServices
$services
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.