{"id":14063815,"url":"https://github.com/jjcarrier/PS-WinGet-Essentials","last_synced_at":"2025-07-29T16:32:04.810Z","repository":{"id":182098199,"uuid":"491326148","full_name":"jjcarrier/PS-WinGet-Essentials","owner":"jjcarrier","description":"Provides essential functionality for software management centered around WinGet using PowerShell","archived":false,"fork":false,"pushed_at":"2024-08-17T17:43:48.000Z","size":297,"stargazers_count":10,"open_issues_count":4,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-08-17T18:32:50.869Z","etag":null,"topics":["cli","powershell","utility","winget"],"latest_commit_sha":null,"homepage":"","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jjcarrier.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-12T01:37:27.000Z","updated_at":"2024-08-17T17:34:14.000Z","dependencies_parsed_at":"2024-01-25T04:29:37.115Z","dependency_job_id":"a36da246-0e6b-45c7-a81a-6b971c03b35e","html_url":"https://github.com/jjcarrier/PS-WinGet-Essentials","commit_stats":null,"previous_names":["jjcarrier/ps-winget-essentials"],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjcarrier%2FPS-WinGet-Essentials","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjcarrier%2FPS-WinGet-Essentials/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjcarrier%2FPS-WinGet-Essentials/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jjcarrier%2FPS-WinGet-Essentials/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jjcarrier","download_url":"https://codeload.github.com/jjcarrier/PS-WinGet-Essentials/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228028621,"owners_count":17858419,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","powershell","utility","winget"],"created_at":"2024-08-13T07:03:31.384Z","updated_at":"2024-12-04T01:31:32.042Z","avatar_url":"https://github.com/jjcarrier.png","language":"PowerShell","funding_links":[],"categories":["PowerShell"],"sub_categories":[],"readme":"# WinGet-Essentials PowerShell Module\r\n\r\n[![pwsh version](https://img.shields.io/powershellgallery/v/WinGet-Essentials)](https://www.powershellgallery.com/packages/WinGet-Essentials)\r\n[![pwsh platform](https://img.shields.io/powershellgallery/p/WinGet-Essentials)](https://www.powershellgallery.com/packages/WinGet-Essentials)\r\n[![pwsh downloads](https://img.shields.io/powershellgallery/dt/WinGet-Essentials)](https://www.powershellgallery.com/packages/WinGet-Essentials)\r\n[![CI](https://github.com/jjcarrier/WinGet-Essentials/actions/workflows/ci.yml/badge.svg)](https://github.com/jjcarrier/WinGet-Essentials/actions/workflows/ci.yml)\r\n\r\n## [Table of Contents](#table-of-contents)\r\n\r\n* [Description](#description)\r\n* [Installation](#installation)\r\n* [Upgrading](#upgrading)\r\n* [Update-WinGetSoftware](#update-wingetsoftware)\r\n* [Checkpoint-WinGetSoftware](#checkpoint-wingetsoftware)\r\n* [Restore-WinGetSoftware](#restore-wingetsoftware)\r\n* [Initialize-WinGetIgnore](#initialize-wingetignore)\r\n* [Initialize-WinGetRestore](#initialize-wingetrestore)\r\n* [Merge-WinGetRestore](#merge-wingetrestore)\r\n* [Additional Notes](#additional-notes)\r\n\r\n## [Description](#table-of-contents)\r\n\r\nProvides functionality for improved software management. This module includes\r\nthe following primary functionality:\r\n\r\n* A simple CLI interface for `winget update`:\r\n  * Ignore-Package support, via a `winget.{HOSTNAME}.ignore` file.\r\n  * Tab-completion for locally-cached upgradable packages.\r\n  * An interactive UI for selecting which packages to install.\r\n  * Elevation option to instruct the tool to perform the install as an Administrator.\r\n* A tag-based deployment tool:\r\n  * Installation of suites of self-maintained tagged package-identifiers.\r\n  * Elevation option to instruct the tool to perform the install as an Administrator.\r\n  * A helper cmdlet to detect new package identifiers that have not yet been\r\n    entered into `winget.packages.json`.\r\n* A basic checkpoint command:\r\n  * Takes a backup of the last checkpoint.\r\n  * Saves a list of installed software with version info.\r\n  * This is mostly an alias for `winget export --include-versions`.\r\n\r\n## [Installation](#table-of-contents)\r\n\r\nDownload/install the module from [PSGallery](https://www.powershellgallery.com/packages/WinGet-Essentials):\r\n\r\n```pwsh\r\nInstall-Module -Name WinGet-Essentials -Repository PSGallery\r\n```\r\n\r\nAdd the module to your `$PROFILE`:\r\n\r\n```pwsh\r\nImport-Module WinGet-Essentials\r\n```\r\n\r\nFor first time users, the following steps are recommended for setting up\r\nthe various resources needed by the cmdlets:\r\n\r\n1. Open an Administrator instance of PowerShell\r\n   * Note: This is only necessary if the user's `Local Security Policy` does not\r\n     include them in the `Create symbolic links` entry's `Security Setting`.\r\n     This may be modified under \"Local Policies\\User Rights Assignment\\Create symbolic links\".\r\n2. Change directory to a folder where you wish to store the physical copy of\r\n   the resource files (i.e. the ignore and package list files).\r\n3. Run:\r\n\r\n   ```pwsh\r\n   $ignoreFile = New-Item \"winget.$((hostname).ToLower()).ignore\"\r\n   $packagesFile = New-Item \"winget.packages.json\"\r\n   Initialize-WinGetIgnore -SourceFile $ignoreFile\r\n   Initialize-WinGetRestore -SourceFile $packagesFile\r\n   ```\r\n\r\n4. Run the following which will capture the installed software available on\r\n   WinGet and provide a UI to select what package IDs to add to the list of\r\n   restorable packages. After making the selections the user will be prompted\r\n   to tag each of these packages. The `-MergeAll` switch skips a follow up\r\n   confirmation after the selections have been made from the UI:\r\n\r\n   ```pwsh\r\n   Merge-WinGetRestore -UseUI -MergeAll\r\n   ```\r\n\r\n5. Finally, for any of the packages you opt'd not to add to `winget.packages.json`\r\n   consider adding these to the ignore file that was just created (each entry\r\n   should be on its own line).\r\n\r\nWith the above steps in place, the majority of this module's cmdlets can\r\ngenerally be used without administrator privileges, but for installation of\r\npackages, this will depend on the particular package and whether they support\r\nelevation of permissions.\r\n\r\n## [Upgrading](#table-of-contents)\r\n\r\n### For module versions \u003e= 1.6.1\r\n\r\nTo upgrade from a previously configured installation to a newer release of the\r\nmodule, in an Administrator instance of PowerShell, run:\r\n\r\n```pwsh\r\nUpdate-WinGetEssentials\r\n```\r\n\r\n\u003e [!NOTE]\\\r\n\u003e Module versions \u003e= 1.11.0 do not require this command to run in an Admin\r\n\u003e instance, so long as the user has permissions to create SymLinks.\r\n\r\n### Alternative update method (for module versions \u003c 1.6.1)\r\n\r\nIf desired, it is also possible to perform a more manual upgrade process using\r\n`Update-Module` as shown below and performing the additional actions outlined\r\nin the paragraphs that follow.\r\n\r\n```pwsh\r\nUpdate-Module -Name WinGet-Essentials\r\n```\r\n\r\n\u003e [!NOTE]\\\r\n\u003e If the `WinGet-Essentials` module is already loaded, restart the terminal or\r\n  reload the module explicitly via `Remove-Module` followed by `Import-Module`.\r\n\r\nAfter `Upgrade-Module` completes, it is advisable to run the following commands\r\nin an administrator PowerShell instance to allow new symbolic links to be\r\ncreated. Some cmdlets will attempt to perform this automatically, but it will\r\nonly be possible to create a SymLink if the cmdlet is running in an\r\nadministrator PowerShell instance.\r\n\r\n```pwsh\r\nInitialize-WinGetIgnore\r\nInitialize-WinGetRestore\r\n```\r\n\r\nIt may also be desirable to run the following to have other resources/functions\r\nready to use (such as tab-completion for package IDs with\r\n`Update-WinGetSoftware` or use of `Restore-WinGetSoftware`):\r\n\r\n```pwsh\r\nCheckpoint-WinGetSoftware\r\nUpdate-WinGetSoftware -Sync\r\n```\r\n\r\n\u003e [!NOTE]\\\r\n\u003e The commands above will find the previous module install to determine where\r\n  the resource files reside. If no such files existed, then it will be necessary\r\n  to provide the `-SourceFile` parameter to the associated cmdlets.\r\n\r\n## [Update-WinGetSoftware](#table-of-contents)\r\n\r\nProvides a basic UI for updating software available in a WinGet repository.\r\n\r\n### Aliases\r\n\r\n* `winget-update`\r\n* `winup`\r\n\r\n### Usage\r\n\r\nTo selectively install updates using a simple UI run:\r\n\r\n```pwsh\r\nUpdate-WinGetSoftware\r\n```\r\n\r\n![Update UI](img/winget-update-ui.png)\r\n\r\nTo install a specific package run (supports tab-completion for cached updatable package IDs):\r\n\r\n```pwsh\r\nUpdate-WinGetSoftware \u003cWinGetPackageID\u003e[,\u003cAnotherWinGetPackageID\u003e]\r\n```\r\n\r\n![Update Tab Completion](img/winget-update-cli.png)\r\n\r\nTo update the cached list of upgradable package IDs, run:\r\n\r\n```pwsh\r\nUpdate-WinGetSoftware -Sync\r\n```\r\n\r\n## [Checkpoint-WinGetSoftware](#table-of-contents)\r\n\r\nStores a snapshot of installed software, including versions. This can be used\r\nby WinGet natively to reinstall the listed software. This cmdlet's output\r\nis also needed by other functionality of this module, namely `Merge-WinGetSoftware`\r\nand `Restore-WinGetSoftware` (when using the `-NotInstalled` switch).\r\n\r\nThe checkpoint file and its backup are stored in the same path that this module\r\nresides in. This path may for instance be:\r\n\r\n`$env:USERPROFILE\\Documents\\PowerShell\\Modules\\WinGet-Essentials\\\u003cMODULE_VERSION\u003e\\modules`\r\n\r\n\u003e [!WARNING]\\\r\n\u003e `Uninstall-Module` will indiscriminately remove files in the associated\r\n  module's directory. Consider moving these files to another location. A future\r\n  version of this module will likely provide a user-configurable way to redirect\r\n  this file to other locations.\r\n\r\n### Aliases\r\n\r\n* `winget-checkpoint`\r\n\r\n### Usage\r\n\r\n```pwsh\r\nCheckpoint-WinGetSoftware\r\n```\r\n\r\n## [Restore-WinGetSoftware](#table-of-contents)\r\n\r\nRestores a set of software packages based on a locally, user-managed,\r\n`winget.packages.json` (see `Initialize-WinGetRestore` section below for details\r\non initializing this file).\r\n\r\nThe set of packages to be installed/restored is determined by tags. The tags\r\ncan be used in two ways: `AND-comparison` or `OR-comparison`. This is determined\r\nby the `-MatchAny` switch parameter (default behavior is to `Match All` tags).\r\nThis cmdlet supports tab completions for the user-defined tags found in the\r\n`winget.packages.json` file. A `-NotInstalled` switch can be specified which\r\nwill filter out package IDs that are found in the current `checkpoint` file\r\ngenerated from `Checkpoint-WinGetSoftware`.\r\n\r\n### Aliases\r\n\r\n* `winget-restore`\r\n\r\n### Usage\r\n\r\nExample: All packages containing both \"Dev\" and \"Essential\" tags will\r\nbe presented in a UI for user refinement of which packages to install.\r\n\r\n```pwsh\r\nRestore-WinGetSoftware -Tag Dev,Essential -UseUI\r\n```\r\n\r\n![Restore UI](img/winget-restore-ui.png)\r\n\r\nExample: Install all packages tagged with any of the following: \"Essential\",\r\n\"Desktop\" but not containing \"Dev\".\r\n\r\n```pwsh\r\nRestore-WinGetSoftware -Tag Essential,Desktop -MatchAny -ExcludeTag Dev\r\n```\r\n\r\n![Restore Tab Completion](img/winget-restore-cli.png)\r\n\r\n## [Initialize-WinGetIgnore](#table-of-contents)\r\n\r\nA helper for initializing an instance of `winget.{HOSTNAME}.ignore` for the\r\ncurrent module version. This cmdlet is also called internally by the cmdlets\r\nto attempt automatic migration of previous `winget.{HOSTNAME}.ignore`\r\ninstances to the current version.\r\n\r\n### Adding PackageIdentifiers to the ignore list\r\n\r\nTo ignore a specific package from appearing in the various supported cmdlets,\r\nthe software package's corresponding `PackageIdentifier` (as indicated by the\r\n`winget` command) is to be added to a new line entry in the associated\r\n`winget.{HOSTNAME}.ignore`. Each line should contain a single winget package ID\r\n(verbatim).\r\n\r\n\u003e [!NOTE]\\\r\n\u003e At this time, wild cards are not supported, but may be introduced in a future\r\n  update.\r\n\r\n### Usage\r\n\r\nWith a `winget.{HOSTNAME}.ignore` run the following command in an\r\n__Adminstrator__ PowerShell:\r\n\r\n```pwsh\r\nInitialize-WinGetIgnore -SourceFile .\\winget.{HOSTNAME}.ignore\r\n```\r\n\r\n\u003e [!NOTE]\\\r\n\u003e The `{HOSTNAME}` section should be replaced with the name of the computer as\r\n  determined by the `hostname` command. Technically, the name of this source\r\n  file may be given any name so long as it is symbolically linked, however\r\n  this naming scheme is used to support a centralized cloud backup location\r\n  where multiple ignore files exist targeting different computers.\r\n\r\n\u003e [!WARNING]\\\r\n\u003e While it is possible to have a hard copy of this ignore file placed in\r\n  the module folder, it is recommended to use this cmdlet so that a\r\n  symbolic link is used. This is to avoid accidental deletion during\r\n  `Uninstall-Module`. It also reduces maintenance issues by allowing one\r\n  copy of the file to be used across multiple versions of the module (assuming\r\n  there are no compatibility issues between the versions).\r\n\r\n## [Initialize-WinGetRestore](#table-of-contents)\r\n\r\nA helper for initializing an instance of `winget.packages.json` for the current\r\n`Restore-WinGetSoftware` cmdlet. The `Initialize-WinGetRestore` cmdlet is also\r\ncalled internally by `Restore-WinGetSoftware` to handle migrating previous\r\n`winget.packages.json` instances to the current version.\r\n\r\nWhen using this `Restore-WinGetSoftware` for the first time, the user needs\r\nto manually create/define this JSON file and ideally, create a SymLink to it\r\n(see the [Installation](#installation) section above for details).\r\nThis for instance, may be placed in a cloud backup folder that syncs between\r\ncomputers so that the package list is shared between multiple systems that\r\nare to have similar software packages installed.\r\n\r\n### Setup of winget.packages.json\r\n\r\nThis JSON file is to contain an array of objects describing each package of\r\ninterest. It should, at a minimum, have the following form:\r\n\r\n```json\r\n[\r\n  {\r\n    \"PackageIdentifier\": \"\u003cWINGET_PACKAGE_ID1\u003e\",\r\n    \"Tags\": [\r\n      \"\u003cMY_TAG1\u003e\",\r\n      \"\u003cMY_TAG2\u003e\",\r\n    ]\r\n  },\r\n  {\r\n    \"PackageIdentifier\": \"\u003cWINGET_PACKAGE_ID2\u003e\",\r\n    \"Tags\": [\r\n      \"\u003cMY_TAG1\u003e\",\r\n      \"\u003cMY_TAG3\u003e\",\r\n    ]\r\n  }\r\n]\r\n```\r\n\r\n### Optional JSON keys\r\n\r\nEach entry above may specify various optional key-values which include:\r\n\r\n* Install Location\r\n* Package Version\r\n  * Both weak and strong version locking can be specified through the inclusion\r\n    or omission of the `VersionLock` key.\r\n* Interactive Install\r\n  * Force the install command for a specific `PackageIdentifier` to always\r\n    include `--interactive`. This remains true even `-Force` is specified.\r\n* Additional Arguments\r\n  * Arguments may be passed directly to `winget` to expose all other command\r\n    options that have not been specifically supported by this JSON format.\r\n* Post-installation Commands\r\n  * Supports execution with various control options (error handling/prompts).\r\n\r\nFurther details available in [packages.schema.json](WinGet-Essentials/modules/schema/packages.schema.json)\r\n\r\n### JSON validation\r\n\r\nWhen editing the `winget.packages.json` file, a user may use the available\r\nschema-file for assistance and validation. The following entry may be added\r\n(replacing `\u003cPATH_TO_MODULE\u003e` with the location to the installed\r\n`WinGet-Essentials` module) to a VS Code's user/workspace settings (assuming the\r\nfile is given the default name of `winget.packages.json`):\r\n\r\n```json\r\n\"json.schemas\": [\r\n    {\r\n        \"fileMatch\": [\r\n          \"/winget.packages.json\"\r\n        ],\r\n        \"url\": \"\u003cPATH_TO_MODULE\u003e/modules/schema/packages.schema.json\"\r\n    }\r\n]\r\n```\r\n\r\n### Fake Packages (EXPERIMENTAL)\r\n\r\n\u003e [!NOTE]\\\r\n\u003e Behavior is subject to change in the future.\r\n\r\nAs a side-effect of adding CI testing, there was a need to create a _fake_\r\n`PackageIdentifier` as a way to skip potentially lengthy `winget` install\r\nrequests during test execution and to allow more control over how test execution\r\nflows through the PowerShell logic. A `PackageIdentifier` following the form,\r\n`\u003c*\u003e` will be detected as _fake_ (where * is a wildcard and represents the\r\nuser-defined name of the _fake_ package):\r\n\r\nBecause of this, it is possible to specify `winget.packages.json` entries\r\nthat do not point to a software package to install, rather a series of\r\ncommands/scripts via the `PostInstall` functionality. However, one current\r\nlimitation of this feature is there is no guarantee that `-NotInstalled` will\r\nwork correctly for these packages as they exist outside the scope of `winget`.\r\n\r\nWhile it is certainly handy to provide a unified way to download all tools via\r\none interface, the current advice is to __use this feature sparingly__.\r\n\r\n### Example PostInstall Entry\r\n\r\nBelow is an example entry for installing `python` (version 3.11) from `winget`\r\nand disabling the `winstore` aliases during post-installation. If an error\r\noccurs during install or during post-install command execution the user will be\r\nprompted.\r\n\r\n```json\r\n  {\r\n    \"PackageIdentifier\": \"Python.Python.3.11\",\r\n    \"Tags\": [\r\n      \"Dev\",\r\n      \"Essential\"\r\n    ],\r\n    \"PostInstall\": {\r\n      \"Commands\": [\r\n        \"Remove-Item \\\"$env:LOCALAPPDATA\\\\Microsoft\\\\WindowsApps\\\\python.exe\\\"\",\r\n        \"Remove-Item \\\"$env:LOCALAPPDATA\\\\Microsoft\\\\WindowsApps\\\\python3.exe\\\"\"\r\n      ],\r\n      \"Run\": \"OnSuccess\",\r\n      \"OnError\": \"Prompt\"\r\n    }\r\n  }\r\n```\r\n\r\n### Usage\r\n\r\nWith a `winget.packages.json` created run in an __Adminstrator__ PowerShell:\r\n\r\n```pwsh\r\nInitialize-WinGetRestore -SourceFile .\\winget.packages.json\r\n```\r\n\r\n## [Merge-WinGetRestore](#table-of-contents)\r\n\r\nA helper for detecting package IDs installed on the host system that are not\r\npresent in `winget.packages.json`. This cmdlet will confirm with the user\r\nwhether or not to add the package to the file. If added, the user will also\r\nbe asked what tags to assign the package (if any).\r\n\r\n### Usage\r\n\r\nRunning the command below on two or more systems sharing the same\r\n`winget.packages.json` (i.e. via file sync / cloud storage solutions) will allow\r\nthe user to easily create a superset of software package IDs.\r\n\r\n```pwsh\r\nMerge-WinGetRestore\r\n```\r\n\r\n## [Additional Notes](#table-of-contents)\r\n\r\nOne feature that might be missing from a tool containing the word `Essentials`\r\nis a tab-completion interface for winget itself. This is currently left out of\r\nthis module, but may be included in the future as an optional function to invoke,\r\nin any case this is a trivial feature to add and is well-documented by Microsoft here:\r\n\r\n[Microsoft Learn: WinGet Tab Completion](https://learn.microsoft.com/en-us/windows/package-manager/winget/tab-completion)\r\n\r\nOther code repositories provide suites of tab-completion support for various\r\ncommands such as:\r\n\r\n[PS-TabCompletions Git Repository](https://github.com/jjcarrier/PS-TabCompletions)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjcarrier%2FPS-WinGet-Essentials","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjjcarrier%2FPS-WinGet-Essentials","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjjcarrier%2FPS-WinGet-Essentials/lists"}