# Deploy 'CSC - Caregiver Device Lockdown' GPO: computer startup script + link to OU=Caregiver Devices. # Startup script content is injected as base64 (__B64__) to preserve nested here-strings. $ErrorActionPreference = 'Stop' Import-Module GroupPolicy -ErrorAction Stop Import-Module ActiveDirectory -ErrorAction Stop $gpoName = 'CSC - Caregiver Device Lockdown' $domain = 'cascades.local' $gpo = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue if (-not $gpo) { $gpo = New-GPO -Name $gpoName -Comment 'Caregiver/medtech shared-device lockdown: lock 3min, auto sign-out 15min (90s warning), never sleep. Computer startup script. Linked to OU=Caregiver Devices.' Write-Output ('CREATED: ' + $gpoName) } else { Write-Output ('REUSING: ' + $gpoName) } $gid = '{' + $gpo.Id.ToString().ToUpper() + '}' Write-Output ('GUID: ' + $gid) $gpo.GpoStatus = 'UserSettingsDisabled' Write-Output ('GpoStatus: ' + $gpo.GpoStatus) # Decode + write the startup script into SYSVOL $b64 = '__B64__' $startup = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($b64)) $base = "C:\Windows\SYSVOL\sysvol\$domain\Policies\$gid" $scriptsDir = Join-Path $base 'Machine\Scripts\Startup' New-Item -ItemType Directory -Path $scriptsDir -Force | Out-Null $utf8 = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText((Join-Path $scriptsDir 'caregiver-lockdown.ps1'), $startup, $utf8) Write-Output ('WROTE startup script (' + $startup.Length + ' chars)') # psscripts.ini (Unicode, little-endian + BOM, as GPMC writes it) $ini = "[Startup]`r`n0CmdLine=caregiver-lockdown.ps1`r`n0Parameters=`r`n" [System.IO.File]::WriteAllText((Join-Path $base 'Machine\Scripts\psscripts.ini'), $ini, (New-Object System.Text.UnicodeEncoding($false,$true))) Write-Output 'WROTE psscripts.ini' # Register the Scripts (startup) CSE + bump COMPUTER version (low word) $cse = '[{42B5FAAE-6536-11d2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]' $ver = 2 $dn = 'CN=' + $gid + ',CN=Policies,CN=System,DC=cascades,DC=local' Set-ADObject -Identity $dn -Replace @{ gPCMachineExtensionNames = $cse; versionNumber = $ver } $gptIni = Join-Path $base 'GPT.ini' $g = Get-Content $gptIni -Raw if ($g -match 'Version=\d+') { $g = $g -replace 'Version=\d+', ('Version=' + $ver) } else { $g = $g.TrimEnd() + "`r`nVersion=$ver`r`n" } Set-Content -Path $gptIni -Value $g -Encoding ASCII Write-Output ('Set gPCMachineExtensionNames + versionNumber=' + $ver) # Link to OU=Caregiver Devices (computer GPO; default Authenticated Users filtering = the computer applies it) $target = 'OU=Caregiver Devices,OU=Staff PCs,OU=Workstations,DC=cascades,DC=local' try { New-GPLink -Name $gpoName -Target $target -LinkEnabled Yes -ErrorAction Stop | Out-Null; Write-Output ('LINKED at ' + $target) } catch { if ($_.Exception.Message -match 'already') { Write-Output 'Already linked' } else { throw } } Write-Output '' Write-Output '===== VERIFY =====' $chk = Get-ADObject -Identity $dn -Properties gPCMachineExtensionNames,versionNumber Write-Output ('gPCMachineExtensionNames: ' + $chk.gPCMachineExtensionNames) Write-Output ('versionNumber(AD): ' + $chk.versionNumber) Write-Output ('GPT.ini: ' + ((Get-Content $gptIni -Raw).Trim())) Write-Output ('startup .ps1 exists: ' + (Test-Path (Join-Path $scriptsDir 'caregiver-lockdown.ps1'))) Write-Output ('psscripts.ini exists: ' + (Test-Path (Join-Path $base 'Machine\Scripts\psscripts.ini'))) (Get-GPInheritance -Target $target).GpoLinks | ForEach-Object { Write-Output (' link: ' + $_.DisplayName + ' enabled=' + $_.Enabled) }