Skip to content

Instantly share code, notes, and snippets.

@steviecoaster
Created January 6, 2023 18:40
Show Gist options
  • Save steviecoaster/cc9710730f0c229e99a968a45beec3b4 to your computer and use it in GitHub Desktop.
Save steviecoaster/cc9710730f0c229e99a968a45beec3b4 to your computer and use it in GitHub Desktop.
Chocolatey Sync Kickstart
function Sync-Chocolatey {
[CmdletBinding(SupportsShouldProcess)]
Param(
[Parameter()]
[String]
$OutputDirectory
)
begin {
function GetInstalledApps {
process {
$32BitReg = 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
$64bitReg = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
if ((Test-Path $32BitReg)) {
$32Bit = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName
}
if ((Test-Path $64bitReg)) {
$64Bit = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName
}
$InstalledApps = ($32Bit + $64Bit) | Where-Object { -not [String]::IsNullOrEmpty($_.DisplayName) }
return $InstalledApps
}
}
Function GetTop500Packages {
#Setup OData query
$ODataQuery = @(
'$filter=(IsLatestVersion and (substringof(''Deprecated'', Title) eq false) and (substringof(''.install'', Id) eq false))'
'$orderby=DownloadCount desc'
) -join '&'
$Url = "https://chocolatey.org/api/v2/Packages()?$ODataQuery"
#Collect the top 100 downloaded packages from CCR
if(-not $Script:Data){
$Script:Data = @(
Invoke-RestMethod -Uri ($Url + '&$top=40')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=40')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=80')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=120')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=160')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=200')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=240')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=280')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=320')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=360')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=400')
Invoke-RestMethod -Uri ($Url + '&$top=40&$skip=440')
Invoke-RestMethod -Uri ($Url + '&$top=20&$skip=480')
) | Where-Object { -not [String]::IsNullOrEmpty($_.properties.Title) } |Select-Object -Property @(
@{ Name = 'Downloads'; Expression = { $_.properties.DownloadCount.InnerText } }
@{ Name = 'Title'; Expression = { $_.properties.Title } }
@{ Name = 'Id'; Expression = { $_.title.InnerText } }
)
}
return $Script:Data
}
}
process {
$Data = GetTop500Packages
#Create a collection for the map, and populate from OData query results
$map = [System.Collections.Generic.List[psobject]]::new()
$Data | Foreach-Object {
$h = [PsCustomObject]@{DisplayName = $_.Title ; PackageId = $_.Id }
$map.Add($h)
}
#Validate that Programs and Features entry is in the top 100 packages
$Applications = GetInstalledApps
foreach ($App in $Applications) {
Write-Verbose -Message "Syncing: $($App.DisplayName)"
$MapItem = $map.Where({($app.DisplayName -match [Regex]::Escape($($_.Displayname -replace "(.*)\(.*(86|64).*\)?",'$1'))) -or ($_.DisplayName -match [Regex]::Escape($($app.Displayname -replace "(.*)\(.*(86|64).*\)?",'$1').Trim()))},1)
if ($MapItem) {
if ($PSCmdlet.ShouldProcess("choco sync --id='$($App.DisplayName)' --package-id='$($MapItem.PackageId.ToLower())'", "Sync Command")) {
if(-not $OutputDirectory){
$chocoArgs = @('sync',"--id='$($App.DisplayName)'","--package-id='$($MapItem.PackageId.ToLower())'")
} else {
$chocoArgs = @('sync',"--id='$($App.DisplayName)'","--package-id='$($MapItem.PackageId.ToLower())'","--output-directory='$OutputDirectory'")
}
& choco @chocoArgs
}
}
else {
Write-Warning "Installed application not in map!"
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment