Crescendo icon indicating copy to clipboard operation
Crescendo copied to clipboard

Allow for Parameter values to be translated via key/value pair

Open EmeraldFlame opened this issue 4 years ago • 4 comments

I'd like to recommend adding the ability to translate the input given in the PowerShell command to a different value that actually gets used on the cmd side. This would allow crescendo modules to offer cleaner and clearer options to end users when the naming, notation, or syntax of the cmd tool isn't necessarily intuitive.

One such example I can think of where this would be helpful would be with 7-Zip's recursion switch.

In condensed form

-r- : Recursion off
-r  : Recursion on
-r0 : Recursion on, but only when matching the wild card searches

The syntax for this really isn't clear on what it does, you have to go out to the documentation site to understand it. For a crescendo command, I think it'd be preferable to do something like:

-recurse $false
-recurse $true
-recurse 'WildCardMatches'

But in this instance, instead of passing the actual value given, it'd be preferable to pass the accompanying value it translates to (ie, '-', $null, or '0').

As a very quick mock-up, I could see this being implemented in roughly the following manner

{
  "$schema": "https://aka.ms/PowerShell/Crescendo/Schemas/2021-11",
  "Commands": [
    {
      "Verb": "Compress",
      "Noun": "7ZArchive",
      "OriginalName": "C:/Program Files/7-Zip/7z.exe",
      "OriginalCommandElements": ["a"],
      "Platform": ["Windows"],
      "DefaultParameterSetName": "Default",
      "Parameters": [
        {
          "OriginalName": "",
          "Name": "DestinationPath",
          "ParameterType": "string",
          "ParameterSetName": ["Default"],
          "OriginalPosition": 1,
          "Mandatory": true,
          "Description": "Specify the path to create your archive"
        },
        {
          "OriginalName": "",
          "Name": "Path",
          "ParameterType": "string",
          "ParameterSetName": ["Default"],
          "OriginalPosition": 3,
          "Mandatory": true,
          "Description": "Specify your source path"
        },
        {
          "OriginalName": "-r",
          "Name": "Recurse",
          "ParameterType": "TranslatedHashtable",
          "ParameterValues": [
            {
              "$false": "-",
              "$true": "$null",
              "WildCardMatches": "0"
            }
          ],
          "DefaultValue": "$false",
          "ParameterSetName": ["Default"],
          "OriginalPosition": 2,
          "NoGap": true,
          "Mandatory": false,
          "Description": "Recurse through subdirectories"
        }
      ],
      "OutputHandlers": [
        {
          "ParameterSetName": "Default",
          "Handler": "$args..."
        }
      ]
    }
  ]
}

EmeraldFlame avatar Mar 15 '22 01:03 EmeraldFlame

I second this enhancement request.

In my case, I would like to combine multiple options that are mutually-exclusive on msiexec into a single PowerShell parameter. msiexec.exe /i <path_to_package> [/q{n|b|r|f}]

I can achieve this today with the following:

{
    "OriginalName": "/q",
    "Name": "UserInterfaceMode",
    "ParameterType": "string",
    "AdditionalParameterAttributes": [
        "[ValidateSet('n','n+','b','b+','r','f')]"
    ],
    "Mandatory": false,
    "Description": "Specifies the UI during the installation process.",
    "NoGap": true
},

But I would like the PowerShell command to have more descriptive values:

{
    "OriginalName": "/q",
    "Name": "UserInterfaceMode",
    "ParameterType": "string",
    "ParameterValues": [
        {
            "None": "n",
            "Basic": "b",
            "Reduced": "r",
            "Full": "f"
        }
    ],
    "AdditionalParameterAttributes": [
        "[ValidateSet('None','Basic','Reduced','Full')]"
    ],
    "Mandatory": false,
    "Description": "Specifies the UI during the installation process.",
    "NoGap": true
},

Another example is the mutually exclusive restart options on msiexec. msiexec.exe /i <path_to_package> [/norestart][/promptrestart][/forcerestart]

jazuntee avatar May 06 '22 21:05 jazuntee

I've been messing about with various bits and have this functionality in an experimental branch at https://github.com/jhoneill/Crescendo/tree/James

This sample https://github.com/jhoneill/Crescendo/blob/James/Microsoft.PowerShell.Crescendo/Samples/Install-Program.crescendo.json does what @jasoth is suggesting . The JSON has this

        "Parameters": [
            {
            "Name": "UIMode",
            "Description": "Specifies the UI during the installation process.",
            "OriginalName": "/q",
            "OriginalPosition": 0,
            "ApplyToExecutable": false,
            "NoGap": true
            "ParameterType": "string",
            "Position": 2147483647,
            "ValueMap": {
                "Reduced": "r",
                "None": "n",
                "Basic": "b",
                "Full": "f"
            },
            "DefaultValue": "Basic",

            }
        ],

The resulting parameter looks like this

    [ValidateSet('None', 'Full', 'Basic', 'Reduced')]
    [PSDefaultValue(Value='Basic')]
    [string]$UIMode="Basic"

The parameter map has this

    $parameterMap   = @{
        UIMode = @{
            OriginalName        = '/q'
            OriginalPosition    = '0'
            ParameterType       = 'string'
            ApplyToExecutable   =  $False
            NoGap               =  $True
            DefaultValue        = 'Basic'
            ValueMap            = @{ 'Reduced' = 'r'; 'None' = 'n'; 'Basic' = 'b'; 'Full' = 'f' }
        }
   }

and the body of the code has this

$parameterMap.Keys |  Where-Object {$parameterMap[$_].containskey('ValueMap') -and $boundParameters.ContainsKey($_)} |
                    ForEach-Object { $boundParameters[$_] = $parameterMap[$_].ValueMap[$boundParameters[$_]]}

So for any passed parameter whose entry in the parameterMap entry has a valuemap - replace the passed value with what it looks up as in the value map.

jhoneill avatar May 20 '22 11:05 jhoneill

@EmeraldFlame - This is interesting and has merit. I also think @jhoneill example is a good start - but we have some open questions to think through. I'll come back with questions ;)

theJasonHelmick avatar Jun 20 '22 22:06 theJasonHelmick

related to #31

theJasonHelmick avatar Aug 23 '22 22:08 theJasonHelmick