How to upgrade PowerShell 7 on Windows 10 and 11

PowerShell 7 installs beside Windows PowerShell 5.1, it does not replace it. How to upgrade with winget, the MSI, the ZIP or the MSIX package, and what changes after 7.6.

Windows ships with Windows PowerShell 5.1 and always will. PowerShell 7 is a separate product with its own executable, pwsh.exe, and it installs alongside 5.1 rather than replacing it. Upgrading therefore means one of two things: moving an existing PowerShell 7 install to a newer 7.x release, or installing 7 for the first time on a machine that only has 5.1.

This guide covers both, on Windows 10 and Windows 11, with four of the five installation methods Microsoft documents for Windows (the fifth, the .NET global tool, is aimed at developers). The current release at the time of writing (September 2026) is 7.6.6, the current LTS release. Two recent changes decide which method is right for you: since the 7.6.0 package, winget installs the MSIX package by default, and Microsoft states there will be no MSI package from PowerShell 7.7.0 onwards.


Quick answer

If PowerShell 7 is already installed and winget can see it, one command upgrades it:

winget upgrade --id Microsoft.PowerShell

Winget keeps the package format you already have, MSI or MSIX. For a first install on a machine that runs scripts, ask for the MSI explicitly, because without --installer-type wix winget now installs the per-user MSIX package:

winget install --id Microsoft.PowerShell --source winget --installer-type wix

Close and reopen the terminal afterwards, then confirm with $PSVersionTable.PSVersion.

Note: Newer versions of PowerShell 7 replace the previous 7.x version. Windows PowerShell 5.1 is untouched, and powershell.exe keeps working exactly as before.

Check what you are actually running

Before you upgrade anything, find out which shell the window in front of you is. The blue Windows PowerShell icon and the black PowerShell 7 icon look similar enough that people upgrade the wrong thing. One line prints both the version and the edition:

"$($PSVersionTable.PSVersion) $($PSVersionTable.PSEdition)"

Core means PowerShell 7. Desktop with a version starting 5.1 means Windows PowerShell, and no amount of upgrading will change that number, because 5.1 is a Windows component.

Next, find out how PowerShell 7 was installed, because Microsoft advises upgrading with the same method. Microsoft’s documented way to tell is to read $PSHOME from inside pwsh:

$PSHOME
$PSHOME isInstalled with
$Env:ProgramFiles\PowerShell\7Probably the MSI (confirm in Programs and Features)
Starts with $Env:ProgramFiles\WindowsApps\The MSIX package (Microsoft Store, winget default since 7.6.0, or a manual msixbundle)
$HOME\.dotnet\toolsThe .NET global tool
Anything elseMost likely the ZIP package

To see what winget knows about, and whether it has an upgrade to offer:

winget list --id Microsoft.PowerShell --upgrade-available

Method 1: winget, for desktops

Microsoft recommends winget for Windows clients. It is included in Windows 11 and in Windows Server 2025 as part of the App Installer, and on Windows 10 it arrives with the same App Installer package. It is not available on Windows Server 2022 or earlier, and Windows Server 2025 has it only with the Desktop Experience.

First install, MSIX package (the default since 7.6.0):

winget install --id Microsoft.PowerShell --source winget

First install, MSI package, installed for all users:

winget install --id Microsoft.PowerShell --source winget --installer-type wix

Later upgrades, whichever format you chose:

winget upgrade --id Microsoft.PowerShell

To pick up preview builds for testing, the package identifier is different. Previews install side by side with the stable version:

winget install --id Microsoft.PowerShell.Preview --source winget
Watch out: The upgrade replaces files in the PowerShell folder, so close every pwsh window first, including the one embedded in VS Code and any Windows Terminal tab. Run the upgrade from Windows PowerShell or cmd.exe rather than from the pwsh you are replacing.

Method 2: the MSI, for servers and fleets

Microsoft calls the MSI the best choice for Windows Server and enterprise deployment. It installs for all users and accepts remote sessions, which the MSIX package cannot. Download it from the PowerShell releases page, choosing the x64 or arm64 build to match the machine, then install it silently. This is Microsoft’s own example with every option switched on:

$msiParams = @(
    '/package'
    'PowerShell-7.6.6-win-x64.msi'
    '/quiet'
    'ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1'
    'ADD_FILE_CONTEXT_MENU_RUNPOWERSHELL=1'
    'ENABLE_PSREMOTING=1'
    'REGISTER_MANIFEST=1'
    'USE_MU=1'
    'ENABLE_MU=1'
    'ADD_PATH=1'
)
msiexec.exe @msiParams
PropertyWhat it does
USE_MUOpts into updates through Microsoft Update, WSUS or Configuration Manager. Default 1.
ENABLE_MUOpts into Microsoft Update for Automatic Updates. Default 1. Setting it to 0 does not remove a setting made earlier, and Group Policy can overrule it.
ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELLAdds the Open PowerShell item to the Explorer context menu.
ADD_FILE_CONTEXT_MENU_RUNPOWERSHELLAdds the Run with PowerShell item to the Explorer context menu.
ENABLE_PSREMOTINGEnables PowerShell remoting during installation.
REGISTER_MANIFESTRegisters the Windows event logging manifest for PowerShell 7.
ADD_PATHAdds PowerShell to the PATH environment variable.
DISABLE_TELEMETRYOpts out of telemetry by setting POWERSHELL_TELEMETRY_OPTOUT.

Installing a newer MSI replaces the previous PowerShell 7 version, so there is no need to uninstall 7.5 before installing 7.6. The install folder is $Env:ProgramFiles\PowerShell\7 for every release, which is why a newer version cannot sit next to an older one this way.

Plan for 7.7: Microsoft states that beginning with the PowerShell 7.7.0 release there is no MSI package, and winget installs only the MSIX package. A deployment that depends on the MSI and its properties will need a new plan before 7.7 reaches your servers.

Method 3: the ZIP, for side-by-side testing

The ZIP package installs nothing. You extract it and run pwsh.exe from wherever you put it, which makes it the right choice when you need to test a script against another build without changing what the machine runs by default. Depending on how you downloaded it, unblock the file first:

Unblock-File -Path .\PowerShell-7.6.6-win-x64.zip
Expand-Archive -Path .\PowerShell-7.6.6-win-x64.zip -DestinationPath C:\PS766
C:\PS766\pwsh.exe -NoProfile -Command '$PSVersionTable.PSVersion'

Nothing is added to PATH, no Start menu shortcut is created and the installer’s prerequisite checks do not run, so WSMan remoting needs its prerequisites met by hand. Delete the folder and the build is gone. The trade-off is that it receives no updates, so treat a ZIP copy as disposable rather than as an install.


Method 4: the MSIX package

This is the Microsoft Store package, the same package winget now installs by default, and the one you get from a manual .msixbundle download with Add-AppxPackage. The Store copy updates itself through Windows, which is convenient on a personal machine. Its limits come from the application sandbox, and Microsoft lists them plainly:

  • It installs for a single user. There is no all-users option.
  • The application folder, $PSHOME, is read-only. That blocks Register-PSSessionConfiguration, Set-ExecutionPolicy -Scope LocalMachine, Update-Help -Scope AllUsers and Enable-ExperimentalFeature -Scope AllUsers, and the all-users profile scripts cannot be created.
  • Remote sessions cannot connect to it, because the WSMan configuration lives in that folder. Outbound SSH remoting and user-level settings work.

The PowerShell package is exempt from the file and registry virtualisation that other packaged apps get, so ordinary writes from your scripts land where you expect, on Windows 10 version 1903 or later.

Watch out: Use the MSI on any machine that receives remote sessions or needs machine-wide settings. The MSIX package suits personal, interactive use.

Which method to use

MethodBest forUpdatesSide by side
wingetWindows 10 and 11 desktopsFollows the package it installed, or winget upgradeNo
MSIServers, imaging, group deploymentMicrosoft Update, on by defaultNo
ZIPTesting a build, Server Core, portable useNoneYes
MSIX (Store)Personal, interactive useAutomaticNo

Verify the upgrade and your scripts

Open a new terminal, because the old one still holds the previous PATH, and check the version numerically rather than as text:

if ($PSVersionTable.PSVersion -ge [version]'7.6.0') {
    Write-Host "Running $($PSVersionTable.PSVersion)" -ForegroundColor Green
} else {
    Write-Warning "Still on $($PSVersionTable.PSVersion), the new build is not the default yet"
}
Note: Compare versions, not strings. '7.10.0' -ge '7.6.0' returns False, because strings compare character by character, while [version]'7.10.0' -ge [version]'7.6.0' returns True. In PowerShell 7, $PSVersionTable.PSVersion is a SemanticVersion, and comparing it with a [version] works as shown above.

Then check that the modules your scripts rely on still load. PowerShell 7 searches its own module folders first: Documents\PowerShell\Modules for the current user and $Env:ProgramFiles\PowerShell\Modules for all users. Modules you installed for the current user under 5.1, in Documents\WindowsPowerShell\Modules, are not in that list. List what 7 can actually see:

Get-Module -ListAvailable | Sort-Object Name | Select-Object Name, Version, ModuleBase

For a Windows-only module that has no PowerShell 7 build, load it through the Windows PowerShell compatibility feature instead of rewriting it:

Import-Module ServerManager -UseWindowsPowerShell

That runs the module in a background Windows PowerShell 5.1 session named WinPSCompatSession and proxies the cmdlets, so objects come back deserialised. Three modules are on the default deny list and will not load this way: PSScheduledJob, BestPractices and UpdateServices. It is a bridge, not a fix, but it keeps existing scripts working while you migrate them.


Problems you will actually hit

pwsh is not recognised after installing

The installer updated the machine PATH, but your open shell captured the old one at launch. Close every terminal and open a new one. A ZIP copy is never on PATH. If it still fails, confirm the install folder exists and check the current PATH:

Get-ChildItem 'C:\Program Files\PowerShell'
$env:PATH -split ';' | Select-String PowerShell

winget reports no applicable upgrade

Check where the install came from with $PSHOME, as shown above. A ZIP copy is invisible to winget, because nothing was registered. Run winget list --id Microsoft.PowerShell --upgrade-available; if the install is not listed, upgrade it the way it was installed, or uninstall it and reinstall through winget.

Scheduled tasks still run the old version

A task whose action is powershell.exe runs Windows PowerShell 5.1, no matter what you installed. Change the action to pwsh.exe with its full path. Tasks also fail for reasons that have nothing to do with the version, which is a separate problem worth ruling out.

The profile you spent hours on is gone

It is not gone, it is in the other folder. The two editions keep separate profiles:

EditionCurrent user profile
Windows PowerShell 5.1Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
PowerShell 7Documents\PowerShell\Microsoft.PowerShell_profile.ps1

Run $PROFILE in each to see the exact path on your machine, then copy across what you still want.

Scripts fail with an execution policy error

PowerShell 7 keeps its execution policy in its own powershell.config.json files: the current user setting in a user-specific file and the machine setting in $PSHOME. A policy set with Set-ExecutionPolicy in 5.1 does not carry over. Check and set it in the new shell:

Get-ExecutionPolicy -List
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

On the MSIX package the LocalMachine scope cannot be set, because $PSHOME is read-only.


Keep it updated without thinking about it

Each package has its own update path, and the hands-off one for servers is Microsoft Update. The MSI opts into it by default (USE_MU=1 and ENABLE_MU=1), after which new 7.x releases arrive through Windows Update for Business, WSUS, Configuration Manager or the Windows Update page in Settings, subject to your Group Policy. The Microsoft Store package updates itself through Windows. A winget install is updated when someone runs winget upgrade.

PowerShell also tells you itself. When update notification is on, it checks whether more than 24 hours have passed since the last check and, if a newer release exists, shows a notice with the startup banner. The environment variable POWERSHELL_UPDATECHECK controls it: Off turns it off, LTS notifies only about LTS releases, and Default is the same as not setting it. It must be set before PowerShell starts, so set it at machine level, from an elevated prompt, on servers where the notice clutters logs:

[Environment]::SetEnvironmentVariable('POWERSHELL_UPDATECHECK', 'Off', 'Machine')
Result: pwsh opens on the current release, 5.1 still runs everything that depended on it, and your scheduled jobs point at the executable you meant.

Official documentation


  • cURL converter turns a copied curl command into a PowerShell Invoke-RestMethod snippet, ready to run in the pwsh you just installed.

Five cheat sheets, one PDF

Subnet masks, PowerShell, Linux commands, HTTP status codes and the ESXi command line - one page each, free to keep. Leave an address and it arrives in a minute.