xetup/scripts/04-default-profile.ps1
X9 31646112bf Fix registry ACL errors in steps 3 and 4
- 03-system-registry.ps1: add Grant-RegWriteAccess helper; Set-Reg now
  retries with ACL fix when Set-ItemProperty throws SecurityException
  (e.g. HKLM\...\Communications owned by TrustedInstaller)
- 04-default-profile.ps1: add Grant-HiveWriteAccess helper; Set-ProfileReg
  retries with ACL fix on Default hive keys with restricted permissions
- Both scripts: add -ErrorAction Stop to Set-ItemProperty so errors are
  properly caught by try/catch instead of bypassing it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 19:37:47 +01:00

275 lines
11 KiB
PowerShell

param(
[object]$Config,
[string]$LogFile
)
$ErrorActionPreference = "Continue"
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$line = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message"
Add-Content -Path $LogFile -Value $line -Encoding UTF8
}
# -----------------------------------------------------------------------
# Helper - apply a registry setting to both Default hive and current HKCU
# -----------------------------------------------------------------------
function Grant-HiveWriteAccess {
param([string]$HivePath) # full path e.g. "Registry::HKU\DefaultProfile\Software\..."
# Grants Administrators FullControl on a loaded hive key with restricted ACL.
try {
$acl = Get-Acl -Path $HivePath -ErrorAction Stop
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(
"BUILTIN\Administrators",
[System.Security.AccessControl.RegistryRights]::FullControl,
[System.Security.AccessControl.InheritanceFlags]"ContainerInherit,ObjectInherit",
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow
)
$acl.SetAccessRule($rule)
Set-Acl -Path $HivePath -AclObject $acl -ErrorAction Stop
}
catch {
Write-Log " Grant-HiveWriteAccess failed for $HivePath - $_" -Level WARN
}
}
function Set-ProfileReg {
param(
[string]$SubKey, # relative to HKCU (e.g. "Software\Microsoft\...")
[string]$Name,
$Value,
[string]$Type = "DWord"
)
# Apply to loaded Default hive
$defPath = "Registry::HKU\DefaultProfile\$SubKey"
try {
if (-not (Test-Path $defPath)) {
New-Item -Path $defPath -Force -ErrorAction Stop | Out-Null
}
Set-ItemProperty -Path $defPath -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop
}
catch {
# Retry after granting write access to parent key
try {
$parentPath = $defPath -replace '\\[^\\]+$', ''
if (Test-Path $parentPath) { Grant-HiveWriteAccess -HivePath $parentPath }
if (-not (Test-Path $defPath)) {
New-Item -Path $defPath -Force -ErrorAction Stop | Out-Null
}
Set-ItemProperty -Path $defPath -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop
}
catch {
Write-Log " DEFAULT HIVE failed $SubKey\$Name - $_" -Level ERROR
}
}
# Apply to current user as well
$hkcuPath = "HKCU:\$SubKey"
try {
if (-not (Test-Path $hkcuPath)) {
New-Item -Path $hkcuPath -Force -ErrorAction Stop | Out-Null
}
Set-ItemProperty -Path $hkcuPath -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop
Write-Log " SET $SubKey\$Name = $Value" -Level OK
}
catch {
Write-Log " HKCU failed $SubKey\$Name - $_" -Level ERROR
}
}
function Remove-ProfileReg {
param([string]$SubKey, [string]$Name)
$defPath = "Registry::HKU\DefaultProfile\$SubKey"
try {
if (Test-Path $defPath) {
Remove-ItemProperty -Path $defPath -Name $Name -Force -ErrorAction SilentlyContinue
}
}
catch { }
$hkcuPath = "HKCU:\$SubKey"
try {
if (Test-Path $hkcuPath) {
Remove-ItemProperty -Path $hkcuPath -Name $Name -Force -ErrorAction SilentlyContinue
Write-Log " REMOVED $SubKey\$Name" -Level OK
}
}
catch {
Write-Log " FAILED removing $SubKey\$Name - $_" -Level ERROR
}
}
# -----------------------------------------------------------------------
# Load Default profile hive
# -----------------------------------------------------------------------
$hivePath = "C:\Users\Default\NTUSER.DAT"
$hiveKey = "DefaultProfile"
Write-Log "Loading Default hive: $hivePath" -Level INFO
# Unload first in case previous run left it mounted
& reg unload "HKU\$hiveKey" 2>&1 | Out-Null
$loadResult = & reg load "HKU\$hiveKey" $hivePath 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Log "Failed to load Default hive: $loadResult" -Level ERROR
exit 1
}
Write-Log "Default hive loaded" -Level OK
try {
# -----------------------------------------------------------------------
# Taskbar settings (Win10 + Win11)
# -----------------------------------------------------------------------
Write-Log "Applying taskbar settings" -Level STEP
$tbPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
# Win11: align taskbar to left (0 = left, 1 = center)
Set-ProfileReg -SubKey $tbPath -Name "TaskbarAl" -Value 0
# Hide Search box / button (0 = hidden, 1 = icon, 2 = full box)
Set-ProfileReg -SubKey $tbPath -Name "SearchboxTaskbarMode" -Value 0
# Hide Task View button
Set-ProfileReg -SubKey $tbPath -Name "ShowTaskViewButton" -Value 0
# Hide Widgets button
Set-ProfileReg -SubKey $tbPath -Name "TaskbarDa" -Value 0
# Hide Chat / Teams button
Set-ProfileReg -SubKey $tbPath -Name "TaskbarMn" -Value 0
# Hide Copilot button
Set-ProfileReg -SubKey $tbPath -Name "ShowCopilotButton" -Value 0
# Show file extensions in Explorer
Set-ProfileReg -SubKey $tbPath -Name "HideFileExt" -Value 0
# Open Explorer to This PC instead of Quick Access
Set-ProfileReg -SubKey $tbPath -Name "LaunchTo" -Value 1
# -----------------------------------------------------------------------
# System tray - show all icons
# -----------------------------------------------------------------------
Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer" `
-Name "EnableAutoTray" -Value 0
# -----------------------------------------------------------------------
# Start menu settings
# -----------------------------------------------------------------------
Write-Log "Applying Start menu settings" -Level STEP
# Disable Bing search suggestions in Start menu
Set-ProfileReg -SubKey "Software\Policies\Microsoft\Windows\Explorer" `
-Name "DisableSearchBoxSuggestions" -Value 1
# Win11: empty Start menu pins
$startPinsPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Start" `
-Name "ConfigureStartPins" `
-Value '{"pinnedList":[]}' `
-Type "String"
# -----------------------------------------------------------------------
# Copilot - disable
# -----------------------------------------------------------------------
Set-ProfileReg -SubKey "Software\Policies\Microsoft\Windows\WindowsCopilot" `
-Name "TurnOffWindowsCopilot" -Value 1
# -----------------------------------------------------------------------
# GameDVR - disable
# -----------------------------------------------------------------------
Set-ProfileReg -SubKey "System\GameConfigStore" `
-Name "GameDVR_Enabled" -Value 0
Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\GameDVR" `
-Name "AppCaptureEnabled" -Value 0
# -----------------------------------------------------------------------
# Num Lock on startup
# -----------------------------------------------------------------------
Set-ProfileReg -SubKey "Control Panel\Keyboard" `
-Name "InitialKeyboardIndicators" -Value 2 -Type "String"
# -----------------------------------------------------------------------
# Accent color on title bars
# -----------------------------------------------------------------------
Set-ProfileReg -SubKey "Software\Microsoft\Windows\DWM" `
-Name "ColorPrevalence" -Value 1
# -----------------------------------------------------------------------
# OneDrive - remove RunOnce key from Default profile
# -----------------------------------------------------------------------
Write-Log "Removing OneDrive from Default profile RunOnce" -Level INFO
Remove-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "OneDriveSetup"
Remove-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\RunOnce" `
-Name "Delete Cached Standalone Update Binary"
# Remove OneDrive from Explorer namespace (left panel)
$oneDriveClsid = "{018D5C66-4533-4307-9B53-224DE2ED1FE6}"
$nsPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\$oneDriveClsid"
$defNsPath = "Registry::HKU\DefaultProfile\$nsPath"
if (Test-Path $defNsPath) {
Remove-Item -Path $defNsPath -Recurse -Force -ErrorAction SilentlyContinue
Write-Log " Removed OneDrive from Explorer namespace (Default)" -Level OK
}
$hkcuNsPath = "HKCU:\$nsPath"
if (Test-Path $hkcuNsPath) {
Remove-Item -Path $hkcuNsPath -Recurse -Force -ErrorAction SilentlyContinue
Write-Log " Removed OneDrive from Explorer namespace (HKCU)" -Level OK
}
# -----------------------------------------------------------------------
# Empty taskbar pinned apps (Win10/11)
# -----------------------------------------------------------------------
Write-Log "Clearing taskbar pinned apps layout" -Level INFO
$taskbarLayoutDir = "C:\Users\Default\AppData\Local\Microsoft\Windows\Shell"
if (-not (Test-Path $taskbarLayoutDir)) {
New-Item -ItemType Directory -Path $taskbarLayoutDir -Force | Out-Null
}
$taskbarLayoutXml = @"
<?xml version="1.0" encoding="utf-8"?>
<LayoutModificationTemplate
xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification"
xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout"
xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout"
xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout"
Version="1">
<CustomTaskbarLayoutCollection PinListPlacement="Replace">
<defaultlayout:TaskbarLayout>
<taskbar:TaskbarPinList>
</taskbar:TaskbarPinList>
</defaultlayout:TaskbarLayout>
</CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>
"@
$taskbarLayoutXml | Set-Content -Path "$taskbarLayoutDir\LayoutModification.xml" -Encoding UTF8 -Force
Write-Log " Taskbar LayoutModification.xml written" -Level OK
}
finally {
# -----------------------------------------------------------------------
# Unload Default hive - always, even on error
# -----------------------------------------------------------------------
Write-Log "Unloading Default hive" -Level INFO
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
Start-Sleep -Milliseconds 500
$unloadResult = & reg unload "HKU\$hiveKey" 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Log "Default hive unloaded" -Level OK
} else {
Write-Log "Failed to unload Default hive: $unloadResult" -Level ERROR
}
}
Write-Log "Step 4 complete" -Level OK