Skip to content

Document MSIX-packaged PowerShell: system-wide config and profiles move to a per-machine data store (MachineFolder) #13172

Description

@jshigetomi

Draft documentation tracking issue filed by the PowerShell team to seed docs work for an upcoming feature. Specifics (exact paths, target version, final cmdlet behavior) will be refined as the implementation lands.
Code PR: PowerShell/PowerShell#27632 · Design: PowerShell/PowerShell#27697 · Umbrella: PowerShell/PowerShell#27565

Summary

In an upcoming preview (7.7 series), MSIX-packaged PowerShell relocates system-wide (AllUsers) configuration files out of the now read-only $PSHOME install directory into a dedicated, admin-writable per-machine data store (referred to internally as the MachineFolder). This lets administrators change machine-wide settings that:

  • persist across package upgrades, and
  • do not require writing into the immutable MSIX install root.

This change is Windows/MSIX-only. Zip, MSI, Linux, and macOS installs are unchanged and continue to use $PSHOME.

Why this changes

MSIX packages install into a read-only, tamper-protected location. Any write into $PSHOME fails, and for mutable packages would be discarded on upgrade. Keeping $PSHOME immutable is also a security benefit (mitigates DLL-planting / binary tampering, aligns with Defender / Azure guidance). The per-machine data store provides a writable, admin-controlled location that survives upgrades.

What changes (user-facing)

Affected install method

Install method System-wide config location
MSIX / Store package (Windows) New — per-machine data store (MachineFolder)
Zip, MSI (Windows), Linux, macOS Unchanged$PSHOME

New locations (MSIX only)

  • System-wide config (powershell.config.json) is read/written in the per-machine data store.
  • The store is isolated per package family, so Stable, Preview, and LTS each get their own separate config (no cross-channel bleed).
  • Underlying path (resolved automatically at runtime; subject to change): {PackageRepositoryRoot}\Families\ApplicationData\{PackageFamilyName}\Machine, where {PackageRepositoryRoot} comes from HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\PackageRepositoryRoot (typically C:\Program Files\WindowsApps).

Permissions (how to edit)

The MachineFolder is provisioned by the package manifest with this ACL:

<appdata:MachineFolder Sddl="(A;OICI;GA;;;BA)(A;OICI;GR;;;BU)" />
  • Administrators (BA) — full control (Generic All); can create/edit the files.
  • Built-in Users (BU) — read-only (Generic Read); every user on the machine can read the system-wide config.
  • Both ACEs are inheritable to files and subfolders (OICI).

Docs need an explicit "how to edit" walkthrough. Editing the system-wide config now requires an elevated (admin) session/editor, and the location is less discoverable than $PSHOME. Provide copy-pasteable steps to locate the folder and edit the file.

Configuration merge precedence (key conceptual topic)

The feature adds a third configuration scope. Effective settings are merged across CurrentUser, MachineFolder (admin), and $PSHOME (read-only product defaults). How the scopes combine depends on whether a setting behaves like a policy or a preference:

  • Policy-type list settings are the union of every scope — entries from CurrentUser, MachineFolder, and $PSHOME all accumulate, and no scope can remove an entry contributed by another. This ensures, for example, that a module added to the Windows PowerShell compatibility deny list by a product update in $PSHOME is never silently dropped because an admin also defined the key in the MachineFolder. Example: WindowsPowerShellCompatibilityModuleDenyList.
  • Preference-type settings use highest-precedence-wins: CurrentUser > MachineFolder > $PSHOME. Only the most specific scope that defines the key is used. Examples: execution policy set via powershell.config.json, DisableImplicitWinCompat, WindowsPowerShellCompatibilityNoClobberModuleList.
  • ExecutionPolicy is a preference — not a policy — when it comes from a config file. A config-based execution policy (the Process / CurrentUser / LocalMachine scopes) follows the preference order above (CurrentUser wins over LocalMachine), and this legacy order is unchanged by this feature. Only Group Policy (the registry-backed MachinePolicy / UserPolicy scopes) is a true policy, and it still overrides all config-based scopes.
  • Only changed keys are written to the MachineFolder. The shipped $PSHOME\powershell.config.json remains the read-only product-defaults layer and is not rewritten — docs should make clear that admins edit the MachineFolder copy, not the $PSHOME copy.

Affected settings / cmdlets

  • Set-ExecutionPolicy -Scope LocalMachine — writes now land in the MachineFolder under MSIX. (Execution policy from a config file remains a preference; see the merge precedence note above.)
  • Windows PowerShell compatibility settings: DisableImplicitWinCompat, WindowsPowerShellCompatibilityModuleDenyList (merged as a policy / union across scopes), WindowsPowerShellCompatibilityNoClobberModuleList (resolved as a preference).
  • Experimental features at AllUsers scope — not part of this change; the AllUsers/MachineFolder redesign for experimental features (explicit enable/disable lists + merge semantics) is tracked separately in PS7-packaged: bring experimental features into the MachineFolder model (deferred from #27632) PowerShell/PowerShell#27702.

Docs to add / update

  • about_PowerShell_Config — new MachineFolder scope, path, merge precedence (policy = union, preference = CurrentUser > MachineFolder > $PSHOME), MSIX-only note.
  • about_Execution_Policies — clarify that a config-based execution policy is a preference (CurrentUser > LocalMachine), that LocalMachine resolves to the MachineFolder under MSIX, and that only Group Policy is a true policy.
  • about_Windows_PowerShell_Compatibility — where the deny/no-clobber lists live under MSIX, and that the deny list is unioned across scopes while the no-clobber list is a preference.
  • New conceptual/how-to page: "Editing system-wide settings for MSIX-packaged PowerShell" — locating the store, editing with elevation, per-channel isolation.

Out of scope (tracked separately)

These related items are not part of this change and will be documented with their own PRs:

References


This is a draft to seed documentation work; the PowerShell team will refine specifics as the feature finalizes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions