powershell

Is there a way in PowerShell to get the default value of a script parameter?


For launching scripts with Start-Job it is required to use the correct order of parameters within the array provided to -ArgumentList.

Consider this script:

# $script = c:\myScripts.ps1
Param (
    [Parameter(Mandatory)]
    [String]$ScriptName,
    [Parameter(Mandatory)]
    [String]$Path,
    [Parameter(Mandatory)]
    [String[]]$MailTo,
    [String]$LogFolder = "\\$env:COMPUTERNAME\Log",
    [String]$ScriptAdmin = 'gmail@hchucknoris.com'
)

We would like to know how it is possible to retrieve the default values set in $LogFolder and $ScriptAdmin?

My attempt where I can't seem to find it:

  $scriptParameters = (Get-Command $script).Parameters.GetEnumerator() | 
    Where-Object { $psBuildInParameters -notContains $_.Key }
    
    foreach ($p in $scriptParameters.GetEnumerator()) {
        'Name: {0} Type: {1} Mandatory: {2} DefaultValue: x' -f $p.Value.Name, $p.Value.ParameterType, $p.Value.Attributes.Mandatory
    }

If we have the default value we can use Start-Job more flexible in case we want to start a job with only the mandatory parameters and say $ScriptAdmini, but want to keep the value in $LogFolder and not blank it out with an empty string because we need to respect the order or the arguments.


Solution

  • You can use Ast parsing for this:

    $script = 'c:\myScripts.ps1'
    
    # Parse the script file for objects based on Ast type
    $parsed = [System.Management.Automation.Language.Parser]::ParseFile($script,[ref]$null,[ref]$null)
    
    # Extract only parameter ast objects
    $params = $parsed.FindAll({$args[0] -is [System.Management.Automation.Language.ParameterAst]},$true)
    
    $params | Foreach-Object {
        $name = $_.Name.VariablePath.ToString()
        $type = $_.StaticType.FullName
        # Convoluted because the property values themselves present strings rather than booleans where the values are $false or false 
        $mandatory = [bool]($_.Attributes | where {$_.NamedArguments.ArgumentName -eq 'Mandatory'} |% {$_.NamedArguments.Argument.SafeGetValue()})
        $DefaultValue = $_.DefaultValue.Value
        "Name: {0} Type: {1} Mandatory: {2} DefaultValue: {3}" -f $name,$type,$mandatory,$DefaultValue 
    }
    

    See System.Management.Automation.Language Namespace for other potential abstract syntax tree types.