Files
claudetools/clients/cascades-tucson/scripts/build-caregiver-gpo.ps1
Howard Enos b0efd6d4ec sync: auto-sync from HOWARD-HOME at 2026-06-05 17:35:42
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-05 17:35:42
2026-06-05 17:35:53 -07:00

105 lines
7.1 KiB
PowerShell

# 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 '<SharedPrinter clsid="{9A5E9697-9095-436d-A0EE-4D128FDFBCE5}" name="' + $p + '" status="' + $p + '" image="0" changed="' + $changed + '" uid="' + $uid + '" bypassErrors="1"><Properties action="' + $action + '" comment="' + $comment + '" path="' + $p + '" location="" default="' + $default + '" skipLocal="1" deleteAll="0" persistent="0" deleteMaps="0" portName="">' + $filters + '</Properties></SharedPrinter>'
}
$noFilter = '<Filters/>'
function GroupFilterXml($grp) { return '<Filters><FilterGroup bool="AND" not="0" name="CASCADES\' + $grp + '" sid="" userContext="0" primaryGroup="0" localGroup="0"/></Filters>' }
$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 = '<?xml version="1.0" encoding="utf-8"?>' + "`r`n" + '<Printers clsid="{1F577D12-3D1B-471c-A7BF-E0F49DC793FE}">' + ($entries -join '') + '</Printers>'
# 3) Build Shortcuts.xml (URL internet shortcuts on the Desktop)
function ShortcutXml($name,$url,$comment) {
$uid = '{' + ([guid]::NewGuid()).ToString().ToUpper() + '}'
return '<Shortcut clsid="{4F2F7C55-2790-433e-8127-0739D1CFA327}" name="' + $name + '" status="' + $name + '" image="0" changed="' + $changed + '" uid="' + $uid + '" bypassErrors="1"><Properties shortcutPath="%DesktopDir%\' + $name + '" pidl="" targetType="URL" action="R" comment="' + $comment + '" startIn="" arguments="" iconIndex="0" targetPath="' + $url + '" iconPath="" window="" shortcutKey="0"/></Shortcut>'
}
$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 = '<?xml version="1.0" encoding="utf-8"?>' + "`r`n" + '<Shortcuts clsid="{872C5C8A-6BBD-4d24-B962-D7A6F92B6F1A}">' + ($scs -join '') + '</Shortcuts>'
# 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 '<Registry clsid="{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}" name="' + $valName + '" status="' + $valName + '" image="7" changed="' + $changed + '" uid="' + $uid + '" bypassErrors="1"><Properties action="U" displayDecimal="1" default="0" hive="HKEY_CURRENT_USER" key="' + $key + '" name="' + $valName + '" type="REG_DWORD" value="' + $dword + '"/></Registry>'
}
$regItems = @()
$regItems += (RegDword 'Software\Microsoft\Windows NT\CurrentVersion\Windows' 'LegacyDefaultPrinterMode' '00000001')
$registryXml = '<?xml version="1.0" encoding="utf-8"?>' + "`r`n" + '<RegistrySettings clsid="{A3CCFC41-DFDB-43a5-8D26-0FE8B954DA51}">' + ($regItems -join '') + '</RegistrySettings>'
# 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