tl;dr
The observed behavior is arguably a bug, present in Windows PowerShell and still as of PowerShell (Core) 7.3.1- see GitHub issue #3301.
To bypass the problem without side effects, use the following approach:
Param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String] $Type = 'Startup'
)
$MyInvocation.MyCommand.Parameters['Type'].Attributes.ValidValues
If there's a chance that Set-StrictMode -version 2
or higher is in effect or you're using PSv2, use
Param (
[ValidateSet('Startup', 'Shutdown', 'LogOn', 'LogOff')]
[String] $Type = 'Startup'
)
($MyInvocation.MyCommand.Parameters['Type'].Attributes |
Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] }).ValidValues
Optional background information
The problem is not related to the ISE per se, but to repeated dot-sourcing (the ISE just happens to run all scripts by dot-sourcing them).
Dot-sourcing runs scripts in the current scope (in the caller's scope itself, as opposed to in a child scope) and therefore typically modifies the current scope's state, such as by adding variables.
If you dot-source a script from an interactive session, you're effectively modifying the global session state, which is how definitions from the PS profile files are loaded, for instance.
In the case at hand, a dot-sourced invocation of the script effectively adds parameter variable $Type
to the invoking scope as a regular variable, as designed.
The bug surfaces when you dot-source the same script again (assume that the script in the question is present as ./script.ps1
:
After the first dot-sourced invocation, variable $Type
is still intact with respect to its attribute:
> . ./script.ps1; (Get-Variable Type).Attributes.Count
Startup
Shutdown
LogOn
LogOff
3 # PS implicitly adds 2 add'l attributes behind the scenes
When you dot-source again, the attributes are lost:
> . ./script.ps1; (Get-Variable Type).Attributes.Count
0