# Build "CSC - Caregiver Workstation" GPO (User-config GPP): desktop shortcuts + CS-SERVER printers.
# Run on CS-SERVER (DC) as an account with AD/GP write rights. Idempotent-ish (recreates XML + attrs).
# Cascades of Tucson - 2026-06-05. Mirrors production; test-filtered to SG-Caregivers-Test (set in step C).
$ErrorActionPreference = 'Stop'
Import-Module GroupPolicy -ErrorAction Stop
Import-Module ActiveDirectory -ErrorAction Stop
$gpoName = 'CSC - Caregiver Workstation'
$domain = 'cascades.local'
$changed = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
# 1) Create (or reuse) the GPO
$gpo = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue
if (-not $gpo) {
$gpo = New-GPO -Name $gpoName -Comment 'Caregiver/medtech desktop shortcuts (ALIS, LinkRx, Safe Living) + CS-SERVER printers. User GPP. TEST=filter SG-Caregivers-Test; go-live=filter SG-Caregivers.'
Write-Output ('CREATED GPO: ' + $gpoName)
} else { Write-Output ('REUSING GPO: ' + $gpoName) }
$gid = '{' + $gpo.Id.ToString().ToUpper() + '}'
Write-Output ('GUID: ' + $gid)
# Disable the (unused) computer side
$gpo.GpoStatus = 'ComputerSettingsDisabled'
Write-Output ('GpoStatus: ' + $gpo.GpoStatus)
# 2) Build Printers.xml
function PrinterXml($share,$action,$default,$comment,$filters) {
$p = '\\CS-SERVER\' + $share
$uid = '{' + ([guid]::NewGuid()).ToString().ToUpper() + '}'
return '' + $filters + ''
}
$noFilter = ''
function GroupFilterXml($grp) { return '' }
$entries = @()
foreach ($s in 'NursesPrinter','HealthServices','MCMedTech','MCReception','MCDirector','CopyRoom') {
$entries += (PrinterXml $s 'U' '0' '' $noFilter)
}
# Conditional defaults by DEVICE location (computer group membership, userContext=0)
$entries += (PrinterXml 'NursesPrinter' 'U' '1' 'Default for Main Tower devices' (GroupFilterXml 'SG-PC-MainTower'))
$entries += (PrinterXml 'MCMedTech' 'U' '1' 'Default for Memory Care devices' (GroupFilterXml 'SG-PC-MemoryCare'))
$printersXml = '' + "`r`n" + '' + ($entries -join '') + ''
# 3) Build Shortcuts.xml (URL internet shortcuts on the Desktop)
function ShortcutXml($name,$url,$comment) {
$uid = '{' + ([guid]::NewGuid()).ToString().ToUpper() + '}'
return ''
}
$scs = @()
$scs += (ShortcutXml 'ALIS' 'https://cascadestucson.alisonline.com/Login' 'ALIS EHR')
$scs += (ShortcutXml 'LinkRx' 'https://pharmcare.linkrxnow.com/Login.aspx' 'LinkRx Pharmacy')
$scs += (ShortcutXml 'Helpany' 'https://app.safe-living.com/login' 'Helpany (Safe Living)')
$shortcutsXml = '' + "`r`n" + '' + ($scs -join '') + ''
# 3b) Build Registry.xml: HKCU LegacyDefaultPrinterMode=1 (stop Windows "manage my default printer" so Nurses default sticks)
function RegDword($key,$valName,$dword) {
$uid = '{' + ([guid]::NewGuid()).ToString().ToUpper() + '}'
return ''
}
$regItems = @()
$regItems += (RegDword 'Software\Microsoft\Windows NT\CurrentVersion\Windows' 'LegacyDefaultPrinterMode' '00000001')
$registryXml = '' + "`r`n" + '' + ($regItems -join '') + ''
# 4) Write XML into SYSVOL (UTF-8 no BOM)
$base = "C:\Windows\SYSVOL\sysvol\$domain\Policies\$gid"
$pDir = Join-Path $base 'User\Preferences\Printers'
$sDir = Join-Path $base 'User\Preferences\Shortcuts'
New-Item -ItemType Directory -Path $pDir -Force | Out-Null
New-Item -ItemType Directory -Path $sDir -Force | Out-Null
$utf8 = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText((Join-Path $pDir 'Printers.xml'), $printersXml, $utf8)
[System.IO.File]::WriteAllText((Join-Path $sDir 'Shortcuts.xml'), $shortcutsXml, $utf8)
$rDir = Join-Path $base 'User\Preferences\Registry'
New-Item -ItemType Directory -Path $rDir -Force | Out-Null
[System.IO.File]::WriteAllText((Join-Path $rDir 'Registry.xml'), $registryXml, $utf8)
Write-Output ('WROTE: ' + (Join-Path $pDir 'Printers.xml'))
Write-Output ('WROTE: ' + (Join-Path $sDir 'Shortcuts.xml'))
Write-Output ('WROTE: ' + (Join-Path $rDir 'Registry.xml'))
# 5) Register the GPP client-side extensions (user) + bump version (AD + GPT.ini must match)
# CSE GUIDs MUST stay sorted ascending: 00000000 < B087BE9D(Registry) < BC75B1ED(Printers) < C418DD9D(Shortcuts)
$cse = '[{00000000-0000-0000-0000-000000000000}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}][{B087BE9D-ED37-454f-AF9C-04291E351182}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}][{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}][{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{A8C42CEA-CDB8-4388-97F4-5831F933DA84}]'
$ver = 131072 # 0x00020000 = user version 2, computer version 0
$gpoDn = 'CN=' + $gid + ',CN=Policies,CN=System,DC=cascades,DC=local'
Set-ADObject -Identity $gpoDn -Replace @{ gPCUserExtensionNames = $cse; versionNumber = $ver }
$gptIni = Join-Path $base 'GPT.ini'
$ini = Get-Content $gptIni -Raw
if ($ini -match 'Version=\d+') { $ini = $ini -replace 'Version=\d+', ('Version=' + $ver) }
else { $ini = $ini.TrimEnd() + "`r`nVersion=$ver`r`n" }
Set-Content -Path $gptIni -Value $ini -Encoding ASCII
Write-Output ('Set gPCUserExtensionNames + versionNumber=' + $ver + ' (AD + GPT.ini)')
# 6) Verify
Write-Output ''
Write-Output '===== VERIFY ====='
$chk = Get-ADObject -Identity $gpoDn -Properties gPCUserExtensionNames,versionNumber
Write-Output ('gPCUserExtensionNames: ' + $chk.gPCUserExtensionNames)
Write-Output ('versionNumber(AD): ' + $chk.versionNumber)
Write-Output ('GPT.ini: ' + ((Get-Content $gptIni -Raw).Trim()))
Write-Output '--- Printers.xml ---'
Get-Content (Join-Path $pDir 'Printers.xml') -Raw
Write-Output '--- Shortcuts.xml ---'
Get-Content (Join-Path $sDir 'Shortcuts.xml') -Raw
Write-Output '--- Registry.xml ---'
Get-Content (Join-Path $rDir 'Registry.xml') -Raw