Skip to content

FileSystem PSDrives not mounted when PowerShell runs inside an AppContainer #27253

@asklar

Description

@asklar

Prerequisites

Steps to reproduce

  1. Create a Windows AppContainer profile via CreateAppContainerProfile.
  2. Launch pwsh.exe inside the AppContainer using CreateProcessW with PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES.
  3. Run any cmdlet:
pwsh.exe -NoProfile -Command "Write-Output hello"

Expected behavior

hello

PowerShell should mount filesystem PSDrives (C:, D:, etc.) and module auto-loading should work normally.

Actual behavior

Write-Output: The term 'Write-Output' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path
is correct and try again.

No filesystem PSDrives are created. The available drives are only: HKLM, HKCU, Alias, Env, Temp, Function, Variable. The FileSystem provider is loaded but has no drives attached to it.

This breaks all cmdlets — Write-Output, Get-ChildItem, Import-Module, Get-Module, etc. — because module auto-loading cannot resolve $env:PSModulePath entries (e.g. C:\Program Files\PowerShell\7\Modules) without a mounted C: PSDrive.

Error details

The root cause is in FileSystemProvider.InitializeDefaultDrives():

DriveInfo[] logicalDrives = DriveInfo.GetDrives();

foreach (DriveInfo newDrive in logicalDrives)
{
    if (newDrive.DriveType == DriveType.Fixed)
    {
        if (!newDrive.RootDirectory.Exists)   // ← returns false in AppContainer
        {
            continue;                          // ← drive skipped entirely
        }

        root = newDrive.RootDirectory.FullName;
    }
    // … create PSDriveInfo …
}

RootDirectory.Exists calls FileSystem.DirectoryExists() in the .NET runtime, which calls GetFileAttributesEx. On a typical Windows installation, C:\ does not have an ALL APPLICATION PACKAGES ACE, so GetFileAttributesEx("C:") returns ERROR_ACCESS_DENIED (5). .NET interprets this as "does not exist" and returns false.

Subdirectories like C:\Windows and C:\Program Files do have ALL APPLICATION PACKAGES ACEs and are fully accessible — only the volume root is blocked.

Why this breaks module loading specifically:

Without a C: PSDrive, PowerShell's path resolution (LocationGlobberSessionStateDriveAPIs.GetDrive()) throws DriveNotFoundException for any C:\… path. Module auto-discovery iterates $env:PSModulePath entries (all on C:), each triggers a caught DriveNotFoundException, and all are silently skipped. No modules discovered → no cmdlets.

Note: the underlying Win32 filesystem is accessible — [System.IO.Directory]::GetDirectories("C:\Program Files\PowerShell\7\Modules") succeeds inside the AppContainer and returns all 14 module directories. The problem is purely in the PSDrive layer.

Diagnostic evidence:

Check Normal process AppContainer
GetFileAttributes("C:\") (Win32) 0x16 (DIR) ❌ Error 5 (ACCESS_DENIED)
GetFileAttributes("C:\Windows") 0x10 (DIR) 0x10 (DIR)
GetLogicalDrives() 0x3C 0x3C (drives present)
TokenIsAppContainer 0 1
PSDrives C, D, E, F, Temp, … HKLM, HKCU, Alias, Env, Temp, Function, Variable
FileSystem provider loaded ✅ (but no drives attached)
[IO.Directory]::GetDirectories(…) ✅ (filesystem works)

Suggested fix:

The RootDirectory.Exists check is too strict. DriveInfo.GetDrives() already proved the drive exists via GetLogicalDrives(). An ACCESS_DENIED on the root does not mean the drive is absent. Options:

  1. Remove the RootDirectory.Exists checkGetDrives() is sufficient proof.
  2. Treat ACCESS_DENIED as "exists" — similar to the VolumeLabel read a few lines above which already catches UnauthorizedAccessException.
  3. Fall back to GetLogicalDrives() bitmask instead of GetFileAttributes on the root.

Environment data

Name                           Value
----                           -----
PSVersion                      7.5.5
PSEdition                      Core
GitCommitId                    7.5.5
OS                             Microsoft Windows 10.0.26593
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

AppContainer created via CreateAppContainerProfile + PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES (standard Win32 APIs).

Visuals

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions