Search code examples
packagewindows-installernuget-packagepackage-managerschocolatey

How to pass installation arguments directly to an MSI installer (like -ArgumentLIist in PowerShell) using Chocolatey?


I want to pass custom arguments directly to the MSI installer. I have tried adding those arguments in the silentArgs but when I do that, after I run choco install I get the following (and after that the installation is aborted):

enter image description here

This is how I have passed those parameters in silentArgs:

silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`" /CUSTOMPARAM1:'dummydata' /CUSTOMPARAM2:'dummydata'"

I have tried different syntax (instead of using :, I used = but still the same result). Then I tried choco install <pckgName> --install-arguments="CUSTOMPARAM1=""dummy.data""", but with this approach the package does get installed but the parameters weren't passed to the MSI installer. I searched for some kind of docs related to --install-arguments such as the format that it expects (e.g. quotes, = or :, etc.) but didn't find anything.

TLDR; I want to pass custom parameters/arguments to my MSI installer through choco.


Solution

  • For an installer package that is managing an MSI, you must pass arguments to the underlying installer as the installer expects to see them, for an MSI, that is UPPERCASEPROPERTY="Value" NEXTPROPERTY="Another value". Otherwise MSI exec will pop up like you are seeing, telling you that you are passing things to it incorrectly.

    There are three approaches to this if you are creating the packaging:

    1. In Packaging
    2. Install-Arguments (the only option if you are using a package you can't change)
    3. Package Parameters (recommended)

    I'll go through each in a bit more detail.

    In Packaging - chocolateyInstall.ps1

    You were actually quite close on this. All you needed to do was change:

    /CUSTOMPARAM1:'dummydata' in

    silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`" /CUSTOMPARAM1:'dummydata' /CUSTOMPARAM2:'dummydata'"

    to:

    CUSTOMPARAM1=`"dummydata`", such as the following (I renamed CUSTOMPARAM1 to MSIPROPERTY below to signify that these must already exist in the MSI installer as properties you can set):

    silentArgs = "/qn /norestart /l*v `"$($env:TEMP)\$($packageName).$($env:chocolateyPackageVersion).MsiInstall.log`" MSIPROPERTY=`"dummydata`" EXISTINGMSIPROPERTY2=`"dummydata`""

    Install-Arguments at Runtime - choco install

    You could also pass in additional arguments directly to the installer at runtime.

    choco install <pkgName> --install-arguments="'CUSTOMPARAM1=""dummy.data""'" (NOTE: the quoting bits are specific to the shell you are running, cmd.exe expects these one way and powershell.exe needs them a bit different.). https://docs.chocolatey.org/en-us/choco/commands/#how-to-pass-options-switches (see Pass Quotes in Arguments) Also note this is different in that it employs the quotes bookending apostrophes as Chocolatey docs describe it ("'values'").

    Also, if you want to override the install arguments already being passed with silentArgs instead of just appending to the end of it, you want to use an additional switch --override-arguments. From https://docs.chocolatey.org/en-us/choco/commands/install#options-and-switches:

     -o, --override, --overrideargs, --overridearguments, --override-arguments
         OverrideArguments - Should install arguments be used exclusively without appending to 
         current package passed arguments? Defaults to false.
    

    Package Parameters

    This is a combination of putting together package parameters in your ChocolateyInstall.ps1 and then deciding how to pass those to the silentArgs.

    Based on the docs, you'll want to specify default options you would have for each parameter, then you'll look to convert that properly.

    Based on https://docs.chocolatey.org/en-us/guides/create/parse-packageparameters-argument, you would set up something like this in your script:

    $pp = Get-PackageParameters
    
    $additionalArgs = ''
    if ($pp['SOMEPROPERTY']) {
      $additionalArgs += " MSIPROPERTYNAME=`"$($pp['SOMEPROPERTY'])`""
    }
    
    
    [..snip..]
    
    silentArgs = "/qn /norestart MSIPROPERTY=`"dummydata`" $additionalArgs"
    # removed /l*v args for readability/brevity 
    
    

    You would want to add those parameters to the description of your nuspec file. There is a specific format as outlined at https://docs.chocolatey.org/en-us/guides/create/parse-packageparameters-argument#step-2-add-package-parameters-to-the-description

    And then you can call the Choco install like this:

    choco install <pkgName> --package-parameters="'/SOMEPROPERTY=dummy.data'"

    The benefits of Package Parameters:

    • The syntax is easier to pass - no weird quoting issues are required.
    • You can set sensible defaults.
    • You can validate what is passed in with the property.
    • You can name things how you want and translate them to the installer arguments.
    • You can provide a better explanation in validation of a value than something like an MSI exec pop up or error code that is unhelpful.
    • You can fail a package if there is a required parameter you need.
    • You can use package parameters for other things as well - https://docs.chocolatey.org/en-us/guides/create/parse-packageparameters-argument#example