To get a list of installed programs using PowerShell, read the Uninstall keys in the registry with Get-ItemProperty. That’s the same data Windows shows in Settings > Apps > Installed apps, and it works without admin rights.
Here’s the short version. It checks the 64-bit, 32-bit and per-user locations and prints each program’s name, version and publisher:
Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue |
Where-Object DisplayName |
Select-Object DisplayName, DisplayVersion, Publisher |
Sort-Object DisplayName
Below, I’ll turn that into a reusable function, check whether one program is installed, export the list to CSV, and cover winget, Microsoft Store apps, Get-Package and remote computers.
I tested everything on a Windows 11 PC in both PowerShell 7.6 and Windows PowerShell 5.1. When the two versions behave differently, I’ll point it out.
List installed programs from the registry
Windows keeps an Uninstall entry for almost every desktop program. Setup tools write the display name, version, publisher and install date there.
This example reads all three locations, drops empty keys and shows the first ten Microsoft programs on my machine:
$paths = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*'
Get-ItemProperty -Path $paths -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -and $_.SystemComponent -ne 1 -and -not $_.ParentKeyName } |
Select-Object DisplayName, DisplayVersion, Publisher |
Sort-Object DisplayName -Unique |
Where-Object Publisher -eq 'Microsoft Corporation' |
Select-Object -First 10 |
Format-Table -AutoSize
Output:
DisplayName DisplayVersion Publisher
----------- -------------- ---------
Active Directory Rights Management Services Client 2.1 1.0.5406.9 Microsoft Corporation
Copilot 154.0.4258.37 Microsoft Corporation
IIS 10.0 Express 10.0.08009 Microsoft Corporation
Microsoft .NET SDK 7.0.403 (x64) from Visual Studio 7.4.323.52024 Microsoft Corporation
Microsoft 365 - en-us 16.0.20430.20048 Microsoft Corporation
Microsoft 365 Apps for enterprise - en-us 16.0.20430.20048 Microsoft Corporation
Microsoft Edge 154.0.4258.37 Microsoft Corporation
Microsoft ODBC Driver 17 for SQL Server 17.10.6.1 Microsoft Corporation
Microsoft OneNote - en-us 16.0.20430.20048 Microsoft Corporation
Microsoft PowerBI Desktop (x64) 2.157.1354.0 Microsoft Corporation

The SystemComponent and ParentKeyName filters hide background components and updates. I’ll explain them in the function section below.
Remove the Where-Object Publisher and Select-Object -First 10 lines to see everything. On my PC, that’s 54 programs.
Why check three registry keys?
If you only read one key, you’ll miss programs. Each location holds a different kind of install:
| Registry path | What it contains |
|---|---|
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall | 64-bit programs installed for all users |
HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall | 32-bit programs on 64-bit Windows |
HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall | Per-user installs, such as VS Code (User) or Zoom |
The per-user key only shows programs for the account running the script. Another user’s per-user apps live in their own registry hive, so an admin script won’t see them there.
Microsoft documents the values you’ll find in these keys, like DisplayName, DisplayVersion and InstallDate, in the Uninstall Registry Key reference.