Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hierarchical Parameter Scripting #13746

Closed
iRon7 opened this issue Oct 5, 2020 · 15 comments
Closed

Hierarchical Parameter Scripting #13746

iRon7 opened this issue Oct 5, 2020 · 15 comments
Labels
Issue-Enhancement the issue is more of a feature request than a bug Resolution-No Activity Issue has had no activity for 6 months or more WG-Engine core PowerShell engine, interpreter, and runtime

Comments

@iRon7
Copy link

iRon7 commented Oct 5, 2020

Summary of the new feature/enhancement

To complement Feature Idea: Revisiting and extending the ParameterSet Experience #12818
I would like to raise two dissenting ideas:

1. Reverse the set/parameter containment

Personally, I think that the current parameter notation is inside out
Currently, parameters contain parameters sets (each Parameter holds multiple attributes with a ParametersSetName)
but it should be visa versa: a parameter set should contain parameters.
By turning this around, you might also support (recursive) parameter subsets.
With all respect, adding additional configuration items (like groups and ParameterMutexName) might help to reduce the redundancy but eventually adds up to the complicity when combining them with the existing configuration items.
I even believe that naming parameters sets is inessential if using subsets.

2. Use PowerShell to build parameter sets.

Developers creating cmdlets are already quiet known with PowerShell and need to learn a complete different parameter syntax to get them straight for their functions.
Apart from the fact that you might reduce the redundancy and complexity by using variables and subsets, there is also another advantage in moving to PowerShell scripting: I guess that changes to the current parameter notification (like e.g. groups) will require an update of the PowerShell engine therefor engineers who like to supply some backwards compatibility (with e.g. Windows PowerShell) for their cmdlets/functions might be reluctant to use any new parameter features provided through the current parameter notation. A PowerShell framework using the DynamicParam section, might only require installing a module to supply backwards compatibility in customer scripts.

Proposed technical implementation details

Let's assume a Draw-Shape cmdlet that requires the following parameter (set) constrains:

  • There are 3 possible shapes:
    • Circle (which requires one Radius parameter)
    • Rectangle (which requires a Width and a Height parameter)
    • Triangle (which requires 3 - Side1, Side2 and Side3 - parameters)
  • Each shape requires either of the (mutually exclusive) parameters below:
    • Transparency
    • Opacity
  • And a optional color (default black) by either using
    • a RGB scheme
      • Red
      • Green
      • Blue
    • or a HSL scheme
      • Hue
      • Sat
      • Lum

Using the current parameter notation, this requires:

a lot of parameter definitions...
function Draw-Shape {
    [CmdletBinding()] param(
        [Parameter(Position = 0, ParameterSetName = 'CircleTransparencyRGB', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'CircleTransparencyHSL', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'CircleOpacityRGB', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'CircleOpacityHSL', Mandatory = $True)]
        [int]$Radius,
        
        [Parameter(Position = 0, ParameterSetName = 'SquareTransparencyRGB', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'SquareTransparencyHSL', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'SquareOpacityRGB', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'SquareOpacityHSL', Mandatory = $True)]
        [int]$Width,

        [Parameter(Position = 1, ParameterSetName = 'SquareTransparencyRGB', Mandatory = $True)]
        [Parameter(Position = 1, ParameterSetName = 'SquareTransparencyHSL', Mandatory = $True)]
        [Parameter(Position = 1, ParameterSetName = 'SquareOpacityRGB', Mandatory = $True)]
        [Parameter(Position = 1, ParameterSetName = 'SquareOpacityHSL', Mandatory = $True)]
        [int]$Height,

        [Parameter(Position = 0, ParameterSetName = 'TriangleTransparencyRGB', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'TriangleTransparencyHSL', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'TriangleOpacityRGB', Mandatory = $True)]
        [Parameter(Position = 0, ParameterSetName = 'TriangleOpacityHSL', Mandatory = $True)]
        [int]$Side1,

        [Parameter(Position = 1, ParameterSetName = 'TriangleTransparencyRGB', Mandatory = $True)]
        [Parameter(Position = 1, ParameterSetName = 'TriangleTransparencyHSL', Mandatory = $True)]
        [Parameter(Position = 1, ParameterSetName = 'TriangleOpacityRGB', Mandatory = $True)]
        [Parameter(Position = 1, ParameterSetName = 'TriangleOpacityHSL', Mandatory = $True)]
        [int]$Side2,

        [Parameter(Position = 2, ParameterSetName = 'TriangleTransparencyRGB', Mandatory = $True)]
        [Parameter(Position = 2, ParameterSetName = 'TriangleTransparencyHSL', Mandatory = $True)]
        [Parameter(Position = 2, ParameterSetName = 'TriangleOpacityRGB', Mandatory = $True)]
        [Parameter(Position = 2, ParameterSetName = 'TriangleOpacityHSL', Mandatory = $True)]
        [int]$Side3,
        
        [Parameter(ParameterSetName = 'CircleTransparencyRGB',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'SquareTransparencyRGB',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'TriangleTransparencyRGB', Mandatory = $True)]
        [Parameter(ParameterSetName = 'CircleTransparencyHSL',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'SquareTransparencyHSL',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'TriangleTransparencyHSL', Mandatory = $True)]
        [int]$Transparency,

        [Parameter(ParameterSetName = 'CircleOpacityRGB',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'SquareOpacityRGB',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'TriangleOpacityRGB', Mandatory = $True)]
        [Parameter(ParameterSetName = 'CircleOpacityHSL',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'SquareOpacityHSL',   Mandatory = $True)]
        [Parameter(ParameterSetName = 'TriangleOpacityHSL', Mandatory = $True)]
        [int]$Opacity,

        [Parameter(ParameterSetName = 'CircleTransparencyRGB')]
        [Parameter(ParameterSetName = 'SquareTransparencyRGB')]
        [Parameter(ParameterSetName = 'TriangleTransparencyRGB')]
        [Parameter(ParameterSetName = 'CircleOpacityRGB')]
        [Parameter(ParameterSetName = 'SquareOpacityRGB')]
        [Parameter(ParameterSetName = 'TriangleOpacityRGB')]
        [int]$Red,

        [Parameter(ParameterSetName = 'CircleTransparencyRGB')]
        [Parameter(ParameterSetName = 'SquareTransparencyRGB')]
        [Parameter(ParameterSetName = 'TriangleTransparencyRGB')]
        [Parameter(ParameterSetName = 'CircleOpacityRGB')]
        [Parameter(ParameterSetName = 'SquareOpacityRGB')]
        [Parameter(ParameterSetName = 'TriangleOpacityRGB')]
        [int]$Green,

        [Parameter(ParameterSetName = 'CircleTransparencyRGB')]
        [Parameter(ParameterSetName = 'SquareTransparencyRGB')]
        [Parameter(ParameterSetName = 'TriangleTransparencyRGB')]
        [Parameter(ParameterSetName = 'CircleOpacityRGB')]
        [Parameter(ParameterSetName = 'SquareOpacityRGB')]
        [Parameter(ParameterSetName = 'TriangleOpacityRGB')]
        [int]$Blue,

        [Parameter(ParameterSetName = 'CircleTransparencyHSL')]
        [Parameter(ParameterSetName = 'SquareTransparencyHSL')]
        [Parameter(ParameterSetName = 'TriangleTransparencyHSL')]
        [Parameter(ParameterSetName = 'CircleOpacityHSL')]
        [Parameter(ParameterSetName = 'SquareOpacityHSL')]
        [Parameter(ParameterSetName = 'TriangleOpacityHSL')]
        [int]$Hue,

        [Parameter(ParameterSetName = 'CircleTransparencyHSL')]
        [Parameter(ParameterSetName = 'SquareTransparencyHSL')]
        [Parameter(ParameterSetName = 'TriangleTransparencyHSL')]
        [Parameter(ParameterSetName = 'CircleOpacityHSL')]
        [Parameter(ParameterSetName = 'SquareOpacityHSL')]
        [Parameter(ParameterSetName = 'TriangleOpacityHSL')]
        [int]$Sat,

        [Parameter(ParameterSetName = 'CircleTransparencyHSL')]
        [Parameter(ParameterSetName = 'SquareTransparencyHSL')]
        [Parameter(ParameterSetName = 'TriangleTransparencyHSL')]
        [Parameter(ParameterSetName = 'CircleOpacityHSL')]
        [Parameter(ParameterSetName = 'SquareOpacityHSL')]
        [Parameter(ParameterSetName = 'TriangleOpacityHSL')]
        [int]$Lum
    )
}

Using this prototype ParameterFunctions module, it requires the following knowledge. Sorry, there is no readme yet, but you can use the -? option to get the syntax and the description below:

There are 2 functions included in the module to create parameters and parameter-sets:

  1. New-Parameter (alias New-Param, or NPM)
    This function has 5 main parameters:
  • [int]$Position
  • [type]$Type
  • [string]$Name
  • [object]$Default
  • [switch]$Mandatory

Besides has a few parameters like HelpMessage to set certain parameter attributes.
It has no ParameterSetName option!

  1. New-ParameterSet (alias New-ParamSet, or NPS)
    Which has two parameters:
  • [RuntimeDefinedParameterDictionary[]]$ParameterSets
  • [String]$SetName (Optional)

There can only be one root (default) parameter set (or a single parameter which is quiet pointless).
Each set might contain multiple (optional or mandatory) parameters or multiple (recursive) parameter sets.

Syntax

The basic syntax notation:

[x]

Optional parameter. The command runs whether or not you enter optional parameters.

function FMO {
    [CmdletBinding()] param()
    DynamicParam {
        New-Param 0 ([string]) x
    }
}

[x|y]

Select between optional parameters.

function FMO {
    [CmdletBinding()] param()
    DynamicParam {
        New-ParamSet @(
            New-Param 0 ([string]) x
            New-Param 1 ([string]) y
        )
    }
}

<x>

Required option. If you omit a required option, the command line program returns an error message.

function Test {
    [CmdletBinding()] param()
    DynamicParam {
        New-Param 0 ([string]) x -Mandatory
    }
}

<x|y>

Select between required options. For the command to run, you must select from the listed options. If you omit a required option, the command line program returns an error message.

function Test {
    [CmdletBinding()] param()
    DynamicParam {
        New-ParamSet @(
            New-ParamSet @(
                New-Param ([string]) x -Mandatory
            )
            New-ParamSet @(
                New-Param ([string]) y -Mandatory
            )
        )
    }
}

Further steps to come to the final result below you can find in the Parameters.Test.ps1:

function Draw-Shape {
    [CmdletBinding()] param()
    DynamicParam {

        # Define the optional  RGB and HSL subsets
        $Color = @(
            New-ParamSet @(
                New-Param ([int]) Red
                New-Param ([int]) Green
                New-Param ([int]) Blue
            )
            New-ParamSet @(
                New-Param ([int]) Hue
                New-Param ([int]) Sat
                New-Param ([int]) Lum
            )
        )

        # Define the optional mutually exclusive Transparency/Opacity subsets
        $Tint = @(
            New-ParamSet @(
                New-Param ([int]) Transparency -Mandatory
                $Color
            )
            New-ParamSet @(
                New-Param ([int]) Opacity -Mandatory
                $Color
            )
        )

        # Create a (single) main set
        New-ParamSet @(
            New-ParamSet @(
                New-Param 0 ([int]) Radius -Mandatory
                $Tint
            )
            New-ParamSet @(
                New-Param 0 ([int]) Width  -Mandatory
                New-Param 1 ([int]) Height -Mandatory
                $Tint
            )
            New-ParamSet @(
                New-Param 0 ([int]) Side1 -Mandatory
                New-Param 1 ([int]) Side2 -Mandatory
                New-Param 2 ([int]) Side3 -Mandatory
                $Tint
            )
        )
    }
}

Draw-Shape -?

NAME
    Draw-Shape

SYNTAX
    Draw-Shape [-Radius] <int> -Transparency <int> [-Red <int>] [-Green <int>] [-Blue <int>] [<CommonParameters>]

    Draw-Shape [-Radius] <int> -Opacity <int> [-Red <int>] [-Green <int>] [-Blue <int>] [<CommonParameters>]

    Draw-Shape [-Width] <int> [-Height] <int> -Transparency <int> [-Red <int>] [-Green <int>] [-Blue <int>] [<CommonParameters>]

    Draw-Shape [-Width] <int> [-Height] <int> -Opacity <int> [-Red <int>] [-Green <int>] [-Blue <int>] [<CommonParameters>]

    Draw-Shape [-Side1] <int> [-Side2] <int> [-Side3] <int> -Transparency <int> [-Red <int>] [-Green <int>] [-Blue <int>] [<CommonParameters>]

    Draw-Shape [-Side1] <int> [-Side2] <int> [-Side3] <int> -Opacity <int> [-Red <int>] [-Green <int>] [-Blue <int>] [<CommonParameters>]

    Draw-Shape [-Radius] <int> -Transparency <int> [-Hue <int>] [-Sat <int>] [-Lum <int>] [<CommonParameters>]

    Draw-Shape [-Radius] <int> -Opacity <int> [-Hue <int>] [-Sat <int>] [-Lum <int>] [<CommonParameters>]

    Draw-Shape [-Width] <int> [-Height] <int> -Transparency <int> [-Hue <int>] [-Sat <int>] [-Lum <int>] [<CommonParameters>]

    Draw-Shape [-Width] <int> [-Height] <int> -Opacity <int> [-Hue <int>] [-Sat <int>] [-Lum <int>] [<CommonParameters>]

    Draw-Shape [-Side1] <int> [-Side2] <int> [-Side3] <int> -Transparency <int> [-Hue <int>] [-Sat <int>] [-Lum <int>] [<CommonParameters>]

    Draw-Shape [-Side1] <int> [-Side2] <int> [-Side3] <int> -Opacity <int> [-Hue <int>] [-Sat <int>] [-Lum <int>] [<CommonParameters>]

Caveats

  • It concerns a prototype and there might be quiet some bugs a limitation but I think it might eventually replace the current parameter notation
  • Consider a (default) parameter Provider (I am lacking the C# knowledge to set this up 😌)
  • It might be slower than the current parameter notation (consider a -Static option which caches the RuntimeDefinedParameterDictionary)
  • Default value is not work (yet)
  • Dynamic parameters are not automatically put in variables, workaround:
foreach ($Name in $PSBoundParameters.get_keys()) {
    if (!(Test-Path variable:$Name)) { Set-Variable -Name $Name -Value $PSBoundParameters[$Name] }
}
@iRon7 iRon7 added the Issue-Enhancement the issue is more of a feature request than a bug label Oct 5, 2020
@iSazonov
Copy link
Collaborator

iSazonov commented Oct 5, 2020

In general I like the idea to enhance the parameter defining -

What about additional level? I mean an optional parameter could require some mandatory/optional subparameters.
And what about C# notation?

@iSazonov iSazonov added the WG-Engine core PowerShell engine, interpreter, and runtime label Oct 5, 2020
@vexx32
Copy link
Collaborator

vexx32 commented Oct 5, 2020

The main reason I'm unsure about this style of declaring params is that you have declare the same parameter multiple times if it happens to be in multiple sets. This creates a greater possibility of mistakes and more confusing UX if a parameter by the same name appears to behave multiple different ways depending on the other parameters specified with it.

I would love to see a rework of parameter declaration, but I don't think this is the right direction to go. 🤔

@ThomasNieto
Copy link
Contributor

ThomasNieto commented Oct 5, 2020

Looking at the command syntax it looks like this cmdlet is trying to do too much. A good rule of thumb that I've seen with PowerShell parameter set best practices is that if you're getting this many, maybe its time to create dedicated cmdlets. This many parameter sets is also confusing to the user as the syntax diagram is too complex.

For your example the cmdlet could be broken down into multiple cmdlets:

Draw-Shape gets broken down into three cmdlets:

  • Draw-Circle -Radius <int>
  • Draw-Rectangle -Height <int> -Width <int>
  • Draw-Triangle -Side1 <int> -Side2 <int> -Side3 <int>

Dedicated color cmdlets can be created to define either of the two color schemes. Then a parameter set can be added to Draw-* for the -RGBColor or -HSLColor or to be a common parameter. The same can be done with -Transparency and -Opacity.

  • New-RGBColor -Red <int> -Blue <int> -Red <int>
  • New-HSLColor -Hue <int> -Sat <int> -Lum <int>

This can take the 12 parameter sets down to just a couple by going this route. There was also an old RFC that defined mutually exclusive parameters without needing a new parameter set.

@iSazonov
Copy link
Collaborator

iSazonov commented Oct 6, 2020

I added more info in #12818.

@iRon7
Copy link
Author

iRon7 commented Oct 6, 2020

@vexx32 and @ThomasNieto, the 'Draw-Shape' is just an extreme example which two mutually exclusive parameter sets almost at the root of the main set.

The main reason I'm unsure about this style of declaring params is that you have declare the same parameter multiple times if it happens to be in multiple sets. This creates a greater possibility of mistakes and more confusing UX if a parameter by the same name appears to behave multiple different ways depending on the other parameters specified with it.

Yes, there are about 22 (sub)sets in the Draw-Shape example with a total of 58 parameters (where the current parameters notation has 14 parameters with 72 parameters-sets). As @iSazonov pointed out in #12818, my general objective is to use a syntax diagram which is similar to the (expanded) syntax displayed by the help. In the existing solution, you might limit some of the parameter-sets by using configuration items like DefaultParameterSetName but it is difficult to further reduce the redundancy of this rather flat design. This is mainly because the attributes that usually relate to the parameter (like position and mandatory) are contaminated with a ParameterSetName property that actually belongs to parameter-set. In the purposed design it is easy to script any redundancy using variables or loops:

Taking the parameter-set of the current Where-Object cmdlet for another example:

function WhereObject {
    [CmdletBinding()] param()
    DynamicParam {
        $MandatoryOperators = @(
            'CEQ', 'NE', 'CNE', 'GT', 'CGT', 'LT', 'CLT', 'GE', 'CGE', 'LE', 'CLE',
            'Like', 'CLike', 'NotLike', 'CNotLike', 'Match', 'CMatch', 'NotMatch', 'CNotMatch',
            'Contains', 'CContains', 'NotContains', 'CNotContains',
            'In', 'CIn', 'NotIn', 'CNotIn', 'Is', 'IsNot'
        )
        New-ParamSet @(
            New-ParamSet @(
                New-ParamSet @(
                    New-Param 0 ([scriptblock]) FilterScript -Mandatory
                    New-Param ([psobject]) InputObject
                )
            )
            New-ParamSet @(
                New-Param 0 ([string]) Property -Mandatory
                New-ParamSet @(
                    New-Param 1 ([object]) Value
                    New-Param ([switch]) EQ
                    New-Param ([psobject]) InputObject
                )
                foreach ($Operator in $MandatoryOperators) {
                    New-ParamSet @(
                        New-Param 1 ([object]) Value
                        New-Param ([switch]) $Operator -Mandatory
                        New-Param ([psobject]) InputObject
                    )
                }
            )
            New-ParamSet @(
                New-Param 0 ([string]) Property -Mandatory
                New-ParamSet @(
                    New-Param ([switch]) Not -Mandatory
                    New-Param ([psobject]) InputObject
                )
            )
        )
    }
}

@vexx32
Copy link
Collaborator

vexx32 commented Oct 6, 2020

Yeah, you can do that with dynamicparam but you wouldn't likely be able to do anything remotely similar if we had builtin syntax for this (good luck parsing that; it'd be insanely complicated to try to make that work in anything like a param block).

Also... just in general, dynamicparam tends to cause more problems that it solves, so IMO any design based on it is generally best avoided (even when prototyping other designs). YMMV I suppose, but I don't think this is an approachable angle for users.

@iRon7
Copy link
Author

iRon7 commented Oct 6, 2020

What about additional level? I mean an optional parameter could require some mandatory/optional subparameters.

I have updated the module (see also below the design definitions) which allows a for the intuitive dynamicparameter statement:

function Test {
    [CmdletBinding()] param()
    DynamicParam {
        New-ParamSet @(
            New-Param ([string]) Opt1
            New-ParamSet @(
                New-Param ([string]) Man1 -Mandatory
                New-Param ([string]) Opt2
            )
        )
    }
}

Test -?

SYNTAX
    Test -Man1 <string> [-Opt2 <string>] [-Opt1 <string>] [<CommonParameters>]
    Test [-Opt1 <string>] [<CommonParameters>]

And what about C# notation?

Unfortunately, I do not have enough C# experience to comment on this.

@iRon7
Copy link
Author

iRon7 commented Oct 6, 2020

@vexx32

you can do that with dynamicparam but you wouldn't likely be able to do anything remotely similar if we had builtin syntax for this.

Agree, it is not in the intention to align the current Param() notation with the purpose. Besides, as already noted, that would require an engine update where the dynamicparam purpose might only require a module which could even supply some downward compatibility with older (Windows) PowerShell versions.

dynamicparam tends to cause more problems that it solves

I don't think you can make a fair comparison (yet) between using the the current Param() notation and dynamicparam scripting because there are currently no functions, cmdlets, frameworks (or provider), type accelerators, guidance, etc. to support the developers in using the dynamicparam section. There are only a few .Net constructors (which you need to tie together) to work with. The issue is that the current parameter notation is far from DRY, very verbose and not as lean as you might expect. For this reason, I guess that there are a lot of developers (including myself) that often just lump all parameters together and throw an error from within input processing methods when comes to an incorrect parameter constrain.

@iSazonov
Copy link
Collaborator

iSazonov commented Oct 6, 2020

I was thinking of throwing an error if there is a mandatory parameter in the subset and not in the parent but didn't implement this yet

I'd expect symmetric behavior for all levels.

And what about C# notation?
Unfortunately, I do not have enough C# experience to comment on this.

Script and binary developers should get the same capabilities otherwise your work will be only partial research.

@iRon7
Copy link
Author

iRon7 commented Oct 6, 2020

I'd expect symmetric behavior for all levels.

That depends on the actual implementation. In this purpose, I trying to follow the syntax diagram¹, where subsets (...[...][...[...][...]]) are not just extensions of the parent set but exclusive optional sets or in case all subsets contain at least one mandatory parameter, they are considered mutually exclusive sets².

  1. Which the exception where it concerns the definition of a single parameter:
    • An optional parameter [MyParam] is created like: New-Param MyParam
    • A mandatory parameter MyParam is created like: New-Param MyParam -Mandatory

2) If it just concerns a single subset, all of the containing parameters are simply added to the parent parameters (unsure about this as you might as well put all the parameters simply in the parent set. I need to give this some more thoughts).

  1. If it just concerns a single subset:
    • if the parent set doesn't contain any mandatory parameters, both the parent and subset are optional (where all mandatory parameters in the subset are required if any of the other parameters in the subset is used)
    • If the parent set contains one or more mandatory parameters, the usage will be the same as when all parameters in the subset were directly put in the parent set.

See also below the design definitions and above reworked "What about additional level? I mean an optional parameter could require some mandatory/optional subparameters." answer to @iSazonov.

@iRon7
Copy link
Author

iRon7 commented Oct 9, 2020

I have updated the prototype module to better support optional parameters (see the updated answer to @iSazonov "an optional parameter could require some mandatory/optional subparameters" comment) which also results in a more symmetric behavior (see the updated answer to @vex32 "I'd expect symmetric behavior for all levels" comment).

(Sub)set design

Below is the description how the ParameterSetName of each parameter is set with respect to their (sub)set containers.

  • If there is no SetName supplied, the ParameterSetName is initially set to '0' (a string containing a zero).
  • The SetName is added to:
    • the ParameterSetName attribute of each optional parameter
    • the ParameterSetName attribute of each mandator parameter unless the set also contains subsets
  • In case of a subset, the ParameterSetName of the each attribute of each containing parameter is prefixed SetName (or '0', if no setname is supplied) separated by a dot '.'.
    • Any ParameterSetName parameter attribute in a subset that is already prefixed with a '0' (e.g. '0.1') will get a new unique index prefix (e.g. '1.1'). In the case of a named subset, the developer is responsible to supply unique names for each subset.

Note that with each subset iteration, the whole parameter set (including the containing parameter attributes) is cloned. This is to support parameter sets supplied in variable (which eventually require an unique ParameterSetName).

(Sub)set usage:

The basic idea of this purpose is to follow the standard parameter syntax diagram similar to the Help (-?) syntax output..

  • There is one exception where it concerns the definition of a single parameter:

    • An optional parameter [MyParam], is created like: New-Param MyParam
    • A mandatory parameter MyParam, is created like: New-Param MyParam -Mandatory
  • Every parameter subset is exclusive
    This means that a user can select a specific subset (and supply the contained mandatory parameters) but can't choose parameters out of different subsets

    • If the parent set and all subsets contain at least one mandatory parameter, the parameter subset is mutually exclusive
      This means that a user must choose one specific subset
    • If the parent set or one of the subsets contain only optional parameters the parameter subset is an exclusive choose
      This means that the user might choose one subset (or none of the subsets)
  • The user is required to supply both mandatory parameters of the selected subset and the mandatory parameters of its parent set.

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

2 similar comments
Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

@microsoft-github-policy-service microsoft-github-policy-service bot added Resolution-No Activity Issue has had no activity for 6 months or more labels Nov 16, 2023
Copy link
Contributor

This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement the issue is more of a feature request than a bug Resolution-No Activity Issue has had no activity for 6 months or more WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

No branches or pull requests

4 participants