Powershell

Dynamic Parameters discoverability

In my previous post About Dynamic Parameters I forgot to mention an important point about discoverability.

When I come across a new script or module, usually the first thing I do is to check its syntax to get an idea of the kind of arguments it can accept, like this:

PS > Get-Command -Syntax -Name Get-AzResource

Get-AzResource [-Name <string>] [-ResourceType <string>] [-ODataQuery <string>] [-ResourceGroupName <string>] [-TagName <string>] [-TagValue <string>] [-ExpandProperties] [-ApiVersion <string>] [-Pre] [-DefaultProfile <IAzureContextContainer>] [<CommonParameters>]

Get-AzResource -ResourceId <string> [-ODataQuery <string>] [-ExpandProperties] [-ApiVersion <string>] [-Pre] [-DefaultProfile <IAzureContextContainer>] [<CommonParameters>]

Get-AzResource -Tag <hashtable> [-Name <string>] [-ResourceType <string>] [-ODataQuery <string>] [-ResourceGroupName <string>] [-ExpandProperties] [-ApiVersion <string>] [-Pre] [-DefaultProfile <IAzureContextContainer>] [<CommonParameters>]

This concise syntax tells me for example that all parameters in the first ParameterSet are optional (each parameter and its type is enclosed in square brackets), meaning I can simply run Get-AzResource on an Azure Subscription and get the list of all available Resources. The second ParameterSet on the other hand requires at least the ResourceId parameter since it is not enclosed in square brackets; the other parameters are optional though, so I may or may not use them. And so on.

Get-Help too shows the script’s syntax, along with additional help details if available:

PS /Users/carlo/Temp> Get-Help -Name Get-AzResource

NAME
    Get-AzResource

SYNOPSIS
    Gets resources.


SYNTAX
    Get-AzResource [-ApiVersion <System.String>] [-DefaultProfile
    <Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer>] [-ExpandProperties] [-Name <System.String>]
    [-ODataQuery <System.String>] [-Pre] [-ResourceGroupName <System.String>] [-ResourceType <System.String>] [-TagName <System.String>] [-TagValue
    <System.String>] [<CommonParameters>]

    Get-AzResource [-ApiVersion <System.String>] [-DefaultProfile
    <Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer>] [-ExpandProperties] [-Name <System.String>]
    [-ODataQuery <System.String>] [-Pre] [-ResourceGroupName <System.String>] [-ResourceType <System.String>] -Tag <System.Collections.Hashtable>
    [<CommonParameters>]

    Get-AzResource [-ApiVersion <System.String>] [-DefaultProfile
    <Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer>] [-ExpandProperties] [-ODataQuery <System.String>]
    [-Pre] -ResourceId <System.String> [<CommonParameters>]


DESCRIPTION
    The Get-AzResource cmdlet gets Azure resources.


RELATED LINKS
    Online Version: https://docs.microsoft.com/en-us/powershell/module/az.resources/get-azresource
    Find-AzResource
    Move-AzResource
    New-AzResource
    Remove-AzResource
    Set-AzResource

REMARKS
    To see the examples, type: "get-help Get-AzResource -examples".
    For more information, type: "get-help Get-AzResource -detailed".
    For technical information, type: "get-help Get-AzResource -full".
    For online help, type: "get-help Get-AzResource -online"

Dynamic Parameters are special though:

PS /Users/carlo/Temp> Get-Command -Syntax -Name ./dynamicParameter.ps1

dynamicParameter.ps1 [[-FolderPath] <string> ] [<CommonParameters>]

As you can see, FolderPath is displayed as an optional parameter (expected) but there is no sign of FileName which we know will be created at runtime. That is the core of the matter: FileName does not appear in the param declaration, therefore Powershell does not see this as a valid parameter unless the script is executed and the corresponding object structure gets created in memory.

Does this mean Dynamic Parameters are left in the wild to run undiscovered? ? Not quite. ?

From the online help Dynamic Parameters:

Dynamic parameters can be very useful, but use them only when necessary, because they can be difficult for users to discover. To find a dynamic parameter, the user must be in the provider path, use the ArgumentList parameter of the Get-Commandcmdlet, or use the Path parameter of Get-Help.

ArgumentList is the key. According to the Get-Command help:

Specifies an array of arguments. This cmdlet gets information about a cmdlet or function when it is used with the specified parameters (“arguments”). The alias for ArgumentList is Args.
To detect dynamic parameters that are available only when certain other parameters are used, set the value of ArgumentListto the parameters that trigger the dynamic parameters.
To detect the dynamic parameters that a provider adds to a cmdlet, set the value of the ArgumentList parameter to a path in the provider drive, such as WSMan:, HKLM:, or Cert:. When the command is a PowerShell provider cmdlet, enter only one path in each command. The provider cmdlets return only the dynamic parameters for the first path the value of ArgumentList. For information about the provider cmdlets, see about_Providers.

So, armed with this knowledge let’s give another try to Get-Command and my test script:

PS /Users/carlo/Temp> Get-Command ./dynamicParameter.ps1 -ArgumentList / -Syntax

dynamicParameter.ps1 [[-FolderPath] ] [-FileName <string[]>] [<CommonParameters>]

I am passing “/” to ArgumentList since that is the Name for the FileSystem PSProvider. Run Get-PSProvider to get the list of available Providers.

Sure enough, FileName is now displayed as second optional parameter to this script ?. 


Imagination will often carry us to worlds that never were. But without it we go nowhere. – Carl Sagan 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.