Using winget to automate software deployment to a new laptop

2023-02-17  Technology,   Programming

I got my first new laptop in six years this week! The new hardware is definitely exciting, but reviews aren’t really my thing, so while I’ll inevitably tweet about how the Microsoft Surface Laptop fares, that’s not the purpose of this post. This is more about the mundane job of porting all my usual applications over to a new PC, and a handy new Windows feature that helped to make things a little easier - winget.

Before we get started, I want to acknowledge both that I’m late to the party on winget and that there have been package managers around on Windows for years - but it’s certainly a cool and useful addition to the core operating system, which bucks the trend when you consider how frequently Microsoft removes more advanced features and options these days (or at least applies confusing double UIs).

I’ll also concede that taking the time to write a PowerShell script to automate software deployment is probably overkill for most users - myself included. The time spent on development and testing is probably greater than the amount of time it would take to download and install each package individually, but at the end of the day I now have a pre-baked script I can use to drop my software on any future systems.

Initial research

Before I even got as far as creating a PS1 file, my first step was to do some research to identify the software packages I wanted to install. To achieve this, I used the following winget command.

winget search <APP_NAME>

This ran a search across all the configured repositories (by default, basically the Microsoft Store and winget’s own one). The most important details were in the Id column, which generally follows the format Developer.Product. There were a lot of third-party apps that had the names of popular software in their own names, so this helped to sort the wheat from the chaff and identify the real packages.

During this planning stage, I considered the software I wanted to deploy to my new system and ran the winget search command to find the corresponding packages until I had a complete list.

The PowerShell script

Now I could start writing a PowerShell script to iterate through my list of applications and try to install each of them. Firstly, I created an array to store the list (note that only the Id values here match the repository data - the names are my own more readable ones, for display and logging only).

$install_apps = 
    ("Firefox", "Mozilla.Firefox"),
    ("Steam", "Valve.Steam"),
    ("Discord", "Discord.Discord"),
    ("Netflix", "9WZDNCRFJ3TJ"),
    ("Spotify", "Spotify.Spotify")

Next, I used a foreach loop to work through each application in $install_apps and attempt to run winget to install the corresponding package according to its Id, using the --silent flag to keep output to a minimum and require as little user interaction as possible to complete the deployment.

There are a number of reasons why installation of any given application might fail - a missing package or insufficient permissions to name just a couple. To prevent missing software from flying under the radar, I used an if/else statement based on the winget exit code ($LASTEXITCODE) to detect any issues.

foreach ($app in $install_apps) {
    Write-Host "Installing" $app[0] "..."
    winget install --silent --id $app[1]
    if ($LASTEXITCODE -eq 0) {
        Write-Host $app[0] "installation complete."
        Write-Host ""
    } else {
        Write-Host $app[0] "installation failed."
        Write-Host ""
    }
}

And that’s pretty much all I needed to get going! I also added a section to install Windows Subsystem for Linux (with Ubuntu) and a few extra lines to log failures to a file (in case I missed them in the terminal), but the code above would be perfectly adequate to try to install all the packages in the given list.

The results

So how did things go with the new laptop? Did my winget PowerShell script solve all my problems and allow me to kick back and relax as my applications were automatically deployed to my new system?

Well, to tell the complete truth, not quite… But it was very close.

As you can see from the screenshot above, winget undoubtedly made the job much quicker and easier, but it wasn’t entirely hands-off. Spotify was the only app that failed to install for some reason (perhaps because it’s one of those apps that come half-installed on a fresh Windows system?), but there were also a couple of others that required me to hit the Y key to accept licence agreements and terms of use.

I eventually found a solution to this part of the issue - unfortunately just after I ran the script. You can accept licence agreements automatically by using the --accept-source-agreements and --accept-package-agreements parameters when running winget.

Still, it was a fun experiment, saved a lot of time downloading installers from developer websites and running them manually via the GUI, and leaves me with a script that will be easy to repurpose to (almost) automate the setup of any new computers I adopt in future. While winget isn’t the perfect zero-touch solution, I’d definitely recommend giving it a go - particularly if you ever find yourself in a situation where you need to set up multiple systems in a short time and a cheat code would help to preserve your sanity.

Looking for the comments? My website doesn't have a comments section because it would take a fair amount of effort to maintain and wouldn't usually present much value to readers. However, if you have thoughts to share I'd love to hear from you - feel free to send me a tweet or an email.