Winget PowerShell module

I’ve been using Winget for a while now and whilst it’s fantastic, the command line interface sometimes wasn’t ideal, especially as I tend to live in PowerShell and like to be able to manipulate the output a bit.

For my winget scripts, I have been using some functions put together for an old Microsoft event which simply manipulate the command line output.

I was very excited to learn there is now an official Winget PowerShell module (still in alpha release) with some very exciting commands. In this post I’ll run through installing it and the commands available within it.

I also think this could be the answer to our Company Portal deployment issues, check that out below!

Testing the module

First, we need the module itself:

Install-Module -Name Microsoft.WinGet.Client

Then obviously we need to import it:

import-module -Name Microsoft.Winget.Client

Now we have the module installed, we can dig around and see what it can do:

(Get-Module microsoft.winget.client).ExportedCommands

As we can see, the commands are fairly similar to those available in the standard CLI, only these give us PS Objects to use:

To give an idea of the improvements, lets search for everything and export to a txt file

In the CLI:

winget search "" > c:\temp\wingetcli.txt

It works to an extent, but anything with a large package name is truncated which is a nightmare when trying to automate as then you have to deal with non-absolutes and you risk installing the wrong thing. Let’s use Windows Spotlight as an example:

Windows-Spotlight                           Windows-Spotlight.Windows-Spotliā€¦ 1.0.0.0        Moniker:  winget

Now we can switch to the PowerShell module. As this returns a PS Object, we can use out-gridview rather than messing with txt files

 Find-WinGetPackage "" | out-gridview

That’s an excellent start!

Just to double check:

Find-WinGetPackage "" | where-object Name -eq "Windows-Spotlight"

One which is particularly useful, I tend to search for a package before installing it. With the CLI that was a search and then a second command. With PowerShell, we can simply pipe through:

Find-WingetPackage "appname" | Install-WingetPackage

Ok, so the basic commands work better, but what about these new ones in the list?

Company Portal?

The one I am most excited about is repair-wingetpackagemanager

This command will re-install the Winget application as well as all dependancies. You may well be thinking “so what, Winget never breaks anyway”, BUT there is a huge advantage to this. When deploying a new machine, the Microsoft Store waits 15 minutes from first login before it downloads or updates any applications so the user can start working. This means that your Winget update is stopped and your Company Portal deployment is halted.

Using this PowerShell module and command we could package a Win32 app (or script) to:

  • Install the module
  • Repair Winget to update it
  • Install Company Portal (and any other required apps)

Let’s give it a try:

First we need to install nuget:

        $provider = Get-PackageProvider NuGet -ErrorAction Ignore
        if (-not $provider) {
            Write-Host "Installing provider NuGet"
            Find-PackageProvider -Name NuGet -ForceBootstrap -IncludeDependencies
        }

Then install and import our module

install-module microsoft.winget.client -Force -AllowClobber
import-module microsoft.winget.client

Install/Repair Winget

repair-wingetpackagemanager

Finally install the apps:

install-wingetpackage 9WZDNCRFJ3PZ -source msstore
install-wingetpackage 7zip.7zip

If deploying as an app, you may want to add a reg key, text file etc. at the end to use as a detection method.

Update: This now works in PS5, new script here and original one below:

Install-Module microsoft.winget.client -Force -AllowClobber
Import-Module microsoft.winget.client
repair-wingetpackagemanager
install-wingetpackage 9WZDNCRFJ3PZ -source msstore

Old script

Remember to deploy PowerShell 7 during ESP as a pre-requisite when using this!

Of course, this is one of my posts, so here is a script to sort it for you. It will deploy PS7 (latest version), then install Winget and company portal:

# GitHub API endpoint for PowerShell releases
$githubApiUrl = 'https://api.github.com/repos/PowerShell/PowerShell/releases/latest'

# Fetch the latest release details
$release = Invoke-RestMethod -Uri $githubApiUrl

##Find asset with .msi in the name
$asset = $release.assets | Where-Object { $_.name -like "*msi*" -and $_.name -like "*x64*" }

# Get the download URL and filename of the asset (assuming it's a MSI file)
$downloadUrl = $asset.browser_download_url
$filename = $asset.name

# Download the latest release
Invoke-WebRequest -Uri $downloadUrl -OutFile $filename

# Install PowerShell 7
Start-Process msiexec.exe -Wait -ArgumentList "/I $filename /qn"

# Start a new PowerShell 7 session
$pwshExecutable = "C:\Program Files\PowerShell\7\pwsh.exe"

# Run a script block in PowerShell 7
& $pwshExecutable -Command {
$provider = Get-PackageProvider NuGet -ErrorAction Ignore
if (-not $provider) {
Write-Host "Installing provider NuGet"
Find-PackageProvider -Name NuGet -ForceBootstrap -IncludeDependencies
}
}
& $pwshExecutable -Command Install-Module microsoft.winget.client -Force -AllowClobber
& $pwshExecutable -Command Import-Module microsoft.winget.client
& $pwshExecutable -Command repair-wingetpackagemanager
& $pwshExecutable -Command install-wingetpackage 9WZDNCRFJ3PZ -source msstore

}

You can also grab it from GitHub here:

https://github.com/andrew-s-taylor/public/blob/main/Powershell%20Scripts/Intune/deploy-winget-during-esp.ps1

Things to watch

Remember, this module is still in alpha so some things aren’t perfect, some commands don’t yet accept a pipe pass-through and the get-help needs help itself:

It is open source though so if you have time to help, I am sure it will be very much appreciated!

20 thoughts on “Winget PowerShell module”

  1. Hello Andrew,

    Many thanks for this, this helps me reaching for something I’d like to do, although I can’t seem to do it.

    I tried to bundle all this in an app and make it install as a mandatory app during AutoPilot, but that failed. Then I tried to make it as an app running after AutoPilot, and still no luck.

    If I try to run the lines in PowerShell, it works as expected and installs my list of WinGet apps. Would you please have an idea how to do this step by step? I’m missing something here, I think. Thanks a lot.

    Reply
  2. Thanks for the blog. I added logging, packaged your script as a win32 app and set it to run as system at ESP. On a fresh Win 11 VM it fails and the log shows:
    “The specified module ‘microsoft.winget.client’ was not loaded because no valid module file was found in any module directory.”

    From the ESP page I ran cmd, then powershell Get-module -ListAvailable – microsoft.winget.client was missing from the list of modules.

    I am able to manually run the commands one by one in this window and they succeed and the module is added to the available list.

    I then repeated but set the win32 app to run as user, I am not able to see the log as the user does not have perms to write it but it failed with 0x87d1041c. Any ideas where I am going wrong?

    Reply
    • I got it to work by changing the script block to below. Just waiting to see if my winget app install scripts now work after ESP, previously there was an error until App Installer updated.

      # Run a script block in PowerShell 7
      & $pwshExecutable -Command {
      $provider = Get-PackageProvider NuGet -ErrorAction Ignore
      if (-not $provider) {
      Write-Host “Installing provider NuGet”
      Find-PackageProvider -Name NuGet -ForceBootstrap -IncludeDependencies
      }
      }
      & $pwshExecutable -Command Install-Module microsoft.winget.client -Force -AllowClobber
      & $pwshExecutable -Command Import-Module microsoft.winget.client
      & $pwshExecutable -Command repair-wingetpackagemanager

      Reply
  3. Looks great thanks Andrew – did you notice that there’s now a module that works with PoSh 5.1? might save some PS7 work in your script

    Reply
  4. Is there any equivalent cmdlet to list all available versions of a specific software like we get with winget cli ? Eg:
    winget show Zoom –source winget –versions

    Reply
  5. I am trying to use the new script in PS 5.1 and having issues. Fresh Win 11 install, the script runs as system but winget –version returns v1.2.10691. I tried running as system using psiexec and have the same issue, winget is on v1.2.10691 until I manually run CMD as admin, run the script lines, then it reports the latest version.

    Do you have any ideas? My goal is to update winget to latest and be able to run a script to install packages from winget. In the past I have had to manually update App Installer in the Microsoft Store when reaching the desktop after ESP, then my apps install fine. Trying to eliminate the need for this manual step. Thanks

    Reply
  6. Hey Andrew, have you had any luck getting this to work in PS5.1 under System context? I’m still getting the “This cmdlet is not supported in Windows PowerShell.” Works running as Admin though!

    Reply
  7. Currently using this script to deploy/upgrade/repair WinGet on our endpoints. Thought I would share it here. If anyone has any suggestions for improvement, I would value their feedback.

    function Install-WinGet {
    # Install NuGet package provider
    try {
    $null = Install-PackageProvider -Name NuGet -Force -ErrorAction Stop
    } catch {
    throw “Failed to install NuGet package provider. Error: $_”
    }

    # Install Microsoft.WinGet.Client module
    try {
    $null = Install-Module -Name Microsoft.WinGet.Client -Repository PSGallery -Force -ErrorAction Stop
    } catch {
    throw “Failed to install Microsoft.WinGet.Client. Error: $_”
    } finally {
    # Verify Microsoft.WinGet.Client module installation
    if (-not (Get-Module -ListAvailable -Name Microsoft.WinGet.Client)) {
    throw ‘Microsoft.WinGet.Client was not found. Verify that the module was installed correctly.’
    }
    }

    # Repair WinGet package manager
    try {
    Repair-WinGetPackageManager -ErrorAction Stop
    } catch {
    throw “Failed to repair WinGet package manager. Error: $_”
    }
    }

    # Install/repair WinGet installation
    Install-WinGet

    Reply
  8. Added a check to see if NuGet is already installed, and to only install it if it’s missing.

    function Install-WinGet {
    # Check if NuGet package provider is already installed
    $NuGetInstalled = Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction Ignore

    if (-not $NuGetInstalled) {
    # Install NuGet package provider
    try {
    $null = Install-PackageProvider -Name NuGet -Force -ErrorAction Stop
    } catch {
    throw “Failed to install NuGet package provider. Error: $_”
    }
    }

    # Install Microsoft.WinGet.Client module
    try {
    $null = Install-Module -Name Microsoft.WinGet.Client -Repository PSGallery -Force -ErrorAction Stop
    } catch {
    throw “Failed to install Microsoft.WinGet.Client module. Error: $_”
    } finally {
    # Verify Microsoft.WinGet.Client module installation
    if (-not (Get-Module -Name Microsoft.WinGet.Client -ListAvailable)) {
    throw ‘Microsoft.WinGet.Client was not found. Verify that the module was installed correctly.’
    }
    }

    # Repair WinGet package manager
    try {
    Repair-WinGetPackageManager -ErrorAction Stop
    } catch {
    throw “Failed to repair WinGet package manager. Error: $_”
    }
    }

    Reply

Leave a Comment