Prerequisites
Steps to reproduce
- Create a Windows AppContainer profile via
CreateAppContainerProfile.
- Launch
pwsh.exe inside the AppContainer using CreateProcessW with PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES.
- Run any cmdlet:
pwsh.exe -NoProfile -Command "Write-Output hello"
Expected behavior
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 (LocationGlobber → SessionStateDriveAPIs.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:
- Remove the
RootDirectory.Exists check — GetDrives() is sufficient proof.
- Treat
ACCESS_DENIED as "exists" — similar to the VolumeLabel read a few lines above which already catches UnauthorizedAccessException.
- 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
Prerequisites
Steps to reproduce
CreateAppContainerProfile.pwsh.exeinside the AppContainer usingCreateProcessWwithPROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES.Expected behavior
helloPowerShell should mount filesystem PSDrives (
C:,D:, etc.) and module auto-loading should work normally.Actual behavior
No filesystem PSDrives are created. The available drives are only:
HKLM, HKCU, Alias, Env, Temp, Function, Variable. TheFileSystemprovider 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:PSModulePathentries (e.g.C:\Program Files\PowerShell\7\Modules) without a mountedC:PSDrive.Error details
The root cause is in
FileSystemProvider.InitializeDefaultDrives():RootDirectory.ExistscallsFileSystem.DirectoryExists()in the .NET runtime, which callsGetFileAttributesEx. On a typical Windows installation,C:\does not have anALL APPLICATION PACKAGESACE, soGetFileAttributesEx("C:")returnsERROR_ACCESS_DENIED(5). .NET interprets this as "does not exist" and returnsfalse.Subdirectories like
C:\WindowsandC:\Program Filesdo haveALL APPLICATION PACKAGESACEs and are fully accessible — only the volume root is blocked.Why this breaks module loading specifically:
Without a
C:PSDrive, PowerShell's path resolution (LocationGlobber→SessionStateDriveAPIs.GetDrive()) throwsDriveNotFoundExceptionfor anyC:\…path. Module auto-discovery iterates$env:PSModulePathentries (all onC:), each triggers a caughtDriveNotFoundException, 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:
GetFileAttributes("C:\")(Win32)0x16(DIR)ACCESS_DENIED)GetFileAttributes("C:\Windows")0x10(DIR)0x10(DIR)GetLogicalDrives()0x3C0x3C(drives present)TokenIsAppContainer01C, D, E, F, Temp, …HKLM, HKCU, Alias, Env, Temp, Function, VariableFileSystemprovider loaded[IO.Directory]::GetDirectories(…)Suggested fix:
The
RootDirectory.Existscheck is too strict.DriveInfo.GetDrives()already proved the drive exists viaGetLogicalDrives(). AnACCESS_DENIEDon the root does not mean the drive is absent. Options:RootDirectory.Existscheck —GetDrives()is sufficient proof.ACCESS_DENIEDas "exists" — similar to theVolumeLabelread a few lines above which already catchesUnauthorizedAccessException.GetLogicalDrives()bitmask instead ofGetFileAttributeson the root.Environment data
AppContainer created via
CreateAppContainerProfile+PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES(standard Win32 APIs).Visuals
No response