3

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 = '[email protected]'
)

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.

3 Answers 3

5

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.

Sign up to request clarification or add additional context in comments.

Comments

3

Unfortunately, the System.Management.Automation.ParameterMetadata instances reported by (Get-Command $script).Parameters do not include information about parameter default values.

Even if they did, you'd be faced with the problem of having to evaluate those values, given that they can be expandable strings or expressions.

If you do want to go that route, AdminOfThings's helpful answer shows you how to use PowerShell's own parser via the PowerShell SDK to get the default values.

Taking a step back: There are two ways of overcoming the inability to pass named arguments to Start-Job:

  • In PowerShell [Core] v6+, you can use postpositional &, the background operator, which allows you to use normal argument-passing:
# PSv6+ only: appending "&" to a pipeline turns it into a job.
$job = & $script -ScriptName foo -Path bar -MailTo [email protected] & 
  • In Windows PowerShell, you can use splatting as a workaround:
$job = Start-Job { $argsHash = $args[0]; & $using:script @argsHash } -Args @{
          ScriptName = 'foo'
          Path = 'bar';
          MailTo = '[email protected]' 
       }

Note: If you don't mind defining an auxiliary variable in the caller's scope, the alternative is:

$argsHash = 
@{
          ScriptName = 'foo'
          Path = 'bar';
          MailTo = '[email protected]' 
}

$job = Start-Job { & $using:script @using:argsHash }

Comments

0

If your script has comment-based help then Get-Help makes this easy.

(If not, just clone/edit the start of the file to add <# .notes #> like)

<# .notes #>
Param (

You want the .parameters.parameter property

$ (get-help ./myScripts.ps1).parameters.parameter | format-table name,defaultValue,required

name        defaultValue              required
----        ------------              --------
ScriptName                            true
Path                                  true
MailTo                                true
LogFolder   "\\$env:COMPUTERNAME\Log" false
ScriptAdmin [email protected]     false

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.