Skip to content

Conversation

@JPRuskin
Copy link
Member

@JPRuskin JPRuskin commented Jun 4, 2025

Description Of Changes

This PR introduces the ability for ChocolateyInstall, ChocolateyBeforeModify, and ChocolateyUninstall scripts to have and utilise PowerShell param() blocks to handle parameters.

It does this by adding a function (Get-PackageScriptParameters), which calculates what parameters a script has and passes any parameters found by the existing function Get-PackageParameters that match the parameter names to the script. Optionally, we could handle aliases, but this implementation does not yet.

The new function is called within the ChocolateyScriptRunner before invoking the script, and the resultant hashtable is "splatted" with the call. When no matching parameters are found (on the script and in packageparameters), this results in no change to behaviour.

It's worth noting that though this does allow for usage of parameter attributes and validation, such as [Parameter(Mandatory)], [ValidateSet()] and the like, Chocolatey can currently swallow some useful output (e.g. with SomeString being a mandatory parameter):
image
vs the PowerShell default:
image
This could possibly be improved in the future.

It adds the functionality, but doesn't remove the existing parameter handling - so all existing packages will continue working.

SMA Update

As a part of this, because of the use of the System.Management.Automation.Language to assess the param block, the System.Management.Automation assembly present in the lib/powershell folder was updated from a version matching the version shipped with PowerShell 2.0 (best guess) to a version from our earliest currently supported version of Windows - 2012.

This DLL isn't shipped in any of our builds; it's just used to ensure our code uses methods et al that are supported by the specific DLL we have embedded in the repository.

Specifically, I grabbed this from the uncertain/fun provenance of a Windows Server 2012 VM, in the folder C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35. There's not a similar version on nuget.org, annoyingly, which only has versions from 2018 onwards starting at 6.0.4.

There is an argument that this is a breaking change, as it may no longer work on machines we don't support - but that "break" has already happened. We do not support Windows versions prior to 2012 (and that only in Azure). Everything else is additive-only, and backwards compatible via a "lovely" new extension I'm looking to publish.

Motivation and Context

This allows for standardisation of how package maintainers handle parameters within their scripts, and helps Chocolatey Community Repository users and moderators to more easily understand what parameters can be used, what default values are used, and what (if any) validation is in place.

Testing

  • Grab https://chocolatey.org/install.ps1 and the modified version of the Chocolatey nupkg package, copy them to your test environment.
  • Set-ExecutionPolicy RemoteSigned Process -Force and Install with .\Install.ps1 -ChocolateyDownloadUrl .\Path\To\chocolatey.nupkg
  • Optional: install a random package without parameters to ensure I've not broken the existing functionality choco install cloudflared --confirm
  • Optional: install a random package with parameters to ensure I've not broken the existing functionality choco install Temurin21jre --params="/ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome" --confirm
  • Grab a package with param blocks available, e.g. testextension.1.0.0.zip (attached as a zip, as nupkg is not a supported file type) and copy it to the test environment (or have it in a repository)
  • choco install testextension --params='/SomeString:A String Value' --confirm (some massaging required for source)
    image

NB: testextension will fail to install if the PowerShell parameter value "SomeString" provided doesn't match the package parameter found by Get-PackageParameters. The install script is partially shown below:

param(
    [string]$SomeString
)

$PackageParameters = Get-PackageParameters

if ($PackageParameters.SomeString -ne $SomeString) {
    throw "'$SomeString' was not equal to '$($PackageParameters.SomeString)'"
}

Operating Systems Testing

  • Windows Server 2012
    image
  • Windows Server 2022
    image
  • Windows 11 (Sandbox)
    image

I also have an extension package that adds the same functionality to any other extension-supporting version of Chocolatey CLI. This hopefully means that this can be an acceptable thing to use for Community packages.

image

I am very excited about this, despite the code being utterly despicable.

I have had to slightly revise my backwards compatibility happiness - it doesn't work with the earliest mention of Chocolatey extensions (0.9.10) because Get-PackageParameters doesn't exist at that point. I could fix this by packing a backup version fo the function in the extension, but I feel like supporting back to the 0.10.8 is enough for any unreasonable expectation:
image

Change Types Made

  • [ ] Bug fix (non-breaking change).
  • Feature / Enhancement (non-breaking change).
  • [ ] Breaking change (fix or feature that could cause existing functionality to change). See SMA update.
  • [ ] Documentation changes.
  • PowerShell code changes.

Change Checklist

  • [ ] Requires a change to the documentation.
  • [ ] Documentation has been updated.
  • Tests to cover my changes, have been added.
  • All new and existing tests passed?
  • PowerShell code changes: PowerShell v3 compatibility checked?

Related Issue

Resolves #3344

@JPRuskin JPRuskin self-assigned this Jun 4, 2025
@JPRuskin JPRuskin requested a review from a team as a code owner June 4, 2025 19:47
@JPRuskin JPRuskin requested a review from pauby June 4, 2025 19:47
@JPRuskin JPRuskin force-pushed the splattingParams branch 3 times, most recently from 40f5979 to f60bd70 Compare June 5, 2025 08:28
@JPRuskin JPRuskin requested review from gep13 and vexx32 June 5, 2025 21:07
Copy link
Member

@vexx32 vexx32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to come back and review the tests added in a bit, but some initial comments. :3

JPRuskin and others added 6 commits July 3, 2025 17:16
Adds a basic function to the helper functions that parses a script file for parameters, and compares that list to available Package Parameters.

If there are matches, it returns a hashtable with matching names and their values.

This can then be used in the chocolateyScriptRunner to pass parameters into the param block.

The methods used all work back to PowerShell v3, though without any plan for backwards compatibility (e.g. considerations for using an extension package/module) it's hard to see this being that popular.

(chocolatey#3344) Adds Tests for Get-ScriptParameters

Adding some tests to check the conversion from
PowerShell to C# cmdlet.
Rewrite of the Get-PackageParameter(s) into C# cmdlet,
though there will be further changes made to refactor
it into a helper method in a later commit.
Updates included SMA to 6.2.9200.24523.

This is now equivalent to a version shipped on Windows Server 2012
(the earliest OS Chocolatey products support).

This is necessary for the more advanced use of the AST parser,
and may allow us to benefit from upgrades elsewhere.
It was pointed out that this PR should be targeted
at including new helper functions into the C# conversion
efforts.

This converts Get-PackageParameter to use a
helper class (shared between this and the new
cmdlet) and adds Get-PackageScriptParameters to the
Chocolatey.PowerShell compiled module.
…ion scriptfile

As it was pointed out that removing a script from the helpers module was a breaking change, I have reverted that change.

The PackageParameter helper remains, used by PackageScriptParameters, but there are no longer any removals from the user contract.
Also refactors the helper method for package parameters to enable logging of sensitive parameter names (not values).
@JPRuskin
Copy link
Member Author

JPRuskin commented Jul 3, 2025

I believe this is no longer a breaking change (as it doesn't remove or change any PowerShell helpers), makes all changes to helper functionality in C#, and doesn't break any business promises.

I suspect I've missed the boat on getting it merged into 2.5.0, though! Shocking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable use of param() blocks in Chocolatey* Scripts

2 participants