-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
This is a longstanding issue that @dlwyatt explained in detail in this 2014 blog post, and he has even published module PreferenceVariables with advanced function Get-CallerPreference to ease the pain, via a hard-coded list of preference variable names.
In short: A script module's functions do not see the preference-variable values set in the caller's context (except if that context happens to be the global one), which means that the caller's preferences are not honored.
Update: Since implicitly setting preference variables is PowerShell's method for propagating (inheriting) common parameters such as -WhatIf, such parameters are ultimately not honored in calls to script-module functions when passed via an advanced function - see #3106, #6556, and #6342. In short: the common-parameter inheritance mechanism is fundamentally broken for advanced functions across module scopes, which also affects standard modules such as NetSecurity and Microsoft.PowerShell.Archive .
-
From a user's perspective this is (a) surprising and (b), once understood, inconvenient.
Additionally, given that compiled cmdlets do not have the same problem, it is not easy to tell in advance which cmdlets / advanced functions are affected. In a similar vein, compiled cmdlets proxied via implicitly remoting modules also do not honor the caller's preferences. -
From a developer's perspective, it is (a) not easy to keep the problem in mind, and (b) addressing the problem requires a workaround that is currently quite cumbersome, exacerbated by currently not having a programmatic way identify all preference variables in order to copy their values to the callee's namespace - see Improving the discoverability of PowerShell variables #4394.
A simple demonstration of the problem:
# Define an in-memory module with a single function Foo() that provokes
# a non-terminating error.
$null = New-Module {
function Foo {
[CmdletBinding()] param()
# Provoke a non-terminating error.
Get-Item /Nosuch
}
}
# Set $ErrorActionPreference in the *script* context:
# Request that errors be silenced.
# (Note: Only if you defined this in the *global* context would the module see it.)
$ErrorActionPreference = 'SilentlyContinue'
# Because the module in which Foo() is defined doesn't see this script's
# variables, it cannot honor the $ErrorActionPreference setting, and
# the error message still prints.
FooDesired behavior
No output.
Current behavior
Get-Item : Cannot find path '/Nosuch' because it does not exist.
...
Environment data
PowerShell Core v6.0.0-beta.5 on macOS 10.12.6
PowerShell Core v6.0.0-beta.5 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.0-beta.5 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.483 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)