Files
claudetools/clients/cascades-tucson/scripts/susan-profile-fix.ps1
Howard Enos 6ec260c023 cascades: LE folder redirection end-to-end + share access review doc
Major work from 2026-04-23:

Folder redirection (OU=Life Enrichment):
- Added 5 folders (Desktop, Pictures, Music, Videos, Favorites) to CSC - Folder
  Redirection (LE) alongside existing Documents + Downloads. All use Flags=1021
  (Basic + create folder per user + move contents + policy-removal: redirect back).
- Created CSC - Always Wait For Network GPO, linked at OU=Workstations. Disables
  FLO via correct Winlogon registry path (HKLM\Software\Policies\Microsoft\
  Windows NT\CurrentVersion\Winlogon\SyncForegroundPolicy=1). First attempt used
  wrong path (Windows\System) which Winlogon ignored.
- Proved GPO FR works for clean-hive users (test user LE.FRTest, now removed).
- Wrote susan-profile-fix.ps1 to repair ProfWiz-poisoned profiles: robocopies
  local content to \CS-SERVER\homes\<user>, loads NTUSER.DAT, rewrites User
  Shell Folders (legacy + modern GUIDs) to UNC, unloads. Applied to Susan Hicks,
  verified via live SMB session + content access.

Share access review doc:
- share-access-matrix-2026-04-23.md drafted for John/Meredith review. One
  short block per employee (department + position + folders they can access).
  All settled decisions from today's calls captured (Sandra Fish = Meredith-
  only, Culinary = kitchen + M/J/A, no chat share, caregivers zero on-prem,
  Veronica = Meredith tier, CasAdmin201 retired, pacs empty).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 20:07:59 -07:00

137 lines
6.5 KiB
PowerShell

# ============================================================================
# Susan Hicks profile fix — runs on DESKTOP-ROK7VNM as SYSTEM via GuruRMM.
#
# Preconditions:
# - Susan is signed out (NTUSER.DAT unlocked)
# - FLO-off GPO active (SyncForegroundPolicy at Winlogon path)
# - LE FR GPO has working UNC paths on SYSVOL
#
# Caller injects sysadmin password into $adminPass placeholder at the top.
# SYSTEM on ROK7VNM has full local file access, but can't auth to
# \\CS-SERVER\homes as itself — so we 'net use' a drive letter with
# CASCADES\sysadmin, do the copy, then drop it.
# ============================================================================
$ErrorActionPreference = 'Continue'
$adminUser = 'CASCADES\sysadmin'
$adminPass = '__ADMIN_PASS__'
$user = 'Susan.Hicks'
$localRoot = 'C:\Users\SusanH'
$serverUNC = '\\CS-SERVER\homes'
$userUNC = $serverUNC + '\' + $user
$driveLetter = 'X'
Write-Host '=== Pre-checks ===' -ForegroundColor Cyan
if (-not (Test-Path $localRoot)) { throw "No local profile at $localRoot" }
$nt = Join-Path $localRoot 'NTUSER.DAT'
if (-not (Test-Path $nt)) { throw "No NTUSER.DAT at $nt" }
try {
$s = [System.IO.File]::Open($nt, 'Open', 'Read', 'None')
$s.Close()
Write-Host '[OK] NTUSER.DAT is unlocked (Susan is signed out)' -ForegroundColor Green
} catch {
throw "NTUSER.DAT is LOCKED — Susan must be signed out. Error: $($_.Exception.Message)"
}
# ------------- Step 1: map homes share with sysadmin creds -------------
Write-Host "`n=== Step 1: Mount \\CS-SERVER\homes as ${driveLetter}: ===" -ForegroundColor Cyan
# Clean up any stale mapping (ignore failure if none existed)
cmd.exe /c "net use ${driveLetter}: /delete /y >nul 2>&1"
$mapOut = cmd.exe /c "net use ${driveLetter}: $serverUNC $adminPass /user:$adminUser 2>&1"
if ($LASTEXITCODE -ne 0) { throw "net use failed: $mapOut" }
Write-Host "[OK] Mapped $driveLetter to $serverUNC as $adminUser"
try {
# ensure per-user home exists
$driveHome = "${driveLetter}:\$user"
if (-not (Test-Path $driveHome)) { New-Item -Path $driveHome -ItemType Directory -Force | Out-Null }
# ------------- Step 2: robocopy local content to server -------------
Write-Host "`n=== Step 2: Copy local folders to $userUNC ===" -ForegroundColor Cyan
$folders = @('Documents','Desktop','Downloads','Pictures','Music','Videos','Favorites')
foreach ($f in $folders) {
$from = Join-Path $localRoot $f
$to = Join-Path $driveHome $f
if (-not (Test-Path $from)) { Write-Host " [SKIP] $from does not exist"; continue }
if (-not (Test-Path $to)) { New-Item -Path $to -ItemType Directory -Force | Out-Null }
$rbArgs = @($from, $to, '/E', '/COPY:DAT', '/DCOPY:T', '/XJ', '/R:1', '/W:1',
'/MT:8', '/NFL', '/NDL', '/NJH', '/NJS')
& robocopy.exe @rbArgs | Out-Null
$code = $LASTEXITCODE
$srcCount = (Get-ChildItem $from -Force -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count
$dstCount = (Get-ChildItem $to -Force -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count
$tag = if ($code -ge 8) { '[FAIL]' } else { '[OK] ' }
Write-Host " $tag $f : src=$srcCount dst=$dstCount (robocopy exit=$code)"
}
Write-Host "`n=== Server-side Susan.Hicks after copy ===" -ForegroundColor Cyan
Get-ChildItem $driveHome -Force -Directory |
Select Name, @{N='Items';E={(Get-ChildItem $_.FullName -Force -Recurse -File -ErrorAction SilentlyContinue | Measure-Object).Count}} |
Format-Table -AutoSize
} finally {
# always drop the mapped drive (ignore failure)
cmd.exe /c "net use ${driveLetter}: /delete /y >nul 2>&1"
}
# ------------- Step 3: load Susan's NTUSER.DAT -------------
Write-Host "`n=== Step 3: Load Susan's NTUSER.DAT as HKU\SusanTemp ===" -ForegroundColor Cyan
cmd.exe /c "reg.exe unload HKU\SusanTemp >nul 2>&1" # clean up any prior
$loadOut = cmd.exe /c "reg.exe load HKU\SusanTemp `"$nt`" 2>&1"
if ($LASTEXITCODE -ne 0) { throw "reg load failed: $loadOut" }
Write-Host '[OK] Hive loaded'
try {
# ------------- Step 4: rewrite User Shell Folders -------------
Write-Host "`n=== Step 4: Rewrite User Shell Folders to UNC ===" -ForegroundColor Cyan
$usf = 'Registry::HKEY_USERS\SusanTemp\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
$sf = 'Registry::HKEY_USERS\SusanTemp\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders'
$mapLegacy = @{
'Desktop' = "$userUNC\Desktop"
'Personal' = "$userUNC\Documents"
'My Pictures' = "$userUNC\Pictures"
'My Music' = "$userUNC\Music"
'My Video' = "$userUNC\Videos"
'Favorites' = "$userUNC\Favorites"
}
$mapGuid = @{
'{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}' = "$userUNC\Desktop"
'{FDD39AD0-238F-46AF-ADB4-6C85480369C7}' = "$userUNC\Documents"
'{374DE290-123F-4565-9164-39C4925E467B}' = "$userUNC\Downloads"
'{7D83EE9B-2244-4E70-B1F5-5393042AF1E4}' = "$userUNC\Downloads"
'{33E28130-4E1E-4676-835A-98395C3BC3BB}' = "$userUNC\Pictures"
'{4BD8D571-6D19-48D3-BE97-422220080E43}' = "$userUNC\Music"
'{18989B1D-99B5-455B-841C-AB7C74E4DDFC}' = "$userUNC\Videos"
'{35286A68-3C57-41A1-BBB1-0EAE73D76C95}' = "$userUNC\Videos"
'{1777F761-68AD-4D8A-87BD-30B759FA33DD}' = "$userUNC\Favorites"
'{F42EE2D3-909F-4907-8871-4C22FC0BF756}' = "$userUNC\Documents"
}
foreach ($k in $mapLegacy.Keys) {
Set-ItemProperty -LiteralPath $usf -Name $k -Value $mapLegacy[$k] -Type ExpandString
Set-ItemProperty -LiteralPath $sf -Name $k -Value $mapLegacy[$k] -ErrorAction SilentlyContinue
Write-Host " $k = $($mapLegacy[$k])"
}
foreach ($g in $mapGuid.Keys) {
Set-ItemProperty -LiteralPath $usf -Name $g -Value $mapGuid[$g] -Type ExpandString
Write-Host " $g = $($mapGuid[$g])"
}
Write-Host "`n=== Verify final User Shell Folders ===" -ForegroundColor Cyan
Get-ItemProperty -LiteralPath $usf | Select * -ExcludeProperty PS* | Format-List | Out-String | Write-Host
} finally {
Write-Host "`n=== Step 5: Unload hive ===" -ForegroundColor Cyan
[gc]::Collect()
Start-Sleep -Seconds 1
cmd.exe /c "reg.exe unload HKU\SusanTemp >nul 2>&1"
Write-Host '[OK] Hive unloaded'
}
Write-Host "`n=== DONE ===" -ForegroundColor Green
Write-Host "Next: sign out LE.FRTest, sign in as Susan. Shell will pull UNC paths from hive; all content pre-copied to server."