Function to change variable values

The below function works as intended when called within the script but doesn’t when called from the command line outside of it. Let me explain.

This is my function:

Function Select-Environment {
[CmdletBinding()]
Param (
[Parameter(ParameterSetName = 'Tier1')]
[switch]$Tier1,

[Parameter(ParameterSetName = 'Tier2')]
[switch]$Tier2
)

switch ($PSCmdlet.ParameterSetName) {
'Tier1' {
$Script:ComTierServers = "Server1","Server2","Server3"
$Script:AppTierServers = "Server4","Server5","Server6"
$Script:WebTierServers = "Server7","Server8","Server9"
}
'Tier2' {
$Script:ComTierServers = "Server10","Serve11","Server13"
$Script:AppTierServers = "Server14","Server15","Server16"
$Script:WebTierServers = "Server17","Server18","Server19"
}
}
}

Currently I’m running the following command within the script to select which variable set to use Select-Environment -Tier1. The idea behind this is that I need to use the same variable names to run against some other functions I have in place like the following:

Check-Services -Tier $ComTierServers -Service "blah|deblah" -AppPool "blah|deblah"

I need to be able to isolate and call the individual tier variables with different criteria like above rather than the same criteria against the whole tier.

As mentioned, this works fine when called within the script but when I run the following externally it complains that the ComputerName is null or empty and so doesn’t work: . .\powershellscript.ps1 -Select-Environment -Tier1

I guess I need to change the function to require a value rather than just a switch?

Hopefully that makes more sense and gives an idea of what I’m trying to do.

I found this thread which says that I need to define a parameter block for the script which accepts (at a minimum) the same parameters I want to pass to the function which makes sense: https://powershell.org/forums/topic/calling-a-function-with-parameters/

I’ve added the following to the script, outside of the function:

[cmdletBinding()]
param (
[switch]$Tier1,
[switch]$Tier2
)

However, this doesn’t appear to make any difference to calling this outside the script still.

I’ve changed my approach in the function:

[CmdletBinding()]
Param (
[string]$Env
)

Function Select-Environment {
[CmdletBinding()]
Param (
[string]$Env
)
 
If ($Env -eq "Tier1") {
$Script:ComTierServers = "Server1","Server2","Server3"
$Script:AppTierServers = "Server4","Server5","Server6"
$Script:WebTierServers = "Server7","Server8","Server9"
}
If ($Env -eq "Tier2") {
$Script:ComTierServers = "Server10","Serve11","Server13"
$Script:AppTierServers = "Server14","Server15","Server16"
$Script:WebTierServers = "Server17","Server18","Server19"
}
}

This now works by using Select-Environment -Env Tier1 from within the script, returning the correct set of servers but still can’t get this to work outside the script using: . .\powershellscript.ps1; Select-Environment -Env Tier1

What am I missing?

Switch isn’t really the best choice for this type of parameter. Take a look at Get-Verb, which will show you the verbs recommended by cmdlets\functions with context, which is why it is a recommendation to use ‘Get’ rather than ‘Select’. Using a ValidateSet you can specify the allowed values and then set the parameter to mandatory to ensure that someone has to define that parameter when calling the function. Setting Global variables is almost always bad. A function typically returns a PSObject, not set a global variable. The only time I set a global variable in a function is when a session is created with an API and it would have to be passed to every other function, so it’s persisted globally. Here is another approach:

Function Get-Environment {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)]
        [ValidateSet(1,2)]
        [int]$Tier
    )
    begin{}
    process {
        $result = switch ($Tier) {
            1 {
                [PSCustomObject]@{
                    ComTierServers = "Server1","Server2","Server3"
                    AppTierServers = "Server4","Server5","Server6"
                    WebTierServers = "Server7","Server8","Server9"
                }

            }
            2 {
                [PSCustomObject]@{
                    ComTierServers = "Server10","Serve11","Server13"
                    AppTierServers = "Server14","Server15","Server16"
                    WebTierServers = "Server17","Server18","Server19"
                }
            }
        }
    }
    end{$result}
}

$environment = Get-Environment -Tier 2

#Reference the variable
$environment.ComTierServers

Output:

PS C:\Users\rasim> $environment


ComTierServers                AppTierServers                 WebTierServers
--------------                --------------                 --------------
{Server10, Serve11, Server13} {Server14, Server15, Server16} {Server17, Server18, Server19}

PS C:\Users\rasim> $environment.AppTierServers

Server14
Server15
Server16
PS C:\Users\rasim> 

Hi Rob,

I’ve actually moved away from a switch statement and opted for IF statements that compare a string value from a command line param set outside the function now. This works as expected now but thanks for your input anyway.

I can see how your function is working but your having to specify the -Tier value in the script still whereas I’m trying to do this from the command line while calling the script.

If you want to pass it as a parameter, it just needs to be added to the script:

Param (
    [Parameter(Mandatory=$true)]
    [ValidateSet(1,2)]
    [int]$Tier
)

Function Get-Environment {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)]
        [ValidateSet(1,2)]
        [int]$Tier
    )
    begin{}
    process {
        $result = switch ($Tier) {
            1 {
                [PSCustomObject]@{
                    ComTierServers = "Server1","Server2","Server3"
                    AppTierServers = "Server4","Server5","Server6"
                    WebTierServers = "Server7","Server8","Server9"
                }

            }
            2 {
                [PSCustomObject]@{
                    ComTierServers = "Server10","Serve11","Server13"
                    AppTierServers = "Server14","Server15","Server16"
                    WebTierServers = "Server17","Server18","Server19"
                }
            }
        }
    }
    end{$result}
}

$environment = Get-Environment -Tier $Tier

Then the parameter can be passed externally:

./myscript.ps1 -Tier 1

Thanks for that. Very handy to have another (probably better) solution to what I ended up using. I appreciate the help.