'How to call a script with unknown parameters

I have a script that calls other scripts that other people manage. It's essentially a CI/CD script that gives users the ability to tap into the pipeline.

The issue I'm running into now is that I would like this calling script to implement a couple new parameters. However, the old scripts don't always implement those parameters.

If I call their script that doesn't implement the parameters, I get an error "A parameter cannot be found that matches parameter name 'newparameter'".

Is there a way to dynamically pass in a parameter so that it doesn't fail if the parameter doesn't exist? I don't mind if they don't implement it. It's a bonus parameter that they don't need to use.

Alternately, can I do something like a Get-Command for a custom .ps1 script, to get a list of accepted parameters? With that, I could confirm that a parameter is implemented before I pass it.



Solution 1:[1]

This might help you get started, you could use the Parser Class to get all functions and it's parameters from a script, this answer shows a minimal reproduction. I'll leave it to you to investigate further.

Given myScript.ps1 that has these 3 functions:

function ExampleFunc {
    param([int] $param1 = 123, [string] $param2)
}

function ExampleFunc2 {
    param([object] $param3, [switch] $param4)
}

function ExampleFunc3 ($param5, [hashtable] $param6 = @{foo = 'var'}) {

}

You can use the parser's ParseFile Method to get the AST, then you can use the .FindAll method to filter for all FunctionDefinitionAst.

using namespace System.Management.Automation.Language

$ast = [Parser]::ParseInput($myscript, [ref] $null, [ref] $null)
$ast.FindAll({ $args[0] -is [FunctionDefinitionAst] }, $true) | ForEach-Object {
    $out = [ordered]@{ Function = $_.Name }
    $_.FindAll({ $args[0] -is [ParameterAst] }, $true) | ForEach-Object {
        $out['ParameterName'] = $_.Name.VariablePath
        $out['Type']          = $_.StaticType
        $out['DefaultValue']  = $_.DefaultValue
        [pscustomobject] $out
    }
} | Format-Table

Above code would result in the following for myScript.ps1:

Function     ParameterName Type                                         DefaultValue
--------     ------------- ----                                         ------------
ExampleFunc  param1        System.Int32                                 123
ExampleFunc  param2        System.String
ExampleFunc2 param3        System.Object
ExampleFunc2 param4        System.Management.Automation.SwitchParameter
ExampleFunc3 param5        System.Object
ExampleFunc3 param6        System.Collections.Hashtable                 @{foo = 'var'}

The same could be accomplished using Get-Command too:

(Get-Command 'fullpath\to\myScript.ps1').ScriptBlock.Ast.FindAll({
    # same syntax as before

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1