private/Invoke-ChocoAPI.ps1
# Builds a command optimized for a package provider and sends to choco.exe function Invoke-ChocoAPI { [CmdletBinding()] param ( [Parameter(Mandatory=$true, ParameterSetName='Search')] [switch] $Search, [Parameter(Mandatory=$true, ParameterSetName='Install')] [switch] $Install, [Parameter(Mandatory=$true, ParameterSetName='Uninstall')] [switch] $Uninstall, [Parameter(Mandatory=$true, ParameterSetName='SourceList')] [switch] $SourceList, [Parameter(Mandatory=$true, ParameterSetName='SourceAdd')] [switch] $SourceAdd, [Parameter(Mandatory=$true, ParameterSetName='SourceRemove')] [switch] $SourceRemove, [Parameter(ParameterSetName='Search')] [Parameter(Mandatory=$true, ParameterSetName='Install')] [Parameter(Mandatory=$true, ParameterSetName='Uninstall')] [string] $Name, [Parameter(ParameterSetName='Search')] [Parameter(Mandatory=$true, ParameterSetName='Install')] [Parameter(Mandatory=$true, ParameterSetName='Uninstall')] [string] $Version, [Parameter(ParameterSetName='Search')] [switch] $AllVersions, [Parameter(ParameterSetName='Search')] [switch] $LocalOnly, [Parameter(ParameterSetName='Search')] [switch] $Exact, [Parameter(ParameterSetName='Search')] [Parameter(ParameterSetName='Install')] [Parameter(Mandatory=$true, ParameterSetName='SourceAdd')] [Parameter(Mandatory=$true, ParameterSetName='SourceRemove')] [string] $Source = $script:PackageSource, [Parameter(Mandatory=$true, ParameterSetName='SourceAdd')] [string] $Location, [Parameter(ParameterSetName='Install')] [switch] $ParamsGlobal, [Parameter(ParameterSetName='Install')] [string] $Parameters, [Parameter(ParameterSetName='Install')] [switch] $ArgsGlobal, [Parameter(ParameterSetName='Install')] [string] $InstallArguments, [switch] $Force = (Get-ForceProperty) ) $sourceCommandName = 'source' $ChocoAPI = [chocolatey.Lets]::GetChocolatey().SetCustomLogging([chocolatey.infrastructure.logging.NullLog]::new()) # Series of generic paramters that can be used across both 'get' and 'set' operations, which are called differently $genericParams = { # Entering scriptblock $config.QuietOutput = $True $config.RegularOutput = $False if ($Version) { $config.Version = $Version } if ($AllVersions) { $config.AllVersions = $true } if ($LocalOnly) { $config.ListCommand.LocalOnly = $true } if ($Force) { $config.Force = $true } } if ($SourceList) { # We can get the source info right from the MachineSources property without any special calls # Just need to alias each source's 'Key' property to 'Location' so that it lines up the CLI terminology $ChocoAPI.GetConfiguration().MachineSources | Add-Member -MemberType AliasProperty -Name Location -Value Key -PassThru } elseif ($Search) { # Configuring 'get' operations - additional arguments are ignored # Using Out-Null to 'eat' the output from the Set operation so it doesn't contaminate the pipeline $ChocoAPI.Set({ # Entering scriptblock param($config) Invoke-Command $genericParams if ($Name) { $config.Input = $Name if ($Exact) { $config.ListCommand.Exact = $true } } $config.CommandName = [chocolatey.infrastructure.app.domain.CommandNameType]::list }) | Out-Null Write-Debug ("Invoking the Choco API with the following configuration: $($ChocoAPI.GetConfiguration() | Out-String)") # This invocation looks gross, but PowerShell currently lacks a clean way to call the parameter-less .NET generic method that Chocolatey uses for returning data $ChocoAPI.GetType().GetMethod('List').MakeGenericMethod([chocolatey.infrastructure.results.PackageResult]).Invoke($ChocoAPI,$null) | ForEach-Object { # If searching local packages, we need to spoof the source name returned by the API with a generic default if ($LocalOnly) { $_.Source = $script:PackageSource } else { # Otherwise, convert the source URI returned by Choco to a source name $_.Source = $ChocoAPI.GetConfiguration().MachineSources | Where-Object Key -eq $_.Source | Select-Object -ExpandProperty Name } $swid = @{ FastPackageReference = $_.Name+"#"+$_.Version+"#"+$_.Source Name = $_.Name Version = $_.Version versionScheme = "MultiPartNumeric" FromTrustedSource = $true Source = $_.Source } New-SoftwareIdentity @swid } } else { # Using Out-Null to 'eat' the output from the Set operation so it doesn't contaminate the pipeline $ChocoAPI.Set({ # Entering scriptblock param($config) Invoke-Command $genericParams # Configuring 'set' operations if ($SourceAdd -or $SourceRemove) { $config.CommandName = $sourceCommandName $config.SourceCommand.Name = $Source if ($SourceAdd) { $config.SourceCommand.Command = [chocolatey.infrastructure.app.domain.SourceCommandType]::add $config.Sources = $Location } elseif ($SourceRemove) { $config.SourceCommand.Command = [chocolatey.infrastructure.app.domain.SourceCommandType]::remove } } else { # In this area, we're only leveraging (not managing) sources, hence why we're treating the source name parameter differently if ($Name) { $config.PackageNames = $Name } if ($Source) { $config.Sources = $config.MachineSources | Where-Object Name -eq $Source | Select-Object -ExpandProperty Key } if ($Install) { $config.CommandName = [chocolatey.infrastructure.app.domain.CommandNameType]::install $config.PromptForConfirmation = $False if ($ParamsGlobal) { $config.ApplyPackageParametersToDependencies = $True } if ($Parameters) { $config.PackageParameters = $Parameters } if ($ArgsGlobal) { $config.ApplyInstallArgumentsToDependencies = $True } if ($InstallArguments) { $config.InstallArguments = $InstallArguments } } elseif ($Uninstall) { $config.CommandName = [chocolatey.infrastructure.app.domain.CommandNameType]::uninstall $config.ForceDependencies = $true } } }) | Out-Null Write-Debug ("Invoking the Choco API with the following configuration: $($ChocoAPI.GetConfiguration() | Out-String)") # Using Out-Null to 'eat' the output from the Run operation so it doesn't contaminate the pipeline $ChocoAPI.Run() | Out-Null if ($Install -or $Uninstall) { # Since the API wont return anything (ex: dependencies installed), we can only return the package asked for # This is a regression of the API vs CLI, as we can capture dependencies returned by the CLI $swid = @{ FastPackageReference = $Name+"#"+$Version+"#"+$Source Name = $Name Version = $Version versionScheme = "MultiPartNumeric" FromTrustedSource = $true Source = $Source } New-SoftwareIdentity @swid } } } |