PowerShell Module Privacy
Module privacy is the rule that only exported members are visible after import, while helpers and module variables stay inside the module. An exported function can still use the private pieces it needs.
A helper works inside its module
The exported function calls the private helper and reads the module variable. Both private pieces work from inside the module.
$module = Join-Path $PSScriptRoot "SafeBox.psm1"
Set-Content -Path $module -Value @'
$SecretWord = "hidden-word"
function Get-InnerCode { "inner-42" }
function Get-SafeMessage { "Safe: " + (Get-InnerCode) + " uses " + $SecretWord }
Export-ModuleMember -Function Get-SafeMessage
'@
Import-Module $module
Get-SafeMessageA helper stays hidden after import
The same helper cannot be called from the session after import. The catch block prints the real failure message.
$module = Join-Path $PSScriptRoot "SafeBox.psm1"
Set-Content -Path $module -Value @'
$SecretWord = "hidden-word"
function Get-InnerCode { "inner-42" }
function Get-SafeMessage { "Safe: " + (Get-InnerCode) + " uses " + $SecretWord }
Export-ModuleMember -Function Get-SafeMessage
'@
Import-Module $module
try { Get-InnerCode } catch { "Caught: " + $_.Exception.Message }A module variable stays inside the module
The session has no variable with the module variable name. The check prints False, which proves nothing leaked.
$module = Join-Path $PSScriptRoot "SafeBox.psm1"
Set-Content -Path $module -Value @'
$SecretWord = "hidden-word"
function Get-InnerCode { "inner-42" }
function Get-SafeMessage { "Safe: " + (Get-InnerCode) + " uses " + $SecretWord }
Export-ModuleMember -Function Get-SafeMessage
'@
Import-Module $module
$found = Get-Variable | Where-Object { $_.Name -eq "SecretWord" }
$found.Count -gt 0Example
$module = Join-Path $PSScriptRoot "SafeBox.psm1"
Set-Content -Path $module -Value @'
$SecretWord = "hidden-word"
function Get-InnerCode { "inner-42" }
function Get-SafeMessage { "Safe: " + (Get-InnerCode) + " uses " + $SecretWord }
Export-ModuleMember -Function Get-SafeMessage
'@
Import-Module $module
Get-SafeMessage
$found = Get-Variable | Where-Object { $_.Name -eq "SecretWord" }
$found.Count -gt 0Key points
- Private function: a function in a module that is not exported, so it cannot be called after import.
- Exported function: a function a module shares with the session, named in Export-ModuleMember.
- Inside access: an exported function can still call a private helper, because both live in the same module.
- Module variable: a variable set in a module file, which belongs to the module and not to the session.
- No leaking: importing a module does not add its private helpers or its variables to the session.
In this example, the script builds the module and imports it. It then calls the exported function, which uses the private helper and the module variable, and finally checks that the module variable did not leak into the session.
Note
a private helper called from outside the module fails, and try and catch can print that failure.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why does Get-InnerCode fail after importing SafeBox?