Public/WingetFunctions.ps1
|
function Install-WingetIfNeeded { <# .SYNOPSIS Ensures Winget is installed on the system, installing it if necessary. .DESCRIPTION Checks if the Microsoft.DesktopAppInstaller package is installed with a sufficient version. If not, installs the required dependencies and the latest Winget release from GitHub. Also accepts source agreements proactively to avoid prompts. .PARAMETER MinVersion The minimum required version of Winget. Defaults to 1.10.0.0. #> param( [version]$MinVersion = "1.10.0.0" ) $hasPackageManager = Get-AppPackage -Name 'Microsoft.DesktopAppInstaller' $wingetInstalled = $hasPackageManager -and [version]$hasPackageManager.Version -ge $MinVersion if ($wingetInstalled) { Write-Host "Winget already installed" Write-Verbose "Winget already installed" } else { Write-Host "Installing winget dependencies" Write-Verbose "Installing winget dependencies" Add-AppxPackage -Path 'https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/microsoft/winget-cli/releases/latest' $latestRelease = $releases.assets | Where-Object { $_.browser_download_url.EndsWith('msixbundle') } | Select-Object -First 1 Write-Host "Installing winget from $($latestRelease.browser_download_url)" Write-Verbose "Installing winget from $($latestRelease.browser_download_url)" Add-AppxPackage -Path $latestRelease.browser_download_url } # Accept source agreements proactively to avoid prompts Write-Host "Accepting winget source agreements..." try { & winget source update --accept-source-agreements 2>$null | Out-Null Write-Host "Source agreements accepted" } catch { Write-Host "Could not pre-accept source agreements. They will be accepted per command." } } function Find-WinGetPackage { <# .SYNOPSIS Searches for a package on configured sources. Additional options can be provided to filter the output, much like the search command. .DESCRIPTION By running this cmdlet with the required inputs, it will retrieve the packages installed on the local system. .PARAMETER Filter Used to search across multiple fields of the package. .PARAMETER Id Used to specify the Id of the package .PARAMETER Name Used to specify the Name of the package .PARAMETER Moniker Used to specify the Moniker of the package .PARAMETER Tag Used to specify the Tag of the package .PARAMETER Command Used to specify the Command of the package .PARAMETER Exact Used to specify an exact match for any parameters provided. Many of the other parameters may be used for case insensitive substring matches if Exact is not specified. .PARAMETER Source Name of the Windows Package Manager private source. Can be identified by running: "Get-WinGetSource" and using the source Name .PARAMETER Count Used to specify the maximum number of packages to return .PARAMETER Header Used to specify the value to pass as the "Windows-Package-Manager" HTTP header for a REST source. .PARAMETER VerboseLog Used to provide verbose logging for the Windows Package Manager. .PARAMETER AcceptSourceAgreement Used to accept any source agreement required for the source. .EXAMPLE Find-WinGetPackage -id "Publisher.Package" This example searches for a package containing "Publisher.Package" as a valid identifier on all configured sources. .EXAMPLE Find-WinGetPackage -id "Publisher.Package" -source "Private" This example searches for a package containing "Publisher.Package" as a valid identifier from the source named "Private". .EXAMPLE Find-WinGetPackage -Name "Package" This example searches for a package containing "Package" as a valid name on all configured sources. #> param( [Parameter(Position = 0)] $Filter, [Parameter()] $Id, [Parameter()] $Name, [Parameter()] $Moniker, [Parameter()] $Tag, [Parameter()] $Command, [Parameter()] [switch] $Exact, [Parameter()] $Source, [Parameter()] [ValidateRange(1, [int]::maxvalue)][int]$Count, [Parameter()] [ValidateLength(1, 1024)]$Header, [Parameter()] [switch] $VerboseLog, [Parameter()] [switch] $AcceptSourceAgreement ) begin { [string[]] $WinGetArgs = @("Search") [WinGetPackage[]] $Result = @() [string[]] $IndexTitles = @("Name", "Id", "Version", "Available", "Source") if ($PSBoundParameters.ContainsKey('Filter')) { ## Search across Name, ID, moniker, and tags $WinGetArgs += $Filter } if ($PSBoundParameters.ContainsKey('Id')) { ## Search for the ID $WinGetArgs += "--Id", $Id.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Name')) { ## Search for the Name $WinGetArgs += "--Name", $Name.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Moniker')) { ## Search for the Moniker $WinGetArgs += "--Moniker", $Moniker.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Tag')) { ## Search for the Tag $WinGetArgs += "--Tag", $Tag.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Command')) { ## Search for the Moniker $WinGetArgs += "--Command", $Command.Replace("…", "") } if ($Exact) { ## Search using exact values specified (case sensitive) $WinGetArgs += "--Exact" } if ($PSBoundParameters.ContainsKey('Source')) { ## Search for the Source $WinGetArgs += "--Source", $Source.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Count')) { ## Specify the number of results to return $WinGetArgs += "--Count", $Count } if ($PSBoundParameters.ContainsKey('Header')) { ## Pass the value specified as the Windows-Package-Manager HTTP header $WinGetArgs += "--header", $Header } if ($PSBoundParameters.ContainsKey('VerboseLog')) { ## Search using exact values specified (case sensitive) $WinGetArgs += "--VerboseLog", $VerboseLog } if ($AcceptSourceAgreement) { ## Accept source agreements $WinGetArgs += "--accept-source-agreements" } } process { $ErrorActionPreference = 'Continue' $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles $IndexTitles -ErrorAction SilentlyContinue 2>$null if ($List) { foreach ($Obj in $List) { $Result += [WinGetPackage]::New($Obj) } } else { Write-Verbose "No packages found matching the search criteria" } } end { return $Result } } function Install-WinGetPackage { <# .SYNOPSIS Installs a package on the local system. Additional options can be provided to filter the output, much like the search command. .DESCRIPTION By running this cmdlet with the required inputs, it will retrieve the packages installed on the local system. .PARAMETER Filter Used to search across multiple fields of the package. .PARAMETER Id Used to specify the Id of the package .PARAMETER Name Used to specify the Name of the package .PARAMETER Moniker Used to specify the Moniker of the package .PARAMETER Tag Used to specify the Tag of the package .PARAMETER Command Used to specify the Command of the package .PARAMETER Scope Used to specify install scope (user or machine) .PARAMETER Exact Used to specify an exact match for any parameters provided. Many of the other parameters may be used for case insensitive substring matches if Exact is not specified. .PARAMETER Source Name of the Windows Package Manager private source. Can be identified by running: "Get-WinGetSource" and using the source Name .PARAMETER Interactive Used to specify the installer should be run in interactive mode. .PARAMETER Silent Used to specify the installer should be run in silent mode with no user input. .PARAMETER Locale Used to specify the locale for localized package installer. .PARAMETER Log Used to specify the location for the log location if it is supported by the package installer. .PARAMETER Header Used to specify the value to pass as the "Windows-Package-Manager" HTTP header for a REST source. .PARAMETER Version Used to specify the Version of the package .PARAMETER VerboseLog Used to provide verbose logging for the Windows Package Manager. .PARAMETER AcceptPackageAgreement Used to accept any package agreement required for the package. .PARAMETER AcceptSourceAgreement Used to explicitly accept any agreement required by the source. .PARAMETER Local Used to install from a local manifest .EXAMPLE Install-WinGetPackage -id "Publisher.Package" This example expects only a single package containing "Publisher.Package" as a valid identifier. .EXAMPLE Install-WinGetPackage -id "Publisher.Package" -source "Private" This example expects the source named "Private" contains a package with "Publisher.Package" as a valid identifier. .EXAMPLE Install-WinGetPackage -Name "Package" This example expects a configured source contains a package with "Package" as a valid name. #> param( [Parameter()] $Filter, [Parameter()] $Name, [Parameter()] $Id, [Parameter()] $Moniker, [Parameter()] $Source, [Parameter()] [ValidateSet("User", "Machine")] $Scope, [Parameter()] [switch] $Interactive, [Parameter()] [switch] $Silent, [Parameter()] [string] $Version, [Parameter()] [switch] $Exact, [Parameter()] [switch] $Override, [Parameter()] [System.IO.FileInfo] $Location, [Parameter()] [switch] $Force, [Parameter()] [ValidatePattern("^([a-zA-Z]{2,3}|[iI]-[a-zA-Z]+|[xX]-[a-zA-Z]{1,8})(-[a-zA-Z]{1,8})*$")] [string] $Locale, [Parameter()] [System.IO.FileInfo] $Log, ## This is a path of where to create a log. [Parameter()] [switch] $AcceptSourceAgreements, [Parameter()] [switch] $Local # This is for installing local manifests ) begin { $WinGetFindArgs = @{} [string[]] $WinGetInstallArgs = "Install" if ($PSBoundParameters.ContainsKey('Filter')) { if ($Local) { $WinGetInstallArgs += "--Manifest" } $WinGetInstallArgs += $Filter $WinGetFindArgs.Add('Filter', $Filter) } if ($PSBoundParameters.ContainsKey('Name')) { $WinGetInstallArgs += "--Name", $Name $WinGetFindArgs.Add('Name', $Name) } if ($PSBoundParameters.ContainsKey('Id')) { $WinGetInstallArgs += "--Id", $Id $WinGetFindArgs.Add('Id', $Id) } if ($PSBoundParameters.ContainsKey('Moniker')) { $WinGetInstallArgs += "--Moniker", $Moniker $WinGetFindArgs.Add('Moniker', $Moniker) } if ($PSBoundParameters.ContainsKey('Source')) { $WinGetInstallArgs += "--Source", $Source $WinGetFindArgs.Add('Source', $Source) } if ($PSBoundParameters.ContainsKey('Scope')) { $WinGetInstallArgs += "--Scope", $Scope } if ($Interactive) { $WinGetInstallArgs += "--Interactive" } if ($Silent) { $WinGetInstallArgs += "--Silent" } if ($PSBoundParameters.ContainsKey('Locale')) { $WinGetInstallArgs += "--locale", $Locale } if ($PSBoundParameters.ContainsKey('Version')) { $WinGetInstallArgs += "--Version", $Version } if ($Exact) { $WinGetInstallArgs += "--Exact" $WinGetFindArgs.Add('Exact', $true) } if ($PSBoundParameters.ContainsKey('Log')) { $WinGetInstallArgs += "--Log", $Log } if ($PSBoundParameters.ContainsKey('Override')) { $WinGetInstallArgs += "--override", $Override } if ($PSBoundParameters.ContainsKey('Location')) { $WinGetInstallArgs += "--Location", $Location } if ($Force) { $WinGetInstallArgs += "--Force" } } process { if (!$Local) { $Result = Find-WinGetPackage @WinGetFindArgs } if ($Result.count -eq 1 -or $Local) { & "WinGet" $WinGetInstallArgs $Result = "" } elseif ($Result.count -lt 1) { Write-Error -Message "Unable to locate package for installation" $Result = "" } else { Write-Error -Message "Multiple packages found matching input criteria. Please refine the input." } } end { return $Result } } filter Assert-WhiteSpaceIsNull { if ([string]::IsNullOrWhiteSpace($_)) { $null } else { $_ } } class WinGetSource { [string] $Name [string] $Argument [string] $Data [string] $Identifier [string] $Type WinGetSource () {} WinGetSource ([string[]]$a) { $this.Name = $a[0].TrimEnd() | Assert-WhiteSpaceIsNull $this.Argument = $a[1].TrimEnd() | Assert-WhiteSpaceIsNull $this.Data = $a[2].TrimEnd() | Assert-WhiteSpaceIsNull $this.Identifier = $a[3].TrimEnd() | Assert-WhiteSpaceIsNull $this.Type = $a[4].TrimEnd() | Assert-WhiteSpaceIsNull } } class WinGetPackage { [string]$Name [string]$Id [string]$Version [string]$Available [string]$Source [string]$Match WinGetPackage ([psobject] $a) { $this.Name = $a.Name | Assert-WhiteSpaceIsNull $this.Id = $a.Id | Assert-WhiteSpaceIsNull $this.Version = $a.Version | Assert-WhiteSpaceIsNull $this.Available = $a.Available | Assert-WhiteSpaceIsNull $this.Source = $a.Source | Assert-WhiteSpaceIsNull } } function Invoke-WinGetCommand { param( [Parameter(Position = 0, Mandatory = $true)] [string[]]$WinGetArgs, [Parameter(Position = 0, Mandatory = $true)] [string[]]$IndexTitles, [Parameter()] [switch] $JSON ) begin { $Index = @() $Result = @() $i = 0 $IndexTitlesCount = $IndexTitles.Count $Offset = 0 $Found = $false ## Add --accept-source-agreements to all winget commands to handle msstore agreement popup $WingetArgs += "--accept-source-agreements" ## Remove two characters from the string length and add "..." to the end (only if there is the three below characters present). [string[]]$WinGetSourceListRaw = & "WinGet" $WingetArgs | Out-String -Stream | ForEach-Object { $_ -replace ("$([char]915)$([char]199)$([char]170)", "$([char]199)") } } process { if ($JSON) { ## If expecting JSON content, return the object return $WinGetSourceListRaw | ConvertFrom-Json } ## Gets the indexing of each title $rgex = $IndexTitles -join "|" for ($Offset = 0; $Offset -lt $WinGetSourceListRaw.Length; $Offset++) { if ($WinGetSourceListRaw[$Offset].Split(" ")[0].Trim() -match $rgex) { $Found = $true break } } if (!$Found) { Write-Error -Message "No results were found." -TargetObject $WinGetSourceListRaw return } foreach ($IndexTitle in $IndexTitles) { ## Creates an array of titles and their string location $IndexStart = $WinGetSourceListRaw[$Offset].IndexOf($IndexTitle) $IndexEnds = "" if ($IndexStart -ne "-1") { $Index += [pscustomobject]@{ Title = $IndexTitle Start = $IndexStart Ends = $IndexEnds } } } ## Orders the Object based on Index value $Index = $Index | Sort-Object Start ## Sets the end of string value while ($i -lt $IndexTitlesCount) { $i ++ ## Sets the End of string value (if not null) if ($Index[$i].Start) { $Index[$i - 1].Ends = ($Index[$i].Start - 1) - $Index[$i - 1].Start } } ## Builds the WinGetSource Object with contents $i = $Offset + 2 while ($i -lt $WinGetSourceListRaw.Length) { $row = $WinGetSourceListRaw[$i] try { [bool] $TestNotTitles = $WinGetSourceListRaw[0] -ne $row [bool] $TestNotHyphenLine = $WinGetSourceListRaw[1] -ne $row -and !$Row.Contains("---") [bool] $TestNotNoResults = $row -ne "No package found matching input criteria." } catch { Write-Verbose "Error parsing winget output row: $_" $i++ continue } if (!$TestNotNoResults) { Write-Verbose "No package found matching input criteria." } ## If this is the first pass containing titles or the table line, skip. if ($TestNotTitles -and $TestNotHyphenLine -and $TestNotNoResults) { $List = @{} foreach ($item in $Index) { if ($Item.Ends) { $List[$Item.Title] = $row.SubString($item.Start, $Item.Ends) } else { $List[$item.Title] = $row.SubString($item.Start, $row.Length - $Item.Start) } } $result += [pscustomobject]$list } $i++ } } end { return $Result } } function Uninstall-WinGetPackage { <# .SYNOPSIS Uninstalls a package from the local system. Additional options can be provided to filter the output, much like the search command. .DESCRIPTION By running this cmdlet with the required inputs, it will uninstall a package installed on the local system. .PARAMETER Filter Used to search across multiple fields of the package. .PARAMETER Id Used to specify the Id of the package .PARAMETER Name Used to specify the Name of the package .PARAMETER Moniker Used to specify the Moniker of the package .PARAMETER Version Used to specify the Version of the package .PARAMETER Exact Used to specify an exact match for any parameters provided. Many of the other parameters may be used for case insensitive substring matches if Exact is not specified. .PARAMETER Source Name of the Windows Package Manager private source. Can be identified by running: "Get-WinGetSource" and using the source Name .PARAMETER Interactive Used to specify the uninstaller should be run in interactive mode. .PARAMETER Silent Used to specify the uninstaller should be run in silent mode with no user input. .PARAMETER Log Used to specify the location for the log location if it is supported by the package uninstaller. .PARAMETER VerboseLog Used to provide verbose logging for the Windows Package Manager. .PARAMETER Header Used to specify the value to pass as the "Windows-Package-Manager" HTTP header for a REST source. .PARAMETER AcceptSourceAgreement Used to explicitly accept any agreement required by the source. .PARAMETER Local Used to uninstall from a local manifest .EXAMPLE Uninstall-WinGetPackage -id "Publisher.Package" This example expects only a single configured REST source with a package containing "Publisher.Package" as a valid identifier. .EXAMPLE Uninstall-WinGetPackage -id "Publisher.Package" -source "Private" This example expects the REST source named "Private" with a package containing "Publisher.Package" as a valid identifier. .EXAMPLE Uninstall-WinGetPackage -Name "Package" This example expects a configured source contains a package with "Package" as a valid name. #> param( [Parameter(Position = 0)] $Filter, [Parameter()] $Name, [Parameter()] $Id, [Parameter()] $Moniker, [Parameter()] $Source, [Parameter()] [switch] $Interactive, [Parameter()] [switch] $Silent, [Parameter()] [string] $Version, [Parameter()] [switch] $Exact, [Parameter()] [switch] $Override, [Parameter()] [System.IO.FileInfo] $Location, [Parameter()] [switch] $Force, [Parameter()] [System.IO.FileInfo] $Log, ## This is a path of where to create a log. [Parameter()] [switch] $AcceptSourceAgreements, [Parameter()] [switch] $Local # This is for installing local manifests ) begin { [string[]] $WinGetArgs = "Uninstall" if ($PSBoundParameters.ContainsKey('Filter')) { if ($Local) { $WinGetArgs += "--Manifest" } $WinGetArgs += $Filter } if ($PSBoundParameters.ContainsKey('Name')) { $WinGetArgs += "--Name", $Name } if ($PSBoundParameters.ContainsKey('Id')) { $WinGetArgs += "--Id", $Id } if ($PSBoundParameters.ContainsKey('Moniker')) { $WinGetArgs += "--Moniker", $Moniker } if ($PSBoundParameters.ContainsKey('Source')) { $WinGetArgs += "--Source", $Source } if ($Interactive) { $WinGetArgs += "--Interactive" } if ($Silent) { $WinGetArgs += "--Silent" } if ($PSBoundParameters.ContainsKey('Version')) { $WinGetArgs += "--Version", $Version } if ($Exact) { $WinGetArgs += "--Exact" } if ($PSBoundParameters.ContainsKey('Log')) { $WinGetArgs += "--Log", $Log } if ($PSBoundParameters.ContainsKey('Location')) { $WinGetArgs += "--Location", $Location } if ($Force) { $WinGetArgs += "--Force" } } process { if (!$Local) { $Result = Find-WinGetPackage -Filter $Filter -Name $Name -Id $Id -Moniker $Moniker -Source $Source } if ($Result.count -eq 1 -or $Local) { & "WinGet" $WingetArgs $Result = "" } elseif ($Result.count -lt 1) { Write-Error -Message "Unable to locate package for uninstallation" $Result = "" } else { Write-Error -Message "Multiple packages found matching input criteria. Please refine the input." } } end { return $Result } } function Update-WinGetPackage { <# .SYNOPSIS Upgrades a package on the local system. Additional options can be provided to filter the output, much like the search command. .DESCRIPTION By running this cmdlet with the required inputs, it will retrieve the packages installed on the local system. .PARAMETER Filter Used to search across multiple fields of the package. .PARAMETER Id Used to specify the Id of the package .PARAMETER Name Used to specify the Name of the package .PARAMETER Moniker Used to specify the Moniker of the package .PARAMETER Tag Used to specify the Tag of the package .PARAMETER Command Used to specify the Command of the package .PARAMETER Channel Used to specify the channel of the package. Note this is not yet implemented in Windows Package Manager as of version 1.1.0. .PARAMETER Scope Used to specify install scope (user or machine) .PARAMETER Exact Used to specify an exact match for any parameters provided. Many of the other parameters may be used for case insensitive substring matches if Exact is not specified. .PARAMETER Source Name of the Windows Package Manager private source. Can be identified by running: "Get-WinGetSource" and using the source Name .PARAMETER Manifest Path to the manifest on the local file system. Requires local manifest setting to be enabled. .PARAMETER Interactive Used to specify the installer should be run in interactive mode. .PARAMETER Silent Used to specify the installer should be run in silent mode with no user input. .PARAMETER Locale Used to specify the locale for localized package installer. .PARAMETER Log Used to specify the location for the log location if it is supported by the package installer. .PARAMETER Override Used to override switches passed to installer. .PARAMETER Force Used to force the upgrade when the Windows Package Manager would ordinarily not upgrade the package. .PARAMETER Location Used to specify the location for the package to be upgraded. .PARAMETER Header Used to specify the value to pass as the "Windows-Package-Manager" HTTP header for a REST source. .PARAMETER Version Used to specify the Version of the package .PARAMETER VerboseLog Used to provide verbose logging for the Windows Package Manager. .PARAMETER AcceptPackageAgreement Used to accept any source package required for the package. .PARAMETER AcceptSourceAgreement .EXAMPLE Update-WinGetPackage -id "Publisher.Package" This example expects only a single package containing "Publisher.Package" as a valid identifier. .EXAMPLE Update-WinGetPackage -id "Publisher.Package" -source "Private" This example expects the source named "Private" contains a package with "Publisher.Package" as a valid identifier. .EXAMPLE Update-WinGetPackage -Name "Package" This example expects the source named "Private" contains a package with "Package" as a valid name. #> param( [Parameter(Position = 0)] $Filter, [Parameter()] $Name, [Parameter()] $Id, [Parameter()] $Moniker, [Parameter()] $Source, [Parameter()] [ValidateSet("User", "Machine")] $Scope, [Parameter()] [switch] $Interactive, [Parameter()] [switch] $Silent, [Parameter()] [string] $Version, [Parameter()] [switch] $Exact, [Parameter()] [switch] $Override, [Parameter()] [System.IO.FileInfo] $Location, [Parameter()] [switch] $Force, [Parameter()] [ValidatePattern("^([a-zA-Z]{2,3}|[iI]-[a-zA-Z]+|[xX]-[a-zA-Z]{1,8})(-[a-zA-Z]{1,8})*$")] [string] $Locale, [Parameter()] [System.IO.FileInfo] $Log, ## This is a path of where to create a log. [Parameter()] [switch] $AcceptSourceAgreements ) begin { [string[]] $WinGetArgs = "Upgrade" if ($PSBoundParameters.ContainsKey('Filter')) { $WinGetArgs += $Filter } if ($PSBoundParameters.ContainsKey('Name')) { $WinGetArgs += "--Name", $Name } if ($PSBoundParameters.ContainsKey('Id')) { $WinGetArgs += "--Id", $Id } if ($PSBoundParameters.ContainsKey('Moniker')) { $WinGetArgs += "--Moniker", $Moniker } if ($PSBoundParameters.ContainsKey('Source')) { $WinGetArgs += "--Source", $Source } if ($PSBoundParameters.ContainsKey('Scope')) { $WinGetArgs += "--Scope", $Scope } if ($Interactive) { $WinGetArgs += "--Interactive" } if ($Silent) { $WinGetArgs += "--Silent" } if ($PSBoundParameters.ContainsKey('Locale')) { $WinGetArgs += "--locale", $Locale } if ($PSBoundParameters.ContainsKey('Version')) { $WinGetArgs += "--Version", $Version } if ($Exact) { $WinGetArgs += "--Exact" } if ($PSBoundParameters.ContainsKey('Log')) { $WinGetArgs += "--Log", $Log } if ($PSBoundParameters.ContainsKey('Override')) { $WinGetArgs += "--override", $Override } if ($PSBoundParameters.ContainsKey('Location')) { $WinGetArgs += "--Location", $Location } if ($Force) { $WinGetArgs += "--Force" } } process { $Result = Find-WinGetPackage -Filter $Filter -Name $Name -Id $Id -Moniker $Moniker -Source $Source if ($Result.count -eq 1) { & "WinGet" $WingetArgs $Result = "" } elseif ($Result.count -lt 1) { Write-Error -Message "Unable to locate package for upgrade" $Result = "" } else { Write-Error -Message "Multiple packages found matching input criteria. Please refine the input." } } end { return $Result } } function Get-WinGetPackage { <# .SYNOPSIS Gets installed packages on the local system. displays the packages installed on the system, as well as whether an update is available. Additional options can be provided to filter the output, much like the search command. .DESCRIPTION By running this cmdlet with the required inputs, it will retrieve the packages installed on the local system. .PARAMETER Filter Used to search across multiple fields of the package. .PARAMETER Id Used to specify the Id of the package .PARAMETER Name Used to specify the Name of the package .PARAMETER Moniker Used to specify the Moniker of the package .PARAMETER Tag Used to specify the Tag of the package .PARAMETER Command Used to specify the Command of the package .PARAMETER Count Used to specify the maximum number of packages to return .PARAMETER Exact Used to specify an exact match for any parameters provided. Many of the other parameters may be used for case insensitive substring matches if Exact is not specified. .PARAMETER Source Name of the Windows Package Manager private source. Can be identified by running: "Get-WinGetSource" and using the source Name .PARAMETER Header Used to specify the value to pass as the "Windows-Package-Manager" HTTP header for a REST source. .PARAMETER AcceptSourceAgreement Used to accept any source agreements required by a REST source. .EXAMPLE Get-WinGetPackage -id "Publisher.Package" This example expects only a single configured REST source with a package containing "Publisher.Package" as a valid identifier. .EXAMPLE Get-WinGetPackage -id "Publisher.Package" -source "Private" This example expects the REST source named "Private" with a package containing "Publisher.Package" as a valid identifier. .EXAMPLE Get-WinGetPackage -Name "Package" This example expects the REST source named "Private" with a package containing "Package" as a valid name. #> param( [Parameter(Position = 0)] $Filter, [Parameter()] $Name, [Parameter()] $Id, [Parameter()] $Moniker, [Parameter()] $Tag, [Parameter()] $Source, [Parameter()] $Command, [Parameter()] [ValidateRange(1, [int]::maxvalue)][int]$Count, [Parameter()] [switch]$Exact, [Parameter()] [ValidateLength(1, 1024)]$Header, [Parameter()] [switch]$AcceptSourceAgreement ) begin { [string[]] $WinGetArgs = @("List") [WinGetPackage[]]$Result = @() [string[]] $IndexTitles = @("Name", "Id", "Version", "Available", "Source") if ($Filter) { ## Search across Name, ID, moniker, and tags $WinGetArgs += $Filter } if ($PSBoundParameters.ContainsKey('Name')) { ## Search for the Name $WinGetArgs += "--Name", $Name.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Id')) { ## Search for the ID $WinGetArgs += "--Id", $Id.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Moniker')) { ## Search for the Moniker $WinGetArgs += "--Moniker", $Moniker.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Tag')) { ## Search for the Tag $WinGetArgs += "--Tag", $Tag.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Source')) { ## Search for the Source $WinGetArgs += "--Source", $Source.Replace("…", "") } if ($PSBoundParameters.ContainsKey('Count')) { ## Specify the number of results to return $WinGetArgs += "--Count", $Count } if ($Exact) { ## Search using exact values specified (case sensitive) $WinGetArgs += "--Exact" } if ($PSBoundParameters.ContainsKey('Header')) { ## Pass the value specified as the Windows-Package-Manager HTTP header $WinGetArgs += "--header", $Header } if ($AcceptSourceAgreement) { ## Accept source agreements $WinGetArgs += "--accept-source-agreements" } } process { $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles $IndexTitles foreach ($Obj in $List) { $Result += [WinGetPackage]::New($Obj) } } end { return $Result } } |