简体   繁体   中英

How to export a variable from a powershell module function?

Please, observe:

C:\> $TestVariable
C:\> $a
C:\> get-command Test-VariableExport

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Test-VariableExport                                0.0.0.1    Test


C:\> (get-command Test-VariableExport).ScriptBlock

    $script:TestVariable = Get-Date

C:\> Test-VariableExport
C:\> $TestVariable
C:\> function f() { $script:a = Get-Date }
C:\> f
C:\> $a

Monday, April 15, 2019 2:48:59 PM


C:\> f
C:\> $a

Monday, April 15, 2019 2:49:03 PM


C:\>

The same exact code when inside just a function works - the variable a is exported from the function to the outer scope. But when the function is part of a module as is the case of the Test-VariableExport function - the export does not work.

How can I make it work for a module function?

The behavior is all about scopes . The TLDR:

Sessions, modules, and nested prompts are self-contained environments, but they are not child scopes of the global scope in the session.

Basically, since modules are not a child scope, they can't set script scoped variables in the "parent" script scope.

Let's test scopes inside a Module:

sampleModule.psm1

Function Test-Local { $local:l = Get-Date }
Function Test-Script { $script:s = Get-Date }
Function Test-Global { $global:g = Get-Date }

#Only present desired functions
Export-ModuleMember -Function Test-Local, Test-Script, Test-Global

And running:

PS C:> Import-Module .\sampleModule.psm1

PS C:> Test-Local
PS C:> Test-Script
PS C:> Test-Global

PS C:> Write-Host "Local $l"
Local
PS C:> Write-Host "Script $s"
Script
PS C:> Write-Host "Global $g"
Global 04/15/2019 17:12:23

As we can see, since Modules run in their own self contained environment but are still a part of the global scope session, the only way to pass variables around in this use case is to use the $global scope.

Functions also act differently depending on how you run them as well. For ex. Take this sample script:

sample.ps1

Function Test-Local { $local:l = Get-Date }
Test-Local

Function Test-Script { $script:s = Get-Date }
Test-Script

Function Test-Global { $global:g = Get-Date }
Test-Global

And at the prompt let's run it in the script scope:

PS C:> .\sample.ps1

PS C:> Write-Host "Local $l"
Local
PS C:> Write-Host "Script $s"
Script
PS C:> Write-Host "Global $g"
Global 04/15/2019 17:14:56

Notice that you can't access the variable from the local or script scope. Let's restart PowerShell and now try the Call Operator ( & ):

PS C:> & .\sample.ps1

PS C:> Write-Host "Local $l"
Local
PS C:> Write-Host "Script $s"
Script
PS C:> Write-Host "Global $g"
Global 04/15/2019 17:22:07

Same results. Now let's run it in the local scope with the dot ( . ) operator:

PS C:> . .\sample.ps1

PS C:> Write-Host "Local $l"
Local
PS C:> Write-Host "Script $s"
Script 04/15/2019 17:24:16
PS C:> Write-Host "Global $g"
Global 04/15/2019 17:24:16

Now we can see the variable in the script scope is passed out. We won't ever see the Local scoped variables because they only are present in their current scope. eg in this example self contained to the inside of the function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM