Craig Celeste
Craig Celeste

Reputation: 12653

Add PowerShell function to the parent scope

I have some PowerShell helper functions in a file. I'd like to make them available to the scope of another file that I am writing, but not pollute the global scope.

Helpers.ps1

function global:Helper1
{
    # this function pollutes the global scope
}
function Helper2
{
    # this function is not visible to the Utility.ps1 file.
}

Utilities.ps1

&{
    ./Helpers.ps1
    function global:Utility1
    {
        Helper1
    }
    function global:Utility2
    {
        Helper2
    }
}

I found this question: How do I dynamically create functions that are accessible in a parent scope? but the answers discuss adding functions to the global scope. What I really want to do is make the Helper functions from one PS1 file available to a calling PS1 file, without polluting the global scope with the helpers.

I want to avoid defining the functions as variables, which is possible with Set-Variable and the -Scope parameter. The closest I've seen (from the linked thread) is using Set-Item in the function: drive.

Any help would be appreciated!

Edit: here is the solution expanded from Mike's answer

Helpers.ps1

function Helper
{
}

Utilities.ps1

&{
    function global:Utility
    {
        . ./Helpers.ps1
        Helper1
    }
}

Using the dot-source syntax to load Helpers.ps1 puts it's contents in the scope of the Utility function. Putting Helpers.ps1 outside the Utility function causes it to be in the &{...} scope but that scope ends once the functions are defined.

Upvotes: 5

Views: 5767

Answers (2)

CosmosKey
CosmosKey

Reputation: 1317

You can use this snippet in the Utilities.ps1 file. What we do is get all current functions then we dot source the helpers. We then make a diff of the before and after functions. From the diff we recreate the functions in the global scope.

$beforeFunctions = ls function:
. .\helpers.ps1
$afterFunctions = ls function:
$functionDiff = @(Compare-Object $beforeFunctions $afterFunctions)
foreach($diffEntry in $functionDiff){
    $func = $diffEntry.InputObject
    invoke-expression "function global:$($func.Name) { $($func.definition) }"
}

Upvotes: 7

Mike Shepard
Mike Shepard

Reputation: 18166

If you dot-source a .ps1 file in a function, the definitions that are in the ps1 file are not global, unless the function was itself dot-sourced.

Upvotes: 5

Related Questions