Home > other >  Allow function to run in parent scope?
Allow function to run in parent scope?

Time:10-06

Pardon the title wording if it's a bit confusing. . .

I have a very simple script that just dot sources a .ps1 file but, since it runs inside a function, it doesn't get loaded into the parent scope which is my ultimate objective.

function Reload-ToolBox {
    Param (
        [Parameter(Mandatory=$false)]
        [ValidateSet('TechToolBox',
                     'NetworkToolBox','All')]
        [string[]]$Name = 'TechToolBox'
    )
    Begin 
    {
        $ToolBoxes = @{
            TechToolBox     = "\\path\to\my\ps1.ps1"
            NetworkToolBox  = "\\path\to\my\ps2.ps1"
        }
        if ($($PSBoundParameters.Values) -contains 'All') {
            $null = $ToolBoxes.Add('All',$($ToolBoxes.Values | Out-String -Stream))
        }

        $DotSource = {
            foreach ($PS1Path in $ToolBoxes.$ToolBox)
            {
                . $PS1Path
            }
        }
    }
    Process 
    {
        foreach ($ToolBox in $Name) 
        {
            
            Switch -Regex ($ToolBoxes.Keys) 
            {
                {$_ -match "^$ToolBox$"} { & $DotSource } 
            }

        }

    }
    End { }
}

Question:

  • How would I be able to load the ps1 being called in the function, into the parent scope?

google no helped:(

CodePudding user response:

  • In order for dot-sourcing performed inside your function to also take effect for the function's caller, you must dot-source the function call itself (. Reload-TooBox ...)

  • Unfortunately, there is no way to make this dot-sourcing automatic, but you can at least check whether the function was called via dot-sourcing, and report an error with instructions otherwise.

Here's a streamlined version of your function that includes this check:

function Reload-ToolBox {
  [CmdletBinding()]
  Param (
    [ValidateSet('TechToolBox', 'NetworkToolBox', 'All')]
    [string[]] $Name = 'TechToolBox'
  )
  Begin {
    # Makes sure that *this* function is also being dot-sourced, as only
    # then does dot-sourcing of scripts from inside it also take effect
    # for the caller.
    if ($MyInvocation.CommandOrigin -ne 'Internal') { # Not dot-sourced?
      throw "You must DOT-SOURCE calls to this function: . $((Get-PSCallStack)[1].Position.Text)"
    }

    $ToolBoxes = @{
      TechToolBox    = "\\path\to\my\ps1.ps1"
      NetworkToolBox = "\\path\to\my\ps2.ps1"
    }
    $ToolBoxes.All = @($ToolBoxes.Values)

    if ($Name -Contains 'All') { $Name = 'All' }

  }

  Process {

    foreach ($n in $Name)  {
      foreach ($script in $ToolBoxes.$n) {
        Write-Verbose "Dot-sourcing $script..."
        . $script
      }
    }

  }
}
  • Related