Skip to content

Instantly share code, notes, and snippets.

@infogulch
Forked from alimbada/Export-Chocolatey.ps1
Last active September 16, 2023 13:47
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save infogulch/0d81c3d4caccf2f1b6a82dc6f6459397 to your computer and use it in GitHub Desktop.
Save infogulch/0d81c3d4caccf2f1b6a82dc6f6459397 to your computer and use it in GitHub Desktop.
Export installed Chocolatey packages as packages.config - thanks to Matty666

Put update.ps1, install.ps1, record.ps1, and packages.config inside a git repository to enable tracking which versions you have installed at any one time. This means you can sync between systems and backup via any git host.

Update procedure is:

git pull
./update.ps1
git commit -m "Updated $env:computername"
git push

Install procedure is:

git pull
# edit packages.config to add <package name="mypackage" />
./install.ps1
git commit -m "Installed mypackage"
git push

It can be very nice to know exactly which versions were installed at some point in history just in case there's an issue with a new version. But it can be trouble to maintain it, so don't worry too much about merging when syncing between different systems; just let it overwrite, then commit with the computer name you updated and push. When you search through your git history you can see which versions were installed on each computer at points in time. (It might be a little messy, but it's fine for a fallback.)

See comments in install.ps1, update.ps1, and record.ps1 for details about what they do.

# ./install.ps1 installs all packages listed in packages.config in the current directory.
#
# It then calls ./record.ps1 to note down the currently installed package versions for all
# packages in packages.config.
#
# * In order to add a new package, add <package name="mypackage" /> line to packages.config
# and run ./install.ps1
# * To update, refer to ./update.ps1
# * To install for the first time / install chocolatey, run:
#
# Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
#
choco feature enable -n useRememberedArgumentsForUpgrades
# upgrade chocolatey first
choco upgrade -y chocolatey
# install packages listed in packages.config
choco install -y packages.config
echo "You may need to run refreshenv / Update-SessionEnvironment to put newly installed programs on the path."
echo "See ./update.ps1 to list and update outdated packages"
./record.ps1
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="7zip.install" version="19.0" />
<package id="adb" version="30.0.4" />
<package id="azure-data-studio" version="1.23.0" />
<package id="bitwarden" version="1.22.2" />
<package id="chocolatey" version="0.10.15" />
<package id="discord.install" version="0.0.308" />
<package id="docker-compose" version="1.27.4" />
<package id="docker-desktop" version="2.4.0.0" />
<package id="dotnetcore-sdk" version="3.1.403" />
<package id="dropbox" version="109.4.517" />
<package id="firacode-ttf" version="5.2" />
<package id="firefox-dev" version="83.0.9-beta" />
<package id="git.install" version="2.29.2.2" packageParameters="/WindowsTerminal /NoShellIntegration" />
<package id="jq" version="1.6" />
<package id="microsoft-edge-insider" version="87.0.664.24" />
<package id="microsoft-teams" version="1.3.00.28779" />
<package id="nodejs.install" version="15.1.0" />
<package id="notepadplusplus.install" version="7.9.1" />
<package id="openjdk11jre" version="11.0.9.11" />
<package id="paint.net" version="4.2.14" />
<package id="postman" version="7.34.0" />
<package id="powershell-core" version="7.0.3" packageParameters="/CleanUpPath" />
<package id="powertoys" version="0.25.0" />
<package id="putty.install" version="0.74" />
<package id="python3" version="3.9.0" />
<package id="shutup10" version="1.8.1415" />
<package id="swi-prolog" version="8.2.2.1" />
<package id="vim" version="8.2.1967" />
<package id="vlc" version="3.0.11" />
<package id="vscode.install" version="1.51.0" packageParameters="/NoDesktopIcon /NoQuickLaunchIcon /NoContextMenuFiles /NoContextMenuFolders" />
<package id="yarn" version="1.22.5" />
</packages>
# ./record.ps1 changes the version numbers listed in packages.config in the current
# directory to the ones currently installed.
#
# * It does not add packages to packages.config that are installed but not currently
# listed, which allows the user to only track the versions of the packages they care
# about, and not all of their transititve dependencies.
#
echo "Writing currently installed package versions to packages.config.."
# get the list of all installed packages and versions
$installed = choco list -lo -r -y | % { @{ id = $($_.SubString(0, $_.IndexOf("|"))); version = $($_.SubString($_.IndexOf("|") + 1)) } }
# take each package listed in packages.config, and rebuild the xml <package /> line but with version set to the currently installed version
$packagelist = select-xml -path .\packages.config -xpath //package `
| % { " <package id=""$($_.node.id)"" version=""$(($installed | where-object id -eq $_.node.id).version)"" $(if ($_.node.packageParameters) { write-output "packageParameters=""""$($_.node.packageParameters)"""" " })/>" } `
| sort-object
# rewrite packages listed in packages.config with versions currently installed
@"
<?xml version="1.0" encoding="utf-8"?>
<packages>
$($packagelist -join "`r`n")
</packages>
"@ | out-file packages.config -encoding utf8
# ./update.ps1 lists all outdated packages and prompts you to update all of them.
# If you respond with 'y' the packages are updated.
#
# It then calls ./record.ps1 to note down the currently installed package versions for all
# packages in packages.config.
#
# always upgrade chocolatey first
choco upgrade -y chocolatey
# list all outdated packages
choco outdated
# prompt to upgrade all listed packages
if ($(read-host "Upgrade all? (Y): ") -eq "y") { choco upgrade all -y }
./record.ps1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment