# Set-ExplorerSeparateProcess-AllUsers.ps1 # Enables: "Launch folder windows in a separate process" for ALL existing users + Default User # Sets: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\SeparateProcess = 1 [CmdletBinding()] param() function Assert-Admin { $id = [Security.Principal.WindowsIdentity]::GetCurrent() $pri = New-Object Security.Principal.WindowsPrincipal($id) if (-not $pri.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw "This script must be run as Administrator." } } function Set-SeparateProcessInHivePath { param( [Parameter(Mandatory=$true)][string]$HiveRoot # e.g. "Registry::HKEY_USERS\S-1-5-21-...\" ) $advPath = Join-Path $HiveRoot "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" New-Item -Path $advPath -Force | Out-Null New-ItemProperty -Path $advPath -Name "SeparateProcess" -Value 1 -PropertyType DWORD -Force | Out-Null } function Load-Hive { param( [Parameter(Mandatory=$true)][string]$MountName, # e.g. "TempHive_1234" [Parameter(Mandatory=$true)][string]$NtUserDatPath ) $mount = "HKU\$MountName" $null = & reg.exe load $mount $NtUserDatPath 2>$null return $mount } function Unload-Hive { param([Parameter(Mandatory=$true)][string]$Mount) # e.g. "HKU\TempHive_1234" $null = & reg.exe unload $Mount 2>$null } Assert-Admin Write-Host "Applying Explorer setting to all users + Default User..." -ForegroundColor Cyan # 1) Update all existing user profiles (even if not logged in) $profileRoots = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*" | Where-Object { $_.PSChildName -match '^S-1-5-21-' -and $_.ProfileImagePath -and (Test-Path $_.ProfileImagePath) } | Select-Object PSChildName, ProfileImagePath $updated = 0 $skipped = 0 $failed = 0 foreach ($p in $profileRoots) { $sid = $p.PSChildName $path = $p.ProfileImagePath $ntDat = Join-Path $path "NTUSER.DAT" # Skip special/system-ish profiles by path if ($path -match '\\(Default|Default User|Public|All Users)$') { $skipped++; continue } if (-not (Test-Path $ntDat)) { $skipped++; continue } # If hive is already loaded (user logged in), just set it directly $loadedHive = "Registry::HKEY_USERS\$sid" if (Test-Path $loadedHive) { try { Set-SeparateProcessInHivePath -HiveRoot $loadedHive $updated++ Write-Host "OK (loaded) $sid [$path]" } catch { $failed++ Write-Warning "FAIL (loaded) $sid [$path] :: $($_.Exception.Message)" } continue } # Otherwise load NTUSER.DAT temporarily, modify, unload $mountName = "TempHive_{0}" -f ([Guid]::NewGuid().ToString("N")) $mount = $null try { $mount = Load-Hive -MountName $mountName -NtUserDatPath $ntDat $hiveRoot = "Registry::HKEY_USERS\$mountName" Set-SeparateProcessInHivePath -HiveRoot $hiveRoot $updated++ Write-Host "OK (loaded*) $sid [$path]" } catch { $failed++ Write-Warning "FAIL $sid [$path] :: $($_.Exception.Message)" } finally { if ($mount) { Unload-Hive -Mount $mount } } } # 2) Update Default User so NEW profiles inherit it $defaultNtDat = "C:\Users\Default\NTUSER.DAT" if (Test-Path $defaultNtDat) { $mountName = "TempDefault_{0}" -f ([Guid]::NewGuid().ToString("N")) $mount = $null try { $mount = Load-Hive -MountName $mountName -NtUserDatPath $defaultNtDat $hiveRoot = "Registry::HKEY_USERS\$mountName" Set-SeparateProcessInHivePath -HiveRoot $hiveRoot Write-Host "OK Default User updated [$defaultNtDat]" } catch { Write-Warning "FAIL Default User [$defaultNtDat] :: $($_.Exception.Message)" } finally { if ($mount) { Unload-Hive -Mount $mount } } } else { Write-Warning "Default User NTUSER.DAT not found at: $defaultNtDat" } Write-Host "" Write-Host "Done." -ForegroundColor Green Write-Host "Updated: $updated Skipped: $skipped Failed: $failed" Write-Host "" Write-Host "Note: Users may need to log off/on, or restart Explorer, to see behavior changes." -ForegroundColor Yellow