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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions