Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
EmeraldFlame opened this issue Mar 15, 2022 · 4 comments
Open

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

EmeraldFlame opened this issue Mar 15, 2022 · 4 comments
Assignees
Labels
Issue-Enhancement New feature or request Issue-Triaged issue was read and triaged
Milestone

Comments

@EmeraldFlame
Copy link

EmeraldFlame commented Mar 15, 2022

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..."
        }
      ]
    }
  ]
}
@jazuntee
Copy link

jazuntee commented May 6, 2022

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]

@jhoneill
Copy link

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.

@theJasonHelmick theJasonHelmick added the Issue-Triaged issue was read and triaged label Jun 20, 2022
@theJasonHelmick
Copy link
Collaborator

@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 theJasonHelmick self-assigned this Jun 20, 2022
@theJasonHelmick theJasonHelmick added this to the Future-Consider milestone Jun 20, 2022
@theJasonHelmick theJasonHelmick added Issue-Enhancement New feature or request labels Jul 11, 2022
@theJasonHelmick
Copy link
Collaborator

related to #31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement New feature or request Issue-Triaged issue was read and triaged
Projects
None yet
Development

No branches or pull requests

4 participants