Add PSContentPath Standard Platform Paths
PR Summary
This pull request introduces support for the PowerShell "PSContentPath" experimental feature, allowing users to customize the location of user content (such as modules and scripts) via an environment variable or configuration file. The code now prefers these new paths when the feature is enabled, improving flexibility and future compatibility.
Support for PSContentPath experimental feature:
- Added logic to detect if the "PSContentPath" experimental feature is enabled by checking the PowerShell configuration file (
powershell.config.json). - When enabled, the code looks for a custom
PSUserContentPathin the environment variable or configuration file, using it as the base path for user content if it exists. If not set, it defaults toLocalApplicationData\PowerShell. - If the experimental feature is not enabled, the code continues to use the legacy
MyDocuments\PowerShellfolder for user content.
Refactoring and path resolution:
- Updated
GetPathsFromEnvVarAndScopeto use the newpsUserContentPathvariable instead of the legacy documents path, ensuring the correct directory is used based on feature detection.
Utility methods:
- Introduced two new helper methods:
IsExperimentalFeatureEnabled(to check for enabled features in the config) andGetPSUserContentPath(to retrieve the custom user content path from environment or config).
PR Context
This change introduces support for the PowerShell PSContentPath experimental feature, enabling users to customize where PowerShell stores user content (modules, scripts, etc.). Historically, PowerShell has relied on fixed paths such as MyDocuments\PowerShell, which limits flexibility in modern environments. With this update, users can define a custom content path via an environment variable or configuration file, allowing PowerShell to adapt to diverse deployment and security scenarios.
The feature is a direct response to long-standing community feedback (see https://github.com/PowerShell/PowerShell/issues/15552) and aligns with related work in https://github.com/PowerShell/PSResourceGet/issues/1912. It was shaped through detailed specifications in https://github.com/PowerShell/PowerShell-RFC/pull/388. This milestone lays the foundation for flexible, user-configurable content storage, addressing needs such as:
Roaming profiles Containerized environments Read-only file systems
By introducing this capability, we empower users to tailor PowerShell to modern deployment and compliance requirements.
PR Checklist
- [x] PR has a meaningful title
- Use the present tense and imperative mood when describing your changes
- [x] Summarized changes
- [x] Make sure all
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright header - [x] This PR is ready to merge and is not Work in Progress.
- If the PR is work in progress, please add the prefix
WIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.
- If the PR is work in progress, please add the prefix
- Breaking changes
- [x] None
- OR
- [ ] Documentation needed
- [ ] Issue filed:
- User-facing changes
- [ ] Not Applicable
- OR
- [x] Documentation needed
- [ ] Issue filed:
- Testing - New and feature
- [ ] N/A or can only be tested interactively
- OR
- [x] Make sure you've added a new test if existing tests do not effectively test the code changed
- Tooling
- [ ] I have considered the user experience from a tooling perspective and don't believe tooling will be impacted.
- OR
- [ ] I have considered the user experience from a tooling perspective and enumerated concerns in the summary.
Added support for Linux and MacOS pathway as well
Azure Pipelines successfully started running 1 pipeline(s).
Opened PR to run CI tests here: https://github.com/PowerShell/PSResourceGet/pull/1913
Decided to use pwsh runspaces instead of reflection to call the PSContentPath API. Talked to @TravisEz13 and found out that APIScan will require proof that APIs are public and not internal. So utilizing the new cmdlet Get-PSContentPath in a pwsh runspace to get the path from the config or default LOCALAppData location.
Tests are looking good, currently 3 failing tests related to Lucene index issues (ie these are flakey tests due to a server side issue with the Gallery). In terms of this PR all tests are passing!
All tests are passing now, PR looks good to me, just have one comment regarding whether to use default runspace created by the .Create() method or use current runspace.
@jshigetomi we reviewed your PR, @anamnavi has a couple comments/suggestions. Everything looks good otherwise. Because we can't test these changes until 7.7 is released we're going to hold off on merging until then.
I added tests so that it skips some PSContentPath tests if it's not enabled. I check for it with test hooks and the availability of Get-PSContentPath.