Skip to content

Let's move PSModulePath out of the documents folder #15552

Description

@JohnLudlow

Summary of the new feature/enhancement

The documents folder has always been where modules user-scoped are kept, and that's always been ok, but I recently discovered some problems with this as I've been getting more familiar with Azure and my work laptop maps Documents to OneDrive. This can be problematic for a few reasons, such as OneDrive not syncing correctly or trying to restore a bunch of files from a module I just uninstalled. This is particularly an issue with larger modules (or groups of modules) such as Az.*

We can certainly wish OneDrive was better at its job, but really these files shouldn't be there - they are not documents. The user is not expected to edit them or look at them. They are more akin to application files or application data. There's no value to them being in OneDrive other than to transfer them to another machine, and that can be better achieved by having a script in OneDrive that calls PSDepend or PowerShellGet to install modules on that other machine.

I have updated my profile script to remove this path but it reappears after running install-module.

Proposed technical implementation details (optional)

  1. Remove Documents\PowerShell\Modules from the $env:PSModulePath default. Select a new default path such as ~\PowerShell\Modules or $env:localappdata\PowerShell\Modules
  2. Offer a cmdlet or documentation to move the existing modules to the new location, and optionally update the value of the environment variable.
  3. Additionally, offer to move the existing modules and update the value of the environment variable during the install. (That way the user has the choice to make the install take care of it or do it later at a time of their choosing).

Activity

  1. added
    Issue-Enhancementthe issue is more of a feature request than a bug
    Needs-TriageThe issue is new and needs to be triaged by a work group.
    on Jun 9, 2021
  2. jeroenlandheer commented on Jun 27, 2021

    @jeroenlandheer

    A few extra things to consider when putting this up for triage:

    • When I install a module on one machine and I am later at a different PC, OneDrive updates the modules folder... but Upgrade-Module doesn't work anymore, because it says the module wasn't installed with Install-Module ... (which it was, just not at the machine I'm working on.)
    • If your module folder is big loading PowerShell can take a (very) long time because it will wait until OneDrive has pulled all the files to your machine.

    I think this change should happen... hopefully soon. I think storage for these modules should be in the %userpfile%\AppData\Local folder, this is the place for things that should not get synced with other machines.

    PS: I create PowerShell modules... I have a lot of them... and they are all on my OneDrive now. 😒

  3. iSazonov commented on Jun 28, 2021

    @iSazonov
    Collaborator

    Jeroen Landheer (@jeroenlandheer) Do you mean Update-Module? If so you couls discuss in PowerShellGet repository.

  4. JohnLudlow commented on Jun 30, 2021

    @JohnLudlow
    Author

    Ilya (@iSazonov) Would the PowerShellGet guys be able to change the default value of $env:PSModulePath and update the installer to optionally update it on upgrade?

    Though there should probably be a second issue in PowerShellGet to respect the value, not overwrite it.

  5. iSazonov commented on Jun 30, 2021

    @iSazonov
    Collaborator

    JohnLudlow Any changes related to PSModulePath are breaking changes. We need to keep backward compatibility.

  6. jeroenlandheer commented on Jun 30, 2021

    @jeroenlandheer

    Ilya (@iSazonov) Sorry, that was a typo. This should indeed go there too, but don't you think they will choose the location of the modules where they install them... based on whatever this teams says it should be? (AFAIK there's no way to customize this with settings, but that's something for another day.)

    If paths for loading the modules is the primary function of PSModulePath, this issue can be solved quite easily:

    1. Designate a folder somewhere in %LocalAppData%\...
    2. Tell others that installing modules in this folder is best practice.
    3. Put both paths in PSModulePath (i.e. %LocalAppData%\.. and %userprofile%\Documents\...)
    4. Ensure the new location is added to new installations in the PSModulePath environment variable.

    No need to move stuff around, new things get installed in %LocalAppData%\.. and old modules that are still in the user's documents folder keep working. Maybe this doesn't even require a code change in PowerShell, just some changes in the installer.

    And now we're on this subject, in Windows installations, modules which are installed on the local machine are installed by default in the Program files\PowerShell\Modules folder. I think the correct place for this should be %AllUsersProfile%\... (often called C:\ProgramData)

    AFAIK the functionality of PSModulePath itself doesn't change with all of this, so this is technically not a breaking change.

    Hope this helps.

  7. JohnLudlow commented on Jul 1, 2021

    @JohnLudlow
    Author

    Jeroen Landheer (@jeroenlandheer) Indeed, and if I do want to move the older modules to the new folder (I probably would, in my case), there are some options:

    • Offer to do that in the installer
    • Offer a tool (such as a cmdlet) to do it post-install
    • Offer documentation that says "you can copy everything from <old location> to <new location>"

    Any of those would work for me, but some people may appreciate it being done for them.

    And you're absolutely correct IMHO about the Windows Modules. The only modules that should be there are ones that are installed as part of PowerShell and shouldn't be removed.

  8. SeeminglyScience commented on Jul 1, 2021

    @SeeminglyScience
    Contributor

    AFAIK the functionality of PSModulePath itself doesn't change with all of this, so this is technically not a breaking change.

    While I agree that it would be hard to claim this is explicitly a breaking change of an API, it would still be disruptive. There has never been a supported way of determining the module paths of different scopes, e.g. no PSModuleInfo.AllUsersModuleRepository or similar. Any tools looking to interact with the module directories explicitly has been required to hard code the path, so any location change here will break these tools.

    (Note that I'm not necessarily advocating against it, but it's something that needs to be considered)

  9. rjmholt commented on Aug 11, 2021

    @rjmholt
    Collaborator
  10. kilasuit commented on Aug 11, 2021

    @kilasuit
    Collaborator

    Previously discussed in #8069 too

  11. 93 remaining items

  12. cimares commented on Aug 27, 2024

    @cimares

    Just to add to one of the issues that OneDrive introduces when the Documents folder is included in the sync, and that is retention policies. My organisation defines a OneDrive retention policy of 5 years since Last modified. This means that large chunks of the PS Module path get deleted at odd times, resulting in incomplete module packages which have to be recovered from the OneDrive Recycle bin.

    Moving user level modules out of Documents is a critical need when OneDrive retention is in the mix.

  13. JustinGrote commented on Sep 4, 2024

    @JustinGrote
    Contributor

    I made a function that uses some private methods on the config and merges them with the API from #19422 to demonstrate what I think the actual public API should look like/behave as so that tools such as PowerShellGet and ModuleFast can all use the same relevant implicit installed modules path if not specified otherwise.

    #Fetches the module path for the current user or all users
    function Get-PSModulePath ([Switch]$AllUsers) {
    	$scopeType = [Management.Automation.Configuration.ConfigScope]
    	$pscType = $scopeType.
    	Assembly.
    	GetType('System.Management.Automation.Configuration.PowerShellConfig')
    
    	$pscInstance = $pscType.
    	GetField('Instance', [Reflection.BindingFlags]'Static,NonPublic').
    	GetValue($null)
    
    	$getModulePathMethod = $pscType.GetMethod('GetModulePath', [Reflection.BindingFlags]'Instance,NonPublic')
    
    	if ($AllUsers) {
    		$getModulePathMethod.Invoke($pscInstance, $scopeType::AllUsers) ?? [Management.Automation.ModuleIntrinsics]::GetPSModulePath('BuiltIn')
    	} else {
    		$getModulePathMethod.Invoke($pscInstance, $scopeType::CurrentUser) ?? [Management.Automation.ModuleIntrinsics]::GetPSModulePath('User') 
    	}
    }

    In my opinion the #19422 API should have an additional override bool parameter to merge the config paths just like this, that will be a non-breaking change.

  14. Jaykul commented on Sep 11, 2024

    @Jaykul
    Contributor

    Honestly, I expected [Management.Automation.ModuleIntrinsics]::GetPSModulePath to return the path after accounting for configuration. I guess I should file a bug for that...

    I can't imagine any scenario where it's useful for this method to return a path that's not actually in the PSModulePath!

    I mean, given that my user powershell.config specifies a %LocalAppData% path, the Documents based path will not be in PowerShell's PSModulePath ...

    image

  15. JustinGrote commented on Sep 11, 2024

    @JustinGrote
    Contributor

    I have created a Module to simplify the editing of the powershell.config.json file as well as including my function for getting the current "primary" PSModulePath
    https://github.com/JustinGrote/ModulePath

    GitHub
    Contribute to JustinGrote/ModulePath development by creating an account on GitHub.
  16. brgsstm commented on Sep 25, 2024

    @brgsstm

    Just to add to one of the issues that OneDrive introduces when the Documents folder is included in the sync, and that is retention policies. My organisation defines a OneDrive retention policy of 5 years since Last modified. This means that large chunks of the PS Module path get deleted at odd times, resulting in incomplete module packages which have to be recovered from the OneDrive Recycle bin.

    Moving user level modules out of Documents is a critical need when OneDrive retention is in the mix.

    +1 on this point - deeply frustrating.

  17. JustinGrote commented on Dec 6, 2024

    @JustinGrote
    Contributor

    My organisational policies prevent me from excluding any paths from OneDrive sync thus excluding me from one of the possible work-arounds.

    Why would it exclude you from the workaround of placing it at a separate path and adjusting your profile to include that as a PSModulePath folder? This doesn't fix PSGet/PSGetv3 and you need to use Save-Module instead of Install-Module but otherwise that should still be a valid workaround until a resolution moves forward.

    If you can use PowerShell 7 this is also already fixable, and I made a module for it called ModulePath, again still need to use ModuleFast or Save-PSModule/Resource with an alternate path.

  18. cimares commented on Feb 19, 2025

    @cimares

    If you can use PowerShell 7 this is also already fixable, and I made a module for it called ModulePath, again still need to use ModuleFast or Save-PSModule/Resource with an alternate path.

    Just to provide some feedback on this Justin Grote (@JustinGrote) , the ModulePath approach made this nice and simple to explain to end users on how to update PowerShell 7 to get modules out of OneDrive, so thanks for the effort on releasing that. Now I just need to resolve PS5.1 modules 8-)

  19. wUEZRs commented on May 21, 2025

    @wUEZRs

    This would be a great addition, or OneDrive should just exclude it by default. There's zero reason to cloud sync local modules. I find it interesting that PS Modules aren't in a native Windows folder by default

  20. JeffMill commented on Jul 14, 2025

    @JeffMill

    4 years and 1 month later. And still no working solution to allow end user control over the modulepath. Hope you all got let go during the recent layoffs.

    MattRose-CC Shame on you. Grow up.

  21. MattRose-CC commented on Jul 14, 2025

    @MattRose-CC

    FOUR YEARS. Shame on Microsoft. Shame on excuse makers such as yourself. basic functionality of controlling environmental variables. Inexusable. Shame on the listless lack of direction and middle management that couldnt effectuate such a basic change in over 4 years.

  22. JustinGrote commented on Jul 14, 2025

    @JustinGrote
    Contributor

    MattRose-CC you must be fun at parties.

  23. JosephColvin commented on Jul 14, 2025

    @JosephColvin
  24. jeroenlandheer commented on Jul 15, 2025

    @jeroenlandheer

    Let's not derail this conversation and keep things constructive. I agree this takes a long time, but if you look at how many people are involved here and putting their hard work in making this happen, it is clearly evident that a seemingly simple change might have a lot of consequences. (I also asked about why this takes long, but compatibility is a big thing and that's a really good thing.)

    Basically there are 2 things going on here:

    1. Where is PowerShell looking for modules?
    2. Where do your modules get installed?

    Looking for modules

    As Joel Bennett (@Jaykul) and Justin Grote (@JustinGrote) have pointed out, there are now new ways around this, see their comments here and here. It is not 100% ideal as defaults for new installations aren't changed AFAIK, but at least there are supported ways now to change this behaviour.

    Where your modules get placed

    To prevent your modules land in your OneDrive folder in the first place, another issue is being worked on. This is issue 1494, which involves changes to the module installer.

    If you're looking for the older commands like Install-Module... this is PowerShellGet, which is provided for compatibility.

    This documentation covers version 3.0.22-beta22 of the PowerShellGet module. This module is provided for compatibility with PowerShellGet v2.2.x. The cmdlets in this version of the module are proxy cmdlets that call the equivalent cmdlets in the Microsoft.PowerShell.PSResourceGet module.

    Source: Documentation

  25. kilasuit commented on Jul 20, 2025

    @kilasuit
    Collaborator

    Being discussed in PowerShell/PowerShell-RFC#388
    So this issue I think should really be closed & locked at this point

  26. locked and limited conversation to collaborators on Jul 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-PowerShellGetspecific to PowerShellGet moduleBreaking-Changebreaking change that may affect usersIssue-Enhancementthe issue is more of a feature request than a bugKeepOpenThe bot will ignore these and not auto-closeRFC-RequiredWorking Groups have decided that an RFC is required for this contributionWG-Engine-ModuleWG-NeedsReviewNeeds a review by the labeled Working Group

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions