diff --git a/flash/Deploy-Windows.ps1 b/flash/Deploy-Windows.ps1 deleted file mode 100644 index 7b53b19..0000000 --- a/flash/Deploy-Windows.ps1 +++ /dev/null @@ -1,244 +0,0 @@ -#Requires -RunAsAdministrator - -[CmdletBinding()] -param( - [switch]$SkipBloatware, - [switch]$SkipSoftware, - [switch]$SkipDefaultProfile, - [switch]$DryRun -) - -$ErrorActionPreference = "Continue" - -# ----------------------------------------------------------------------- -# Paths -# ----------------------------------------------------------------------- -$ScriptRoot = $PSScriptRoot -$LogDir = "C:\Windows\Setup\Scripts" -$LogFile = "$LogDir\Deploy.log" -$ConfigFile = "$ScriptRoot\config\config.json" - -# ----------------------------------------------------------------------- -# Logging -# ----------------------------------------------------------------------- -function Write-Log { - param( - [string]$Message, - [ValidateSet("INFO","OK","ERROR","WARN","STEP")] - [string]$Level = "INFO" - ) - $timestamp = Get-Date -Format "HH:mm:ss" - $line = "[$timestamp] [$Level] $Message" - Add-Content -Path $LogFile -Value $line -Encoding UTF8 - switch ($Level) { - "OK" { Write-Host $line -ForegroundColor Green } - "ERROR" { Write-Host $line -ForegroundColor Red } - "WARN" { Write-Host $line -ForegroundColor Yellow } - "STEP" { Write-Host $line -ForegroundColor Cyan } - default { Write-Host $line } - } -} - -# ----------------------------------------------------------------------- -# Step runner - catches errors, logs, always continues -# ----------------------------------------------------------------------- -$StepResults = [System.Collections.Generic.List[hashtable]]::new() - -function Invoke-Step { - param( - [string]$Name, - [scriptblock]$Action - ) - - Write-Log "---- $Name ----" -Level STEP - - if ($DryRun) { - Write-Log "DryRun - skipping execution" -Level WARN - $StepResults.Add(@{ Name = $Name; Status = "DRYRUN" }) - return - } - - try { - & $Action - Write-Log "$Name - OK" -Level OK - $StepResults.Add(@{ Name = $Name; Status = "OK" }) - } - catch { - Write-Log "$Name - ERROR: $_" -Level ERROR - $StepResults.Add(@{ Name = $Name; Status = "ERROR" }) - } -} - -# ----------------------------------------------------------------------- -# Init -# ----------------------------------------------------------------------- -if (-not (Test-Path $LogDir)) { - New-Item -ItemType Directory -Path $LogDir -Force | Out-Null -} - -Write-Log "========================================" -Level INFO -Write-Log "Deploy-Windows.ps1 started" -Level INFO -Write-Log "Computer: $env:COMPUTERNAME" -Level INFO -Write-Log "User: $env:USERNAME" -Level INFO -Write-Log "Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -Level INFO -if ($DryRun) { Write-Log "Mode: DRY RUN" -Level WARN } -Write-Log "========================================" -Level INFO - -# ----------------------------------------------------------------------- -# Load config -# ----------------------------------------------------------------------- -$Config = $null -Invoke-Step -Name "Load config.json" -Action { - if (-not (Test-Path $ConfigFile)) { - throw "config.json not found: $ConfigFile" - } - $script:Config = Get-Content $ConfigFile -Raw -Encoding UTF8 | ConvertFrom-Json - Write-Log "Config loaded from $ConfigFile" -Level INFO -} - -# ----------------------------------------------------------------------- -# Build step enable/disable map from config + CLI overrides -# ----------------------------------------------------------------------- -$stepsEnabled = @{ - adminAccount = $true - bloatware = $true - software = $true - systemRegistry = $true - defaultProfile = $true - personalization = $true - scheduledTasks = $true - desktopInfo = $true - activation = $true -} -if ($Config -and $Config.steps) { - foreach ($key in @($stepsEnabled.Keys)) { - $val = $Config.steps.$key - if ($null -ne $val) { $stepsEnabled[$key] = [bool]$val } - } -} -# CLI switches override config.steps -if ($SkipBloatware) { $stepsEnabled['bloatware'] = $false } -if ($SkipSoftware) { $stepsEnabled['software'] = $false } -if ($SkipDefaultProfile) { $stepsEnabled['defaultProfile'] = $false } - -function Skip-Step { - param([string]$Name) - Write-Log "$Name - SKIPPED (disabled in config)" -Level WARN - $StepResults.Add(@{ Name = $Name; Status = "SKIPPED" }) -} - -# ----------------------------------------------------------------------- -# Step 0a - Admin account -# ----------------------------------------------------------------------- -if ($stepsEnabled['adminAccount']) { - Invoke-Step -Name "Step 0a - Admin account" -Action { - & "$ScriptRoot\scripts\00-admin-account.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 0a - Admin account" } - -# ----------------------------------------------------------------------- -# Step 0b - Windows activation -# ----------------------------------------------------------------------- -if ($stepsEnabled['activation']) { - Invoke-Step -Name "Step 0b - Windows activation" -Action { - & "$ScriptRoot\scripts\08-activation.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 0b - Windows activation" } - -# ----------------------------------------------------------------------- -# Step 1 - Bloatware removal -# ----------------------------------------------------------------------- -if ($stepsEnabled['bloatware']) { - Invoke-Step -Name "Step 1 - Bloatware removal" -Action { - & "$ScriptRoot\scripts\01-bloatware.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 1 - Bloatware removal" } - -# ----------------------------------------------------------------------- -# Step 2 - Software installation -# ----------------------------------------------------------------------- -if ($stepsEnabled['software']) { - Invoke-Step -Name "Step 2 - Software installation" -Action { - & "$ScriptRoot\scripts\02-software.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 2 - Software installation" } - -# ----------------------------------------------------------------------- -# Step 3 - System registry (HKLM) -# ----------------------------------------------------------------------- -if ($stepsEnabled['systemRegistry']) { - Invoke-Step -Name "Step 3 - System registry" -Action { - & "$ScriptRoot\scripts\03-system-registry.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 3 - System registry" } - -# ----------------------------------------------------------------------- -# Step 4 - Default profile (NTUSER.DAT) -# ----------------------------------------------------------------------- -if ($stepsEnabled['defaultProfile']) { - Invoke-Step -Name "Step 4 - Default profile" -Action { - & "$ScriptRoot\scripts\04-default-profile.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 4 - Default profile" } - -# ----------------------------------------------------------------------- -# Step 5 - Personalization -# ----------------------------------------------------------------------- -if ($stepsEnabled['personalization']) { - Invoke-Step -Name "Step 5 - Personalization" -Action { - & "$ScriptRoot\scripts\05-personalization.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 5 - Personalization" } - -# ----------------------------------------------------------------------- -# Step 6 - Scheduled tasks -# ----------------------------------------------------------------------- -if ($stepsEnabled['scheduledTasks']) { - Invoke-Step -Name "Step 6 - Scheduled tasks" -Action { - & "$ScriptRoot\scripts\06-scheduled-tasks.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 6 - Scheduled tasks" } - -# ----------------------------------------------------------------------- -# Step 7 - DesktopInfo -# ----------------------------------------------------------------------- -if ($stepsEnabled['desktopInfo']) { - Invoke-Step -Name "Step 7 - DesktopInfo" -Action { - & "$ScriptRoot\scripts\07-desktop-info.ps1" -Config $Config -LogFile $LogFile - } -} else { Skip-Step "Step 7 - DesktopInfo" } - -# ----------------------------------------------------------------------- -# Summary -# ----------------------------------------------------------------------- -Write-Log "========================================" -Level INFO -Write-Log "SUMMARY" -Level INFO -Write-Log "========================================" -Level INFO - -$countOK = ($StepResults | Where-Object { $_.Status -eq "OK" }).Count -$countError = ($StepResults | Where-Object { $_.Status -eq "ERROR" }).Count -$countSkipped = ($StepResults | Where-Object { $_.Status -eq "SKIPPED" }).Count -$countDryRun = ($StepResults | Where-Object { $_.Status -eq "DRYRUN" }).Count - -foreach ($r in $StepResults) { - $lvl = switch ($r.Status) { - "OK" { "OK" } - "ERROR" { "ERROR" } - "SKIPPED" { "WARN" } - "DRYRUN" { "WARN" } - } - Write-Log "$($r.Status.PadRight(8)) $($r.Name)" -Level $lvl -} - -Write-Log "----------------------------------------" -Level INFO -Write-Log "OK: $countOK ERROR: $countError SKIPPED: $countSkipped DRYRUN: $countDryRun" -Level INFO -Write-Log "Log saved to: $LogFile" -Level INFO -Write-Log "========================================" -Level INFO - -if ($countError -gt 0) { - Write-Log "Deployment finished with errors. Review log: $LogFile" -Level ERROR - exit 1 -} else { - Write-Log "Deployment finished successfully." -Level OK - exit 0 -} diff --git a/flash/Run.cmd b/flash/Run.cmd deleted file mode 100644 index f7efc56..0000000 --- a/flash/Run.cmd +++ /dev/null @@ -1,125 +0,0 @@ -@echo off -chcp 65001 >nul -setlocal EnableDelayedExpansion - -:: ----------------------------------------------------------------------- -:: Auto-elevate to Administrator if not already elevated -:: ----------------------------------------------------------------------- -net session >nul 2>&1 -if %errorlevel% neq 0 ( - echo Requesting administrator privileges... - powershell -NoProfile -Command "Start-Process -FilePath '%~f0' -Verb RunAs" - exit /b -) - -:: ----------------------------------------------------------------------- -:: Paths -:: ----------------------------------------------------------------------- -set "SCRIPT_DIR=%~dp0" -set "DEPLOY_PS1=%SCRIPT_DIR%Deploy-Windows.ps1" -set "CONFIG_JSON=%SCRIPT_DIR%config\config.json" -set "CONFIG_EDITOR=%SCRIPT_DIR%config-editor.hta" -set "LOG_FILE=C:\Windows\Setup\Scripts\Deploy.log" - -:MENU -cls -echo. -echo ================================================ -echo X9 - Windows Deployment -echo ================================================ -echo. -echo Config : %CONFIG_JSON% -echo Log : %LOG_FILE% -echo. -echo [1] Full deployment (uses config.json) -echo [2] Dry run (no changes, log only) -echo [3] Skip bloatware removal -echo [4] Skip software install -echo [5] Open config editor (config-editor.hta) -echo [0] Exit -echo. -set /p CHOICE=" Select [0-5]: " - -if "%CHOICE%"=="0" goto EXIT -if "%CHOICE%"=="1" goto FULL -if "%CHOICE%"=="2" goto DRYRUN -if "%CHOICE%"=="3" goto SKIP_BLOATWARE -if "%CHOICE%"=="4" goto SKIP_SOFTWARE -if "%CHOICE%"=="5" goto OPEN_EDITOR - -echo Invalid choice. Try again. -timeout /t 2 >nul -goto MENU - -:: ----------------------------------------------------------------------- -:: [1] Full deployment -:: ----------------------------------------------------------------------- -:FULL -cls -echo. -echo Starting full deployment... -echo. -powershell -NoProfile -ExecutionPolicy Bypass -File "%DEPLOY_PS1%" -goto DONE - -:: ----------------------------------------------------------------------- -:: [2] Dry run -:: ----------------------------------------------------------------------- -:DRYRUN -cls -echo. -echo Starting dry run (no changes will be made)... -echo. -powershell -NoProfile -ExecutionPolicy Bypass -File "%DEPLOY_PS1%" -DryRun -goto DONE - -:: ----------------------------------------------------------------------- -:: [3] Skip bloatware -:: ----------------------------------------------------------------------- -:SKIP_BLOATWARE -cls -echo. -echo Starting deployment (bloatware removal skipped)... -echo. -powershell -NoProfile -ExecutionPolicy Bypass -File "%DEPLOY_PS1%" -SkipBloatware -goto DONE - -:: ----------------------------------------------------------------------- -:: [4] Skip software -:: ----------------------------------------------------------------------- -:SKIP_SOFTWARE -cls -echo. -echo Starting deployment (software install skipped)... -echo. -powershell -NoProfile -ExecutionPolicy Bypass -File "%DEPLOY_PS1%" -SkipSoftware -goto DONE - -:: ----------------------------------------------------------------------- -:: [5] Config editor -:: ----------------------------------------------------------------------- -:OPEN_EDITOR -if not exist "%CONFIG_EDITOR%" ( - echo ERROR: config-editor.hta not found: %CONFIG_EDITOR% - pause - goto MENU -) -start "" mshta.exe "%CONFIG_EDITOR%" -goto MENU - -:: ----------------------------------------------------------------------- -:: Done -:: ----------------------------------------------------------------------- -:DONE -echo. -echo ================================================ -echo Deployment finished. -echo Log: %LOG_FILE% -echo ================================================ -echo. -pause -goto MENU - -:EXIT -endlocal -exit /b 0 diff --git a/flash/config-editor.hta b/flash/config-editor.hta deleted file mode 100644 index 168b558..0000000 --- a/flash/config-editor.hta +++ /dev/null @@ -1,632 +0,0 @@ - - -X9 - Deployment Config Editor - - - - - - - - -
-
Steps
-
Software
-
Settings
-
- -
- - -
- - - - - - - - - - - -
OnStepName
-
- - -
- - - - - - - - - - -
Package NameWinget ID
- -
- - -
-
Deployment
-
-
Timezone
-
- -
Locale
-
-
- -
Admin Account
-
-
Username
-
- -
Password
-
- -
Description
-
-
- -
PDF Default
-
-
Force Adobe Reader
-
- -
Scheduled Task
-
-
- -
Desktop Info
-
-
Enabled
-
- -
Position
-
- -
- -
Font Size
-
- -
Font Color
-
-
- -
Activation
-
-
Product Key
-
- -
KMS Server
-
-
-
- -
- - - -
- - - - diff --git a/flash/config/config.json b/flash/config/config.json deleted file mode 100644 index 138c78b..0000000 --- a/flash/config/config.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "steps": { - "adminAccount": true, - "bloatware": true, - "software": true, - "systemRegistry": true, - "defaultProfile": true, - "personalization": true, - "scheduledTasks": true, - "desktopInfo": true, - "activation": true - }, - "deployment": { - "timezone": "Central Europe Standard Time", - "locale": "cs-CZ" - }, - "adminAccount": { - "username": "adminx9", - "password": "AdminX9.AdminX9", - "description": "X9 MSP admin account" - }, - "activation": { - "productKey": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", - "kmsServer": "" - }, - "software": { - "install": [ - { "name": "7-Zip", "wingetId": "7zip.7zip" }, - { "name": "Adobe Acrobat Reader","wingetId": "Adobe.Acrobat.Reader.64-bit" }, - { "name": "OpenVPN Connect", "wingetId": "OpenVPNTechnologies.OpenVPNConnect" } - ] - }, - "bloatware": { - "keepPackages": [ - "Microsoft.WindowsCalculator" - ] - }, - "desktopInfo": { - "enabled": true, - "position": "bottomRight", - "fontSize": 12, - "fontColor": "#FFFFFF", - "backgroundColor": "transparent" - }, - "pdfDefault": { - "forceAdobeReader": true, - "scheduledTaskEnabled": true - } -} diff --git a/flash/jak_na_to.txt b/flash/jak_na_to.txt deleted file mode 100644 index ef7edb2..0000000 --- a/flash/jak_na_to.txt +++ /dev/null @@ -1,88 +0,0 @@ -X9 - Windows Deployment -======================== -Automatizovana priprava noveho Windows 10/11 pocitace pro klienta. -Spustit jednou jako Administrator na ciste nainstalovanem Windows. - - -CO JE NA FLASHCE ----------------- -Run.cmd - SPUSTIT TOTO. Hlavni spoustec s menu. -config-editor.hta - Graficky editor konfigurace (dvojklik). -Deploy-Windows.ps1 - Hlavni deployment skript (spousti Run.cmd). -config\config.json - Konfigurace deploymentu. -scripts\ - Jednotlive kroky deploymentu (00-08). - - -JAK NA TO ---------- -1. Zapojit flashku do pocitace. - -2. Spustit Run.cmd pravym tlacitkem > "Spustit jako spravce". - (nebo dvojklik - skript si sam vyziada adminova prava) - -3. Zobrazit se menu: - [1] Full deployment - spusti vsechny kroky dle config.json - [2] Dry run - projde vsechny kroky BEZ zmen, jen loguje - [3] Skip bloatware - deployment bez odstranovani aplikaci - [4] Skip software - deployment bez instalace softwaru - [5] Open config editor - otevre graficky editor konfigurace - [0] Exit - -4. Vybrat [1] pro standardni deployment. - -5. Po dokonceni zkontrolovat log: - C:\Windows\Setup\Scripts\Deploy.log - - -PRED DEPLOYMENTEM (volitelne) ------------------------------- -Otevrit config-editor.hta (dvojklik) a zkontrolovat / upravit: - - Zalozka STEPS - zapnout / vypnout jednotlive kroky - (kliknout na "i" pro popis co krok dela) - - Zalozka SOFTWARE - seznam aplikaci instalovanych pres winget - (pridat / odebrat balicky) - - Zalozka SETTINGS - casova zona, nazev admin uctu, - nastaveni DesktopInfo wallpaperu - -Po uprave kliknout "Save config.json". Zmeny se projeji pri -spusteni deploymentu. - - -CO DEPLOYMENT DELA (kroky v poradí) -------------------------------------- -00 Admin account - vytvori lokalni admin ucet pro MSP pristup -01 Bloatware - odebere nepotrebne aplikace (Teams, Xbox, ...) -02 Software - nainstaluje aplikace pres winget -03 System registry - HKLM tweaky (widgety, OneDrive, Edge, ...) -04 Default profile - nastaveni taskbaru a Exploreru pro vsechny uzivatele -05 Personalization - tmave tema, akcetni barva #223B47 -06 Scheduled tasks - registruje 4 ulohy (systray, PDF, DesktopInfo, ...) -07 DesktopInfo - vlastni tapeta s info o pocitaci (jmeno, IP, OS, ...) -08 Activation - aktivace Windows - - -LOG ---- -Kazdy krok zapisuje do: - C:\Windows\Setup\Scripts\Deploy.log - -Format zaznamu: - [HH:mm:ss] [OK/ERROR/WARN] zprava - -Na konci logu je souhrn: pocet OK / ERROR / SKIPPED. - - -POZNAMKY --------- -- Skript vyzaduje pripojeni k internetu (winget instalace). -- Restart pocitace neni potreba - spoustec na to upozorni pokud ano. -- Nastaveni z Default Profile se aplikuji na KAZDEHO noveho uzivatele. -- DesktopInfo tapeta se obnovi pri kazdem prihlaseni. -- PDF default (Adobe Reader) se obnovuje pri kazdem prihlaseni jako ochrana - proti tomu, ze Edge prepise asociaci. - - -X9.cz MSP deployment suite diff --git a/flash/scripts/00-admin-account.ps1 b/flash/scripts/00-admin-account.ps1 deleted file mode 100644 index bbd3390..0000000 --- a/flash/scripts/00-admin-account.ps1 +++ /dev/null @@ -1,94 +0,0 @@ -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 -} - -# ----------------------------------------------------------------------- -# Read account config -# ----------------------------------------------------------------------- -$accountName = "adminx9" -$accountPass = "AdminX9.AdminX9" -$accountDesc = "X9 MSP admin account" - -if ($Config -and $Config.adminAccount) { - if ($Config.adminAccount.username) { $accountName = $Config.adminAccount.username } - if ($Config.adminAccount.password) { $accountPass = $Config.adminAccount.password } - if ($Config.adminAccount.description) { $accountDesc = $Config.adminAccount.description } -} - -Write-Log "Creating admin account: $accountName" -Level INFO - -$securePass = ConvertTo-SecureString $accountPass -AsPlainText -Force - -# ----------------------------------------------------------------------- -# Create or update account -# ----------------------------------------------------------------------- -$existing = Get-LocalUser -Name $accountName -ErrorAction SilentlyContinue - -if ($existing) { - Write-Log " Account already exists - updating password" -Level INFO - try { - Set-LocalUser -Name $accountName -Password $securePass -PasswordNeverExpires $true - Enable-LocalUser -Name $accountName - Write-Log " Account updated: $accountName" -Level OK - } - catch { - Write-Log " Failed to update account: $_" -Level ERROR - } -} else { - try { - New-LocalUser -Name $accountName ` - -Password $securePass ` - -Description $accountDesc ` - -PasswordNeverExpires ` - -UserMayNotChangePassword ` - -ErrorAction Stop | Out-Null - Write-Log " Account created: $accountName" -Level OK - } - catch { - Write-Log " Failed to create account: $_" -Level ERROR - } -} - -# ----------------------------------------------------------------------- -# Add to Administrators group -# ----------------------------------------------------------------------- -try { - $adminsGroup = (Get-LocalGroup | Where-Object { $_.SID -eq "S-1-5-32-544" }).Name - $members = Get-LocalGroupMember -Group $adminsGroup -ErrorAction SilentlyContinue | - Where-Object { $_.Name -like "*$accountName" } - if (-not $members) { - Add-LocalGroupMember -Group $adminsGroup -Member $accountName -ErrorAction Stop - Write-Log " Added to $adminsGroup" -Level OK - } else { - Write-Log " Already in $adminsGroup" -Level INFO - } -} -catch { - Write-Log " Failed to add to Administrators: $_" -Level ERROR -} - -# ----------------------------------------------------------------------- -# Hide account from login screen -# ----------------------------------------------------------------------- -try { - $specialPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" - if (-not (Test-Path $specialPath)) { - New-Item -Path $specialPath -Force | Out-Null - } - Set-ItemProperty -Path $specialPath -Name $accountName -Value 0 -Type DWord -Force - Write-Log " Account hidden from login screen" -Level OK -} -catch { - Write-Log " Failed to hide account from login screen: $_" -Level ERROR -} - -Write-Log "Step 0a - Admin account complete" -Level OK diff --git a/flash/scripts/01-bloatware.ps1 b/flash/scripts/01-bloatware.ps1 deleted file mode 100644 index 30fbbe4..0000000 --- a/flash/scripts/01-bloatware.ps1 +++ /dev/null @@ -1,184 +0,0 @@ -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 -} - -# ----------------------------------------------------------------------- -# 1a - AppX packages -# ----------------------------------------------------------------------- -$AppxToRemove = @( - "Microsoft.Microsoft3DViewer" - "Microsoft.BingSearch" - "Microsoft.WindowsCamera" - "Clipchamp.Clipchamp" - "Microsoft.WindowsAlarms" - "Microsoft.Copilot" - "Microsoft.549981C3F5F10" - "Microsoft.Windows.DevHome" - "MicrosoftCorporationII.MicrosoftFamily" - "Microsoft.WindowsFeedbackHub" - "Microsoft.Edge.GameAssist" - "Microsoft.GetHelp" - "Microsoft.Getstarted" - "microsoft.windowscommunicationsapps" - "Microsoft.WindowsMaps" - "Microsoft.MixedReality.Portal" - "Microsoft.BingNews" - "Microsoft.MicrosoftOfficeHub" - "Microsoft.Office.OneNote" - "Microsoft.OutlookForWindows" - "Microsoft.Paint" - "Microsoft.MSPaint" - "Microsoft.People" - "Microsoft.Windows.Photos" - "Microsoft.PowerAutomateDesktop" - "MicrosoftCorporationII.QuickAssist" - "Microsoft.SkypeApp" - "Microsoft.ScreenSketch" - "Microsoft.MicrosoftSolitaireCollection" - "Microsoft.MicrosoftStickyNotes" - "MicrosoftTeams" - "MSTeams" - "Microsoft.Todos" - "Microsoft.WindowsSoundRecorder" - "Microsoft.Wallet" - "Microsoft.BingWeather" - "Microsoft.WindowsTerminal" - "Microsoft.Xbox.TCUI" - "Microsoft.XboxApp" - "Microsoft.XboxGameOverlay" - "Microsoft.XboxGamingOverlay" - "Microsoft.XboxIdentityProvider" - "Microsoft.XboxSpeechToTextOverlay" - "Microsoft.GamingApp" - "Microsoft.YourPhone" - "Microsoft.ZuneMusic" - "Microsoft.ZuneVideo" - "7EE7776C.LinkedInforWindows" -) - -# Packages to always keep -$KeepPackages = @("Microsoft.WindowsCalculator") -if ($Config -and $Config.bloatware -and $Config.bloatware.keepPackages) { - $KeepPackages += $Config.bloatware.keepPackages -} -$KeepPackages = $KeepPackages | Select-Object -Unique - -Write-Log "1a - Removing AppX packages" -Level STEP - -foreach ($pkg in $AppxToRemove) { - if ($KeepPackages -contains $pkg) { - Write-Log " KEEP $pkg" -Level INFO - continue - } - - # Installed packages (current user + all users) - $installed = Get-AppxPackage -Name $pkg -AllUsers -ErrorAction SilentlyContinue - if ($installed) { - try { - $installed | Remove-AppxPackage -AllUsers -ErrorAction Stop - Write-Log " Removed AppxPackage: $pkg" -Level OK - } - catch { - Write-Log " Failed to remove AppxPackage $pkg - $_" -Level WARN - } - } - - # Provisioned packages (for new users) - $provisioned = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | - Where-Object { $_.DisplayName -eq $pkg } - if ($provisioned) { - try { - $provisioned | Remove-AppxProvisionedPackage -Online -ErrorAction Stop | Out-Null - Write-Log " Removed provisioned: $pkg" -Level OK - } - catch { - Write-Log " Failed to remove provisioned $pkg - $_" -Level WARN - } - } - - if (-not $installed -and -not $provisioned) { - Write-Log " Not found (already removed): $pkg" -Level INFO - } -} - -# ----------------------------------------------------------------------- -# 1b - Windows Capabilities -# ----------------------------------------------------------------------- -$CapabilitiesToRemove = @( - "Print.Fax.Scan" - "Language.Handwriting" - "Browser.InternetExplorer" - "MathRecognizer" - "OneCoreUAP.OneSync" - "OpenSSH.Client" - "Microsoft.Windows.MSPaint" - "Microsoft.Windows.PowerShell.ISE" - "App.Support.QuickAssist" - "Microsoft.Windows.SnippingTool" - "App.StepsRecorder" - "Hello.Face" - "Media.WindowsMediaPlayer" - "Microsoft.Windows.WordPad" -) - -Write-Log "1b - Removing Windows Capabilities" -Level STEP - -$installedCaps = Get-WindowsCapability -Online -ErrorAction SilentlyContinue - -foreach ($cap in $CapabilitiesToRemove) { - # Match by prefix (e.g. Hello.Face matches Hello.Face.20134.0.0.0) - $matches = $installedCaps | Where-Object { - $_.Name -like "$cap*" -and $_.State -eq "Installed" - } - if ($matches) { - foreach ($c in $matches) { - try { - Remove-WindowsCapability -Online -Name $c.Name -ErrorAction Stop | Out-Null - Write-Log " Removed capability: $($c.Name)" -Level OK - } - catch { - Write-Log " Failed to remove capability $($c.Name) - $_" -Level WARN - } - } - } else { - Write-Log " Not found or not installed: $cap" -Level INFO - } -} - -# ----------------------------------------------------------------------- -# 1c - Windows Optional Features -# ----------------------------------------------------------------------- -$FeaturesToDisable = @( - "MediaPlayback" - "MicrosoftWindowsPowerShellV2Root" - "Recall" - "Microsoft-SnippingTool" -) - -Write-Log "1c - Disabling Windows Optional Features" -Level STEP - -foreach ($feat in $FeaturesToDisable) { - $feature = Get-WindowsOptionalFeature -Online -FeatureName $feat -ErrorAction SilentlyContinue - if ($feature -and $feature.State -eq "Enabled") { - try { - Disable-WindowsOptionalFeature -Online -FeatureName $feat -NoRestart -ErrorAction Stop | Out-Null - Write-Log " Disabled feature: $feat" -Level OK - } - catch { - Write-Log " Failed to disable feature $feat - $_" -Level WARN - } - } else { - Write-Log " Not enabled or not found: $feat" -Level INFO - } -} - -Write-Log "Step 1 complete" -Level OK diff --git a/flash/scripts/02-software.ps1 b/flash/scripts/02-software.ps1 deleted file mode 100644 index f6d7cf1..0000000 --- a/flash/scripts/02-software.ps1 +++ /dev/null @@ -1,122 +0,0 @@ -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 -} - -# ----------------------------------------------------------------------- -# Check winget availability -# ----------------------------------------------------------------------- -Write-Log "Checking winget availability" -Level INFO - -$winget = Get-Command winget -ErrorAction SilentlyContinue -if (-not $winget) { - # Try to find winget in known locations - $wingetPaths = @( - "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe" - "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller*\winget.exe" - ) - foreach ($p in $wingetPaths) { - $found = Get-Item $p -ErrorAction SilentlyContinue | Select-Object -First 1 - if ($found) { $winget = $found.FullName; break } - } -} - -if (-not $winget) { - Write-Log "winget not found - software installation skipped" -Level ERROR - exit 1 -} - -Write-Log "winget found: $($winget.Source -or $winget)" -Level OK - -# Accept agreements upfront -& winget source update --accept-source-agreements 2>&1 | Out-Null - -# ----------------------------------------------------------------------- -# Install packages from config -# ----------------------------------------------------------------------- -if (-not $Config -or -not $Config.software -or -not $Config.software.install) { - Write-Log "No software list in config - skipping installs" -Level WARN -} else { - foreach ($pkg in $Config.software.install) { - Write-Log "Installing $($pkg.name) ($($pkg.wingetId))" -Level INFO - $result = & winget install --id $pkg.wingetId ` - --silent ` - --accept-package-agreements ` - --accept-source-agreements ` - --disable-interactivity ` - 2>&1 - - $exitCode = $LASTEXITCODE - if ($exitCode -eq 0) { - Write-Log " Installed OK: $($pkg.name)" -Level OK - } elseif ($exitCode -eq -1978335189) { - # 0x8A150011 = already installed - Write-Log " Already installed: $($pkg.name)" -Level OK - } else { - Write-Log " Failed: $($pkg.name) (exit $exitCode)" -Level ERROR - Write-Log " Output: $($result -join ' ')" -Level ERROR - } - } -} - -# ----------------------------------------------------------------------- -# Set Adobe Reader as default PDF app -# ----------------------------------------------------------------------- -$forcePdf = $true -if ($Config -and $Config.pdfDefault) { - $forcePdf = [bool]$Config.pdfDefault.forceAdobeReader -} - -if ($forcePdf) { - Write-Log "Setting Adobe Reader as default PDF app" -Level INFO - - # Find Adobe PDF viewer executable (Acrobat DC or Reader DC) - $acroPaths = @( - "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe" - "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe" - "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" - "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" - "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe" - ) - $acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1 - - if (-not $acroExe) { - Write-Log " Adobe PDF viewer not found - PDF default not set" -Level WARN - } else { - Write-Log " Found: $acroExe" -Level INFO - - # Set file type association via HKCR (system-wide, requires admin) - $progId = "AcroExch.Document.DC" - $openCmd = "`"$acroExe`" `"%1`"" - - # HKCR\.pdf -> progId - if (-not (Test-Path "HKCR:\.pdf")) { - New-Item -Path "HKCR:\.pdf" -Force | Out-Null - } - Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId - - # HKCR\AcroExch.Document.DC\shell\open\command - $cmdPath = "HKCR:\$progId\shell\open\command" - if (-not (Test-Path $cmdPath)) { - New-Item -Path $cmdPath -Force | Out-Null - } - Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd - - # Note: HKCU UserChoice requires a Windows-computed Hash value to be valid. - # Direct ProgId write without Hash is silently reset by Windows on next access. - # HKCR write above provides the system-wide default; per-user default is - # handled by the PDF-DefaultApp scheduled task via HKCR on every logon. - - Write-Log " PDF default set to AcroRd32 (HKCR)" -Level OK - } -} - -Write-Log "Step 2 complete" -Level OK diff --git a/flash/scripts/03-system-registry.ps1 b/flash/scripts/03-system-registry.ps1 deleted file mode 100644 index ac68be4..0000000 --- a/flash/scripts/03-system-registry.ps1 +++ /dev/null @@ -1,322 +0,0 @@ -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 -} - -Add-Type -TypeDefinition @" -using System; -using System.Runtime.InteropServices; -public class RegPrivilege { - [DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)] - static extern bool AdjustTokenPrivileges(IntPtr htok, bool disAll, ref TokPriv1Luid newState, int len, IntPtr prev, IntPtr relen); - [DllImport("kernel32.dll", ExactSpelling=true)] - static extern IntPtr GetCurrentProcess(); - [DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)] - static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok); - [DllImport("advapi32.dll", SetLastError=true)] - static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); - [StructLayout(LayoutKind.Sequential, Pack=1)] - struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } - const int TOKEN_QUERY = 0x8; - const int TOKEN_ADJUST = 0x20; - const int SE_PRIVILEGE_ENABLED = 2; - public static bool Enable(string privilege) { - IntPtr htok = IntPtr.Zero; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST | TOKEN_QUERY, ref htok)) return false; - TokPriv1Luid tp; tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED; - if (!LookupPrivilegeValue(null, privilege, ref tp.Luid)) return false; - return AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); - } -} -"@ -ErrorAction SilentlyContinue - -function Grant-RegWriteAccess { - param([string]$Path) - # Grants Administrators FullControl on a TrustedInstaller-owned registry key. - # Enables SeTakeOwnershipPrivilege + SeRestorePrivilege to override ACL. - try { - [RegPrivilege]::Enable("SeTakeOwnershipPrivilege") | Out-Null - [RegPrivilege]::Enable("SeRestorePrivilege") | Out-Null - - $hive = $Path -replace '^(HKLM|HKCU|HKU|HKCR|HKCC):\\.*', '$1' - $subkey = $Path -replace '^(HKLM|HKCU|HKU|HKCR|HKCC):\\', '' - $rootKey = switch ($hive) { - "HKLM" { [Microsoft.Win32.Registry]::LocalMachine } - "HKCU" { [Microsoft.Win32.Registry]::CurrentUser } - "HKCR" { [Microsoft.Win32.Registry]::ClassesRoot } - } - - # Take ownership (requires SeTakeOwnershipPrivilege) - $key = $rootKey.OpenSubKey($subkey, - [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, - [System.Security.AccessControl.RegistryRights]::TakeOwnership) - if ($key) { - $acl = $key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None) - $acl.SetOwner([System.Security.Principal.NTAccount]"BUILTIN\Administrators") - $key.SetAccessControl($acl) - $key.Close() - } - - # Grant FullControl to Administrators (requires ChangePermissions) - $key = $rootKey.OpenSubKey($subkey, - [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, - [System.Security.AccessControl.RegistryRights]::ChangePermissions) - if ($key) { - $acl = $key.GetAccessControl() - $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) - $key.SetAccessControl($acl) - $key.Close() - } - Write-Log " ACL fixed for $Path" -Level INFO - } - catch { - Write-Log " Grant-RegWriteAccess failed for $Path - $_" -Level WARN - } -} - -function Set-Reg { - param( - [string]$Path, - [string]$Name, - $Value, - [string]$Type = "DWord" - ) - try { - if (-not (Test-Path $Path)) { - New-Item -Path $Path -Force -ErrorAction Stop | Out-Null - } - Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop - Write-Log " SET $Path\$Name = $Value" -Level OK - } - catch { - # Retry 1: grant write access via ACL manipulation - try { - Grant-RegWriteAccess -Path $Path - if (-not (Test-Path $Path)) { - New-Item -Path $Path -Force -ErrorAction Stop | Out-Null - } - Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force -ErrorAction Stop - Write-Log " SET $Path\$Name = $Value (after ACL fix)" -Level OK - return - } - catch { } - - # Retry 2: write via scheduled task running as SYSTEM - # SYSTEM has full registry access regardless of key ACL - try { - $regType = switch ($Type) { - "DWord" { "REG_DWORD" } - "String" { "REG_SZ" } - "ExpandString"{ "REG_EXPAND_SZ" } - "MultiString" { "REG_MULTI_SZ" } - "QWord" { "REG_QWORD" } - default { "REG_DWORD" } - } - # Convert registry PS path to reg.exe path - $regPath = $Path -replace '^HKLM:\\', 'HKLM\' ` - -replace '^HKCU:\\', 'HKCU\' ` - -replace '^HKCR:\\', 'HKCR\' - $tempScript = "$env:TEMP\set-reg-system-$([System.IO.Path]::GetRandomFileName()).ps1" - "reg add `"$regPath`" /v `"$Name`" /t $regType /d $Value /f" | - Set-Content -Path $tempScript -Encoding UTF8 - - $taskName = "TempRegFix-$([System.IO.Path]::GetRandomFileName())" - $action = New-ScheduledTaskAction -Execute "cmd.exe" ` - -Argument "/c reg add `"$regPath`" /v `"$Name`" /t $regType /d $Value /f" - $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest - $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Seconds 30) - $task = New-ScheduledTask -Action $action -Principal $principal -Settings $settings - - Register-ScheduledTask -TaskName $taskName -InputObject $task -Force | Out-Null - Start-ScheduledTask -TaskName $taskName - Start-Sleep -Seconds 2 - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue - Remove-Item $tempScript -Force -ErrorAction SilentlyContinue - - # Verify it was written - $written = (Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue).$Name - if ($null -ne $written) { - Write-Log " SET $Path\$Name = $Value (via SYSTEM task)" -Level OK - } else { - Write-Log " FAILED $Path\$Name - SYSTEM task ran but value not found" -Level ERROR - } - } - catch { - Write-Log " FAILED $Path\$Name - $_" -Level ERROR - } - } -} - -function Remove-Reg { - param([string]$Path, [string]$Name) - try { - if (Test-Path $Path) { - Remove-ItemProperty -Path $Path -Name $Name -Force -ErrorAction SilentlyContinue - Write-Log " REMOVED $Path\$Name" -Level OK - } - } - catch { - Write-Log " FAILED removing $Path\$Name - $_" -Level ERROR - } -} - -Write-Log "3 - Applying HKLM system registry tweaks" -Level STEP - -# ----------------------------------------------------------------------- -# Bypass Network Requirement on OOBE (BypassNRO) -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" ` - -Name "BypassNRO" -Value 1 - -# ----------------------------------------------------------------------- -# Disable auto-install of Teams (Chat) -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications" ` - -Name "ConfigureChatAutoInstall" -Value 0 - -# ----------------------------------------------------------------------- -# Disable Cloud Optimized Content (ads in Start menu etc.) -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" ` - -Name "DisableCloudOptimizedContent" -Value 1 - -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent" ` - -Name "DisableWindowsConsumerFeatures" -Value 1 - -# ----------------------------------------------------------------------- -# Disable Widgets (News and Interests) -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Dsh" ` - -Name "AllowNewsAndInterests" -Value 0 - -# ----------------------------------------------------------------------- -# Microsoft Edge - hide First Run Experience -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Edge" ` - -Name "HideFirstRunExperience" -Value 1 - -# Also disable Edge desktop shortcut creation after install -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\EdgeUpdate" ` - -Name "CreateDesktopShortcutDefault" -Value 0 - -# ----------------------------------------------------------------------- -# Password - no expiration -# ----------------------------------------------------------------------- -Write-Log " Setting password max age to UNLIMITED" -Level INFO -$pwResult = & net accounts /maxpwage:UNLIMITED 2>&1 -if ($LASTEXITCODE -eq 0) { - Write-Log " Password max age set to UNLIMITED" -Level OK -} else { - Write-Log " Failed to set password max age: $pwResult" -Level ERROR -} - -# ----------------------------------------------------------------------- -# Time zone -# ----------------------------------------------------------------------- -$tz = "Central Europe Standard Time" -if ($Config -and $Config.deployment -and $Config.deployment.timezone) { - $tz = $Config.deployment.timezone -} -Write-Log " Setting time zone: $tz" -Level INFO -try { - Set-TimeZone -Id $tz -ErrorAction Stop - Write-Log " Time zone set: $tz" -Level OK -} -catch { - Write-Log " Failed to set time zone: $_" -Level ERROR -} - -# ----------------------------------------------------------------------- -# OneDrive - uninstall from clean Windows (no policy block) -# NOTE: No policy key is set intentionally - M365 installation can reinstall -# and run OneDrive normally. Policy DisableFileSyncNGSC would prevent that. -# ----------------------------------------------------------------------- -Write-Log " Uninstalling OneDrive" -Level INFO - -# Remove OneDriveSetup.exe if present -$oneDrivePaths = @( - "$env:SystemRoot\System32\OneDriveSetup.exe" - "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" -) -foreach ($odPath in $oneDrivePaths) { - if (Test-Path $odPath) { - try { - # Uninstall first - & $odPath /uninstall 2>&1 | Out-Null - Write-Log " OneDrive uninstalled via $odPath" -Level OK - } - catch { - Write-Log " OneDrive uninstall failed: $_" -Level WARN - } - } -} - -# Remove OneDrive Start Menu shortcut -$odLnk = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk" -if (Test-Path $odLnk) { - Remove-Item $odLnk -Force -ErrorAction SilentlyContinue - Write-Log " Removed OneDrive Start Menu shortcut" -Level OK -} - -# ----------------------------------------------------------------------- -# Outlook (new) - disable auto-install via UScheduler -# ----------------------------------------------------------------------- -Write-Log " Disabling Outlook (new) auto-install" -Level INFO - -$uschedulerPaths = @( - "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate" - "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\OutlookUpdate" -) -foreach ($uPath in $uschedulerPaths) { - if (Test-Path $uPath) { - try { - Remove-Item -Path $uPath -Recurse -Force - Write-Log " Removed UScheduler key: $uPath" -Level OK - } - catch { - Write-Log " Failed to remove UScheduler key: $_" -Level WARN - } - } -} - -# ----------------------------------------------------------------------- -# Disable GameDVR -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\GameDVR" ` - -Name "AllowGameDVR" -Value 0 - -# ----------------------------------------------------------------------- -# Disable Recall (Windows AI feature) -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsAI" ` - -Name "DisableAIDataAnalysis" -Value 1 - -# ----------------------------------------------------------------------- -# Search on taskbar - hide via HKLM policy (Win11 22H2+ enforcement) -# User-level SearchboxTaskbarMode alone is insufficient on newer Win11 builds; -# this policy key ensures the setting survives Windows Updates. -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search" ` - -Name "SearchOnTaskbarMode" -Value 0 - -# ----------------------------------------------------------------------- -# Start menu - hide Recommended section (Win11) -# ----------------------------------------------------------------------- -Set-Reg -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer" ` - -Name "HideRecommendedSection" -Value 1 - -Write-Log "Step 3 complete" -Level OK diff --git a/flash/scripts/04-default-profile.ps1 b/flash/scripts/04-default-profile.ps1 deleted file mode 100644 index 03b0b1e..0000000 --- a/flash/scripts/04-default-profile.ps1 +++ /dev/null @@ -1,324 +0,0 @@ -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 - Win10/11 (0 = hidden, 1 = icon, 2 = full box) - # Note: Win11 uses Search subkey, Win10 uses Explorer\Advanced - set both - Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Search" ` - -Name "SearchboxTaskbarMode" -Value 0 - 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 - # ----------------------------------------------------------------------- - # EnableAutoTray = 0 works on Win10; Win11 ignores it but set anyway - Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer" ` - -Name "EnableAutoTray" -Value 0 - - # Win11 workaround: clear cached tray icon streams so all icons appear on next login - # Windows rebuilds the streams with all icons visible when no cache exists - $trayNotifyKey = "HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" - if (Test-Path $trayNotifyKey) { - Remove-ItemProperty -Path $trayNotifyKey -Name "IconStreams" -Force -ErrorAction SilentlyContinue - Remove-ItemProperty -Path $trayNotifyKey -Name "PastIconsStream" -Force -ErrorAction SilentlyContinue - Write-Log " Cleared TrayNotify icon streams (Win11 systray workaround)" -Level OK - } - - # Also clear in Default hive so new users start with clean state - $defTrayKey = "Registry::HKU\DefaultProfile\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" - if (Test-Path $defTrayKey) { - Remove-ItemProperty -Path $defTrayKey -Name "IconStreams" -Force -ErrorAction SilentlyContinue - Remove-ItemProperty -Path $defTrayKey -Name "PastIconsStream" -Force -ErrorAction SilentlyContinue - Write-Log " Cleared TrayNotify icon streams in Default hive" -Level OK - } - - # ----------------------------------------------------------------------- - # Desktop icons - show This PC - # ----------------------------------------------------------------------- - # CLSID {20D04FE0-3AEA-1069-A2D8-08002B30309D} = This PC / Computer - Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" ` - -Name "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -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 - Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Start" ` - -Name "ConfigureStartPins" ` - -Value '{"pinnedList":[]}' ` - -Type "String" - - # Hide "Recently added" apps in Start menu - Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ` - -Name "Start_TrackProgs" -Value 0 - - # Hide recently opened files/docs from Start menu - Set-ProfileReg -SubKey "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ` - -Name "Start_TrackDocs" -Value 0 - - # ----------------------------------------------------------------------- - # 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 = @" - - - - - - - - - -"@ - $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 - } -} - -# ----------------------------------------------------------------------- -# Restart Explorer to apply taskbar/tray changes to current session -# ----------------------------------------------------------------------- -Write-Log "Restarting Explorer to apply taskbar changes" -Level INFO -try { - Stop-Process -Name explorer -Force -ErrorAction SilentlyContinue - Start-Sleep -Seconds 2 - Start-Process explorer - Write-Log "Explorer restarted" -Level OK -} -catch { - Write-Log "Explorer restart failed (non-fatal): $_" -Level WARN -} - -Write-Log "Step 4 complete" -Level OK diff --git a/flash/scripts/05-personalization.ps1 b/flash/scripts/05-personalization.ps1 deleted file mode 100644 index 957806e..0000000 --- a/flash/scripts/05-personalization.ps1 +++ /dev/null @@ -1,172 +0,0 @@ -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 -} - -# Accent color #223B47 stored as ABGR DWORD: 0xFF473B22 -# A=FF B=47 G=3B R=22 -> 0xFF473B22 = 4283612962 -$AccentColorABGR = 0xFF473B22 - -# Gradient colors (Windows generates these automatically but we set them explicitly) -# AccentPalette is 32 bytes - 8 shades of the accent color (BGRA each) -# We use the same color for all shades as a safe default -$AccentColorHex = "#223B47" - -function Set-Reg { - param([string]$Path, [string]$Name, $Value, [string]$Type = "DWord") - try { - if (-not (Test-Path $Path)) { New-Item -Path $Path -Force | Out-Null } - Set-ItemProperty -Path $Path -Name $Name -Value $Value -Type $Type -Force - Write-Log " SET $Path\$Name = $Value" -Level OK - } - catch { - Write-Log " FAILED $Path\$Name - $_" -Level ERROR - } -} - -function Apply-ThemeSettings { - param([string]$HiveRoot) # "HKCU:" or "Registry::HKU\DefaultProfile" - - # ----------------------------------------------------------------------- - # System theme - Dark (taskbar, Start, action center) - # ----------------------------------------------------------------------- - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" ` - -Name "SystemUsesLightTheme" -Value 0 - - # ----------------------------------------------------------------------- - # App theme - Light - # ----------------------------------------------------------------------- - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" ` - -Name "AppsUseLightTheme" -Value 1 - - # ----------------------------------------------------------------------- - # Accent color on Start and taskbar - # ----------------------------------------------------------------------- - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" ` - -Name "ColorPrevalence" -Value 1 - - # ----------------------------------------------------------------------- - # Transparency effects - disabled - # ----------------------------------------------------------------------- - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" ` - -Name "EnableTransparency" -Value 0 - - # ----------------------------------------------------------------------- - # Accent color - # ----------------------------------------------------------------------- - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\DWM" ` - -Name "AccentColor" -Value $AccentColorABGR -Type "DWord" - - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\DWM" ` - -Name "ColorizationColor" -Value $AccentColorABGR -Type "DWord" - - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\DWM" ` - -Name "ColorizationAfterglow" -Value $AccentColorABGR -Type "DWord" - - # Accent color on title bars and borders - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\DWM" ` - -Name "ColorPrevalence" -Value 1 - - # ----------------------------------------------------------------------- - # Wallpaper - solid color #223B47 (fallback before DesktopInfo runs) - # ----------------------------------------------------------------------- - # Background color as decimal RGB - Set-Reg -Path "$HiveRoot\Control Panel\Colors" ` - -Name "Background" -Value "34 59 71" -Type "String" - - Set-Reg -Path "$HiveRoot\Control Panel\Desktop" ` - -Name "WallpaperStyle" -Value "0" -Type "String" - - Set-Reg -Path "$HiveRoot\Control Panel\Desktop" ` - -Name "TileWallpaper" -Value "0" -Type "String" - - # ----------------------------------------------------------------------- - # Desktop icons - show This PC - # ----------------------------------------------------------------------- - Set-Reg -Path "$HiveRoot\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" ` - -Name "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -Value 0 -} - -# ----------------------------------------------------------------------- -# Load Default hive -# ----------------------------------------------------------------------- -$hivePath = "C:\Users\Default\NTUSER.DAT" -$hiveKey = "DefaultProfile" - -Write-Log "Loading Default hive for personalization" -Level INFO - -& 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 - Write-Log "Applying personalization to current user only" -Level WARN - - Write-Log "Applying theme to current user (HKCU)" -Level STEP - Apply-ThemeSettings -HiveRoot "HKCU:" - - # Set wallpaper via SystemParametersInfo for current user - Add-Type -TypeDefinition @" -using System; -using System.Runtime.InteropServices; -public class WallpaperHelper { - [DllImport("user32.dll", CharSet=CharSet.Auto)] - public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); -} -"@ -ErrorAction SilentlyContinue - [WallpaperHelper]::SystemParametersInfo(20, 0, "", 3) | Out-Null - exit 0 -} - -try { - Write-Log "Applying theme to Default hive" -Level STEP - Apply-ThemeSettings -HiveRoot "Registry::HKU\DefaultProfile" - - Write-Log "Applying theme to current user (HKCU)" -Level STEP - Apply-ThemeSettings -HiveRoot "HKCU:" -} -finally { - [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 - } -} - -# ----------------------------------------------------------------------- -# Apply wallpaper (solid color) to current desktop session -# ----------------------------------------------------------------------- -Write-Log "Setting desktop wallpaper to solid color" -Level INFO - -try { - Add-Type -TypeDefinition @" -using System; -using System.Runtime.InteropServices; -public class WallpaperHelper { - [DllImport("user32.dll", CharSet=CharSet.Auto)] - public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); -} -"@ -ErrorAction SilentlyContinue - - # SPI_SETDESKTOPWALLPAPER=20, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE=3 - # Empty string = solid color defined in Control Panel\Colors\Background - [WallpaperHelper]::SystemParametersInfo(20, 0, "", 3) | Out-Null - Write-Log " Desktop wallpaper updated" -Level OK -} -catch { - Write-Log " Failed to update wallpaper: $_" -Level WARN -} - -Write-Log "Step 5 complete" -Level OK diff --git a/flash/scripts/06-scheduled-tasks.ps1 b/flash/scripts/06-scheduled-tasks.ps1 deleted file mode 100644 index fbdfec8..0000000 --- a/flash/scripts/06-scheduled-tasks.ps1 +++ /dev/null @@ -1,194 +0,0 @@ -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 -} - -$ScriptDir = "C:\Windows\Setup\Scripts" -if (-not (Test-Path $ScriptDir)) { - New-Item -ItemType Directory -Path $ScriptDir -Force | Out-Null -} - -function Register-Task { - param( - [string]$TaskName, - [string]$Description, - [object]$Action, - [object[]]$Triggers, - [string]$RunLevel = "Highest" - ) - try { - # Remove existing task with same name - Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue - - $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 5) ` - -MultipleInstances IgnoreNew ` - -StartWhenAvailable - - $principal = New-ScheduledTaskPrincipal -GroupId "Users" ` - -RunLevel $RunLevel - - $task = New-ScheduledTask -Action $Action ` - -Trigger $Triggers ` - -Settings $settings ` - -Principal $principal ` - -Description $Description - - Register-ScheduledTask -TaskName $TaskName -InputObject $task -Force | Out-Null - Write-Log " Registered task: $TaskName" -Level OK - } - catch { - Write-Log " Failed to register task $TaskName - $_" -Level ERROR - } -} - -# ----------------------------------------------------------------------- -# Task: ShowAllTrayIcons -# Runs on logon: clears TrayNotify icon cache and restarts Explorer so all -# tray icons are visible on first login (Win10: EnableAutoTray=0, Win11: cache clear) -# ----------------------------------------------------------------------- -Write-Log "Registering task: ShowAllTrayIcons" -Level STEP - -$showTrayScript = "$ScriptDir\ShowAllTrayIcons.ps1" -@' -# Win10: disable auto-hiding of tray icons -$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer" -Set-ItemProperty -Path $regPath -Name "EnableAutoTray" -Value 0 -Force -ErrorAction SilentlyContinue - -# Win11: clear icon stream cache so all icons become visible after Explorer restart -$trayPath = "HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify" -if (Test-Path $trayPath) { - Remove-ItemProperty -Path $trayPath -Name "IconStreams" -Force -ErrorAction SilentlyContinue - Remove-ItemProperty -Path $trayPath -Name "PastIconsStream" -Force -ErrorAction SilentlyContinue -} - -# Restart Explorer to apply changes -Stop-Process -Name explorer -Force -ErrorAction SilentlyContinue -Start-Sleep -Milliseconds 1500 -if (-not (Get-Process explorer -ErrorAction SilentlyContinue)) { - Start-Process explorer -} -'@ | Set-Content -Path $showTrayScript -Encoding UTF8 -Force - -$showTrayAction = New-ScheduledTaskAction -Execute "powershell.exe" ` - -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$showTrayScript`"" -$showTrayTrigger = New-ScheduledTaskTrigger -AtLogOn - -Register-Task -TaskName "ShowAllTrayIcons" ` - -Description "Show all system tray icons for current user" ` - -Action $showTrayAction ` - -Triggers $showTrayTrigger - -# ----------------------------------------------------------------------- -# Task: PDF-DefaultApp -# Runs on every logon, restores .pdf -> Adobe Reader association -# Guards against Edge overwriting it -# ----------------------------------------------------------------------- -Write-Log "Registering task: PDF-DefaultApp" -Level STEP - -$pdfScript = "$ScriptDir\PDF-DefaultApp.ps1" -@' -# Restore .pdf -> Adobe Reader HKCR association (system-wide). -# Runs as SYSTEM so it can write to HKCR regardless of Edge updates. -# Note: HKCU UserChoice requires Windows Hash validation and cannot be -# set reliably via registry; HKCR provides the system-wide fallback. -$acroPaths = @( - "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe" - "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe" - "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" - "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" - "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe" -) -$acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1 -if (-not $acroExe) { exit 0 } - -$progId = "AcroExch.Document.DC" -$openCmd = "`"$acroExe`" `"%1`"" - -# HKCR\.pdf -if (-not (Test-Path "HKCR:\.pdf")) { New-Item -Path "HKCR:\.pdf" -Force | Out-Null } -$current = (Get-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -ErrorAction SilentlyContinue)."(Default)" -if ($current -ne $progId) { - Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId -Force -} - -# HKCR\AcroExch.Document.DC\shell\open\command -$cmdPath = "HKCR:\$progId\shell\open\command" -if (-not (Test-Path $cmdPath)) { New-Item -Path $cmdPath -Force | Out-Null } -Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd -Force -'@ | Set-Content -Path $pdfScript -Encoding UTF8 -Force - -$pdfAction = New-ScheduledTaskAction -Execute "powershell.exe" ` - -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$pdfScript`"" -$pdfTrigger = New-ScheduledTaskTrigger -AtLogOn - -# Runs as SYSTEM to allow HKCR writes (system-wide file association) -$pdfPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest -$pdfSettings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2) ` - -MultipleInstances IgnoreNew ` - -StartWhenAvailable -$pdfTask = New-ScheduledTask -Action $pdfAction ` - -Trigger $pdfTrigger ` - -Settings $pdfSettings ` - -Principal $pdfPrincipal ` - -Description "Restore Adobe Reader as default PDF app on logon" -try { - Unregister-ScheduledTask -TaskName "PDF-DefaultApp" -Confirm:$false -ErrorAction SilentlyContinue - Register-ScheduledTask -TaskName "PDF-DefaultApp" -InputObject $pdfTask -Force | Out-Null - Write-Log " Registered task: PDF-DefaultApp" -Level OK -} -catch { - Write-Log " Failed to register task PDF-DefaultApp - $_" -Level ERROR -} - -# ----------------------------------------------------------------------- -# Task: UnlockStartLayout -# Runs once after deployment to unlock the Start menu layout -# so users can still customize it later -# ----------------------------------------------------------------------- -Write-Log "Registering task: UnlockStartLayout" -Level STEP - -$unlockScript = "$ScriptDir\UnlockStartLayout.ps1" -@' -# Remove Start layout lock so users can modify it -$layoutXml = "C:\Users\Default\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml" -if (Test-Path $layoutXml) { - Remove-Item $layoutXml -Force -ErrorAction SilentlyContinue -} - -# Unregister self after running once -Unregister-ScheduledTask -TaskName "UnlockStartLayout" -Confirm:$false -ErrorAction SilentlyContinue -'@ | Set-Content -Path $unlockScript -Encoding UTF8 -Force - -$unlockAction = New-ScheduledTaskAction -Execute "powershell.exe" ` - -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$unlockScript`"" -# Trigger: 5 minutes after system startup, once -$unlockTrigger = New-ScheduledTaskTrigger -AtStartup -$unlockTrigger.Delay = "PT5M" - -$unlockPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest -$unlockSettings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 10) ` - -StartWhenAvailable -$unlockTask = New-ScheduledTask -Action $unlockAction ` - -Trigger $unlockTrigger ` - -Settings $unlockSettings ` - -Principal $unlockPrincipal ` - -Description "Unlock Start menu layout 5 min after first boot" - -try { - Unregister-ScheduledTask -TaskName "UnlockStartLayout" -Confirm:$false -ErrorAction SilentlyContinue - Register-ScheduledTask -TaskName "UnlockStartLayout" -InputObject $unlockTask -Force | Out-Null - Write-Log " Registered task: UnlockStartLayout" -Level OK -} -catch { - Write-Log " Failed to register task UnlockStartLayout - $_" -Level ERROR -} - -Write-Log "Step 6 complete" -Level OK diff --git a/flash/scripts/07-desktop-info.ps1 b/flash/scripts/07-desktop-info.ps1 deleted file mode 100644 index 84f2e7f..0000000 --- a/flash/scripts/07-desktop-info.ps1 +++ /dev/null @@ -1,235 +0,0 @@ -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 -} - -$ScriptDir = "C:\Windows\Setup\Scripts" -$RenderScript = "$ScriptDir\DesktopInfo-Render.ps1" -$BmpPath = "$ScriptDir\desktopinfo.bmp" - -if (-not (Test-Path $ScriptDir)) { - New-Item -ItemType Directory -Path $ScriptDir -Force | Out-Null -} - -# ----------------------------------------------------------------------- -# Write the rendering script (runs on every logon as the user) -# Layout: hostname (large bold, centered), then detail lines centered -# ----------------------------------------------------------------------- -Write-Log "Writing DesktopInfo render script to $RenderScript" -Level INFO - -$renderContent = @' -# DesktopInfo-Render.ps1 -# Collects system info and renders it centered on the desktop wallpaper. -# Runs on every user logon via Scheduled Task. - -$ErrorActionPreference = "Continue" -$LogFile = "C:\Windows\Setup\Scripts\desktopinfo.log" -function Write-Log { - param([string]$Message, [string]$Level = "INFO") - Add-Content -Path $LogFile -Value "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message" -Encoding UTF8 -} -Write-Log "DesktopInfo render started" -Level INFO - -Add-Type -AssemblyName System.Drawing -Add-Type -AssemblyName System.Windows.Forms -Add-Type -TypeDefinition @" -using System; -using System.Runtime.InteropServices; -public class WallpaperApi { - [DllImport("user32.dll", CharSet=CharSet.Auto)] - public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni); -} -"@ -ErrorAction SilentlyContinue - -# ----------------------------------------------------------------------- -# Collect system info -# ----------------------------------------------------------------------- -Write-Log "Collecting system info" -$hostname = $env:COMPUTERNAME -$userDomain = $env:USERDOMAIN -$userName = $env:USERNAME -$loggedUser = if ($userDomain -and $userDomain -ne $hostname) { "$userDomain\$userName" } else { "$hostname\$userName" } - -$osInfo = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue -$osName = if ($osInfo) { $osInfo.Caption -replace "^Microsoft\s*", "" } else { "Windows" } -$ramGB = if ($osInfo) { [math]::Round($osInfo.TotalVisibleMemorySize / 1024 / 1024, 1) } else { "?" } - -$cpuInfo = Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue | Select-Object -First 1 -$cpuCount = if ($cpuInfo) { $cpuInfo.NumberOfLogicalProcessors } else { "?" } -$cpuSpeed = if ($cpuInfo) { $cpuInfo.MaxClockSpeed } else { "?" } - -$ips = (Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue | - Where-Object { $_.IPAddress -ne "127.0.0.1" -and $_.PrefixOrigin -ne "WellKnown" } | - Select-Object -ExpandProperty IPAddress) -join ", " -if (-not $ips) { $ips = "N/A" } - -$csInfo = Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue -$domain = if ($csInfo -and $csInfo.PartOfDomain) { $csInfo.Domain } ` - elseif ($csInfo -and $csInfo.Workgroup) { $csInfo.Workgroup.ToLower() } ` - else { "N/A" } - -Write-Log "hostname=$hostname user=$loggedUser os=$osName ram=$($ramGB)GB cpu=${cpuCount}x${cpuSpeed}MHz ips=$ips domain=$domain" - -# ----------------------------------------------------------------------- -# Screen dimensions -# ----------------------------------------------------------------------- -$screen = [System.Windows.Forms.Screen]::PrimaryScreen -$width = if ($screen) { $screen.Bounds.Width } else { 1920 } -$height = if ($screen) { $screen.Bounds.Height } else { 1080 } -Write-Log "screen=${width}x${height}" - -# ----------------------------------------------------------------------- -# Create bitmap and graphics context -# ----------------------------------------------------------------------- -$bmp = New-Object System.Drawing.Bitmap($width, $height) -$g = [System.Drawing.Graphics]::FromImage($bmp) -$g.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAlias -$g.Clear([System.Drawing.ColorTranslator]::FromHtml("#556364")) - -# ----------------------------------------------------------------------- -# Fonts and brushes -# ----------------------------------------------------------------------- -$fontName = "Segoe UI" -$fontTitle = New-Object System.Drawing.Font($fontName, 36, [System.Drawing.FontStyle]::Bold) -$fontBold = New-Object System.Drawing.Font($fontName, 14, [System.Drawing.FontStyle]::Bold) -$fontReg = New-Object System.Drawing.Font($fontName, 14, [System.Drawing.FontStyle]::Regular) -$brushWhite = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White) -$brushGray = New-Object System.Drawing.SolidBrush([System.Drawing.ColorTranslator]::FromHtml("#C8D2D2")) - -# ----------------------------------------------------------------------- -# Lines: text, font, brush -# ----------------------------------------------------------------------- -$texts = @( - $hostname - "Logged on user: $loggedUser" - "OS: $osName" - "CPU: $cpuCount at $cpuSpeed MHz RAM: $($ramGB)GB" - "IPv4 address: $ips Machine domain: $domain" -) -$fonts = @( $fontTitle, $fontReg, $fontBold, $fontReg, $fontReg ) -$brushes = @( $brushWhite, $brushGray, $brushGray, $brushGray, $brushGray ) - -# ----------------------------------------------------------------------- -# Measure total block height, then center vertically -# ----------------------------------------------------------------------- -$lineSpacing = 8 -$heights = @() -for ($i = 0; $i -lt $texts.Count; $i++) { - $heights += [int]($g.MeasureString($texts[$i], $fonts[$i]).Height) -} -$totalH = ($heights | Measure-Object -Sum).Sum + $lineSpacing * ($texts.Count - 1) -$currentY = [int](($height - $totalH) / 2) - -# ----------------------------------------------------------------------- -# Draw each line centered horizontally -# ----------------------------------------------------------------------- -for ($i = 0; $i -lt $texts.Count; $i++) { - $sz = $g.MeasureString($texts[$i], $fonts[$i]) - $x = [int](($width - $sz.Width) / 2) - $g.DrawString($texts[$i], $fonts[$i], $brushes[$i], [float]$x, [float]$currentY) - $currentY += $heights[$i] + $lineSpacing -} - -$g.Dispose() - -# ----------------------------------------------------------------------- -# Save and set as wallpaper -# ----------------------------------------------------------------------- -$bmpPath = "C:\Windows\Setup\Scripts\desktopinfo.bmp" -Write-Log "Saving BMP: $bmpPath" -$bmp.Save($bmpPath, [System.Drawing.Imaging.ImageFormat]::Bmp) -$bmp.Dispose() - -# Clear Windows wallpaper cache so it reloads from our BMP -# Without this, Windows reuses TranscodedWallpaper and ignores the updated file -$transcodedPath = "$env:APPDATA\Microsoft\Windows\Themes\TranscodedWallpaper" -if (Test-Path $transcodedPath) { - Remove-Item $transcodedPath -Force -ErrorAction SilentlyContinue - Write-Log "Cleared TranscodedWallpaper cache" -} - -# SPI_SETDESKTOPWALLPAPER=20, SPIF_UPDATEINIFILE|SPIF_SENDCHANGE=3 -$result = [WallpaperApi]::SystemParametersInfo(20, 0, $bmpPath, 3) -Write-Log "SystemParametersInfo result: $result" -Write-Log "DesktopInfo render complete" -Level INFO -'@ - -$renderContent | Set-Content -Path $RenderScript -Encoding UTF8 -Force -Write-Log "Render script written" -Level OK - -# ----------------------------------------------------------------------- -# Store deployment date in registry (used for reference) -# ----------------------------------------------------------------------- -Write-Log "Storing deployment date in registry" -Level INFO -try { - if (-not (Test-Path "HKLM:\SOFTWARE\X9\Deployment")) { - New-Item -Path "HKLM:\SOFTWARE\X9\Deployment" -Force | Out-Null - } - $existingDate = (Get-ItemProperty -Path "HKLM:\SOFTWARE\X9\Deployment" ` - -Name "DeployDate" -ErrorAction SilentlyContinue).DeployDate - if (-not $existingDate) { - Set-ItemProperty -Path "HKLM:\SOFTWARE\X9\Deployment" ` - -Name "DeployDate" ` - -Value (Get-Date -Format "yyyy-MM-dd") ` - -Force - Write-Log " DeployDate set: $(Get-Date -Format 'yyyy-MM-dd')" -Level OK - } else { - Write-Log " DeployDate already set: $existingDate" -Level INFO - } -} -catch { - Write-Log " Failed to set DeployDate: $_" -Level ERROR -} - -# ----------------------------------------------------------------------- -# Register scheduled task: DesktopInfo -# Runs the render script on every user logon -# ----------------------------------------------------------------------- -Write-Log "Registering task: DesktopInfo" -Level STEP - -try { - Unregister-ScheduledTask -TaskName "DesktopInfo" -Confirm:$false -ErrorAction SilentlyContinue - - $action = New-ScheduledTaskAction -Execute "powershell.exe" ` - -Argument "-NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$RenderScript`"" - $trigger = New-ScheduledTaskTrigger -AtLogOn - $trigger.Delay = "PT20S" # wait for network to be available - $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 2) ` - -MultipleInstances IgnoreNew ` - -StartWhenAvailable - $principal = New-ScheduledTaskPrincipal -GroupId "Users" -RunLevel Limited - - $task = New-ScheduledTask -Action $action ` - -Trigger $trigger ` - -Settings $settings ` - -Principal $principal ` - -Description "Render system info onto desktop wallpaper on logon" - - Register-ScheduledTask -TaskName "DesktopInfo" -InputObject $task -Force | Out-Null - Write-Log "Task DesktopInfo registered" -Level OK -} -catch { - Write-Log "Failed to register DesktopInfo task: $_" -Level ERROR -} - -# ----------------------------------------------------------------------- -# Run once immediately for current user -# ----------------------------------------------------------------------- -Write-Log "Running DesktopInfo render now for current user" -Level INFO -try { - & powershell.exe -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File $RenderScript - Write-Log "DesktopInfo rendered" -Level OK -} -catch { - Write-Log "DesktopInfo render failed: $_" -Level WARN -} - -Write-Log "Step 7 complete" -Level OK diff --git a/flash/scripts/08-activation.ps1 b/flash/scripts/08-activation.ps1 deleted file mode 100644 index c3cbef3..0000000 --- a/flash/scripts/08-activation.ps1 +++ /dev/null @@ -1,109 +0,0 @@ -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 -} - -# ----------------------------------------------------------------------- -# KMS Generic Volume License Keys (GVLK) -# Source: https://docs.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys -# These are official Microsoft-published keys for use with KMS infrastructure. -# Replace with your MAK/retail key for standalone activation. -# ----------------------------------------------------------------------- -$KmsKeys = @{ - # Windows 11 - "Windows 11 Pro" = "W269N-WFGWX-YVC9B-4J6C9-T83GX" - "Windows 11 Pro N" = "MH37W-N47XK-V7XM9-C7227-GCQG9" - "Windows 11 Pro Education" = "6TP4R-GNPTD-KYYHQ-7B7DP-J447Y" - "Windows 11 Education" = "NW6C2-QMPVW-D7KKK-3GKT6-VCFB2" - "Windows 11 Enterprise" = "NPPR9-FWDCX-D2C8J-H872K-2YT43" - # Windows 10 - "Windows 10 Pro" = "W269N-WFGWX-YVC9B-4J6C9-T83GX" - "Windows 10 Pro N" = "MH37W-N47XK-V7XM9-C7227-GCQG9" - "Windows 10 Education" = "NW6C2-QMPVW-D7KKK-3GKT6-VCFB2" - "Windows 10 Enterprise" = "NPPR9-FWDCX-D2C8J-H872K-2YT43" - "Windows 10 Home" = "TX9XD-98N7V-6WMQ6-BX7FG-H8Q99" -} - -# ----------------------------------------------------------------------- -# Check current activation status -# ----------------------------------------------------------------------- -Write-Log "Checking Windows activation status" -Level INFO - -$licenseStatus = (Get-CimInstance SoftwareLicensingProduct -Filter "PartialProductKey IS NOT NULL AND Name LIKE 'Windows%'" -ErrorAction SilentlyContinue | - Select-Object -First 1).LicenseStatus -# LicenseStatus: 0=Unlicensed, 1=Licensed, 2=OOBGrace, 3=OOTGrace, 4=NonGenuineGrace, 5=Notification, 6=ExtendedGrace - -if ($licenseStatus -eq 1) { - Write-Log " Windows is already activated - skipping" -Level OK -} else { - Write-Log " Activation status: $licenseStatus (not activated)" -Level WARN - - # Detect Windows edition - $osCaption = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).Caption - Write-Log " Detected OS: $osCaption" -Level INFO - - # Check if a key is configured in config - $customKey = $null - if ($Config -and $Config.activation -and $Config.activation.productKey) { - $customKey = $Config.activation.productKey - } - - if ($customKey -and $customKey -ne "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX") { - # Use key from config - $keyToUse = $customKey - Write-Log " Using product key from config" -Level INFO - } else { - # Find matching GVLK key by OS name - $keyToUse = $null - foreach ($entry in $KmsKeys.GetEnumerator()) { - if ($osCaption -like "*$($entry.Key)*") { - $keyToUse = $entry.Value - Write-Log " Matched GVLK key for: $($entry.Key)" -Level INFO - break - } - } - } - - if (-not $keyToUse) { - Write-Log " No matching key found for: $osCaption" -Level WARN - Write-Log " Skipping activation - set activation.productKey in config.json" -Level WARN - } else { - # Install key - Write-Log " Installing product key..." -Level INFO - $ipkResult = & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /ipk $keyToUse 2>&1 - if ($LASTEXITCODE -eq 0) { - Write-Log " Key installed" -Level OK - } else { - Write-Log " Key install result: $ipkResult" -Level WARN - } - - # Set KMS server if configured - if ($Config -and $Config.activation -and $Config.activation.kmsServer) { - $kmsServer = $Config.activation.kmsServer - Write-Log " Setting KMS server: $kmsServer" -Level INFO - & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /skms $kmsServer 2>&1 | Out-Null - } - - # Attempt activation - Write-Log " Attempting activation..." -Level INFO - $atoResult = & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /ato 2>&1 - $atoOutput = $atoResult -join " " - - if ($atoOutput -match "successfully" -or $atoOutput -match "uspesn") { - Write-Log " Activation successful" -Level OK - } else { - Write-Log " Activation result: $atoOutput" -Level WARN - Write-Log " Activation may require a KMS server or valid MAK key" -Level WARN - } - } -} - -Write-Log "Step 8 - Activation complete" -Level OK