I had installed Zotero using winget install Zotero.Zotero and it installed fine in C:\Program Files (x86)\Zotero. But when I run winget upgrade, it shows two Zotero versions, like so:

Name   Id            Version Available Source
Zotero Zotero.Zotero 6.0.10  6.0.13    winget
Zotero Zotero.Zotero 6.0.9   6.0.13    winget
2 upgrades available.

I have verified that the currently installed Zotero version is 6.0.13. Since I have had prior installations of Zotero with and without winget, I think, these entries might reflect those installations. So, I wanted to uninstall / remove these without removing version 6.0.13, currently installed at C:\Program Files (x86)\Zotero.

My question is, how do I make winget show the installation directories for these two versions, so that I can manually remove them?


4 Answers 4


Update 2023-04-17

It seems winget version v1.5.1081-preview and above (those including PR3128), include info on default directories by running winget --info.

output from winget --info

There's also an open issue to be able to list the directories per app (Issue 2298).

Regarding Zotero itself, I couldn't find a package with ID Zotero.Zotero, but did find DigitalScholar.Zotero. That shows that the default installer's used, so the default path would be the same as the app's (from hunting around their docs this seems to be C:\Program Files (x86)\Zotero, though I've not seen anything explicit).

Note: It's possible that your additional version of Zotero.Zotero doesn't exist on disk; but only exists in WinGet's database (e.g. if it were installed then the path deleted without WinGet being aware). See "Failed Attempt to Hunt Out Metadata" for info on how to query that database).

Original Answer

The exact location depends on the package & so far as I can tell there's currently no way to fetch that info for all installed winget packages.

For those which don't have installers, but are just files downloaded, they're put under a folder under: %localappdata%\microsoft\winget\packages

Where there's an exe with a portable command alias (i.e. to avoid having to add each exe's path to your PATH variable), a symlink is created. That symlink is held in %localappdata%\Microsoft\WinGet\Links\.

Note: Some apps' manifests may specificy a default install directory. That's given in their InstallLocation property (see schema).

Failed Attempt to Hunt Out Metadata

I wondered if you could find the path under which WinGet stores the metadata of packages installed... I couldn't - but notes below in case this helps others hunt deeper (my conclusion is that WinGet doesn't remember where it installs things, only that it has installed them / what version it installed; everything else is left to the default installer).

You can get the path for its settings file by running winget settings then looking at the path of the settings.json file that this opens. For me this was: C:\Users\myUsername\AppData\Local\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json

By poking around in that directory I found a SQLLite DB: C:\Users\myUsername\AppData\Local\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\Microsoft.Winget.Source_8wekyb3d8bbwe\installed.db.

We can query this file/database using the below PowerShell:

# Load the System.Data.SQLite.dll assembly.  This is likely already somewhere on your machine, but if you can't find it, see https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki
Add-Type -Path 'C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\PrivateAssemblies\System.Data.SQLite.dll'

# Update this path with your install.db path
$installDbPath = 'C:\Users\myUsername\AppData\Local\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\Microsoft.Winget.Source_8wekyb3d8bbwe\installed.db'

# create a connection to this db
$con = [System.Data.SQLite.SQLiteConnection]::new("Data Source=$installDbPath")

# Create and execute a query to list all tables (thanks to https://stackoverflow.com/a/14623907/361842 for the SQL)
$command = $con.CreateCommand()
$command.CommandText = @"
SELECT name FROM sqlite_master
  WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'
SELECT name FROM sqlite_temp_master
  WHERE type IN ('table','view')
$data = [System.Data.DataSet]::new()
$adapter = [System.Data.SQLite.SQLiteDataAdapter]::new($command)
$adapter.Fill($data) | Out-Null

# channels
# commands
# commands_map
# ids
# manifest
# manifest_metadata
# metadata
# monikers
# names
# norm_names
# norm_names_map
# norm_publishers
# norm_publishers_map
# pathparts
# pfns
# pfns_map
# productcodes
# productcodes_map
# tags
# tags_map
# versions

# Now repeat over the IDs table to give the IDs of all installed packages
$command.CommandText = "SELECT * FROM ids"
$data = [System.Data.DataSet]::new() # reset this to avoid appending
$adapter.Fill($data) #note: adapter has a reference to $command, so by updating the command text the adapter's command is automatically updated
$data.Tables.Rows | ft -AutoSize

# sadly I hunted through all the other tables but couldn't find any hint of an installation directory being stored here
  • 2
    This is a very helpful answer, not that it helped me actually find the installed package in question in my own circumstance but it helped me remember that WinGet is not a proper package manager and I shouldn't expect even basic functionality like this, alas. C'est la vie!
    – keithzg
    Apr 14, 2023 at 23:30
  • 1
    New manifest/schemas are now located here.
    – not2qubit
    Dec 7, 2023 at 4:01

I couldn't find anything matching among winget command line options.

But a partial workaround is to use where command to search by executable name.

Like where zotero

  • 4
    Thank you for the answer. The issue with where is that one needs to already have some idea as to where the program might have been installed or the program needs to have been added to path. In my case, neither was true. My issue was actually with how some programs fail to remove Registry entries when uninstalled, causing winget to report multiple versions. Those other Zotero versions weren't really installed.
    – P_0
    Oct 6, 2022 at 6:55
  • On that note, this is what had helped me remove the other versions - github.com/microsoft/winget-cli/issues/….
    – P_0
    Dec 12, 2022 at 7:22

To the ones still looking for an answer, this works for me:

winget list -q $id | Out-Null
if ($?) {  echo "$id installed" }
  • This does not produce the installation location for me, only whether an $id is installed. I am using winget v1.7.10661.
    – P_0
    Mar 20 at 14:37

I have installed hurl with winget install hurl

To find where it has been installed, I have done the next

  1. winget uninstall hurl
  2. have seen warning about changes (that may be dependent on CLI used)
  3. have seen uninstall popup where I was able to see path

That is an uninstall popup: uninstall popup

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .