# ===================================================================== # Hobart Public Schools - New PC Setup Script # Run AFTER Windows 11 is booted and PC is domain-joined. # Usage (from .bat, same pattern as basics.txt): # powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://files.hobart.k12.ok.us/newpc.ps1 | iex" # ===================================================================== # ---- CONFIG: fill these in before deploying ---- $TechUserName = "Tech" $TechPassword = "1010" # <-- set this before running $WebRoot = "https://files.hobart.k12.ok.us/pcsetup" $LogPath = "C:\NewPCSetup_Log.txt" function Write-Log { param([string]$Message) $line = "[{0}] {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Message Write-Host $line try { Add-Content -Path $LogPath -Value $line -ErrorAction Stop } catch { # Can't write to log (e.g. not elevated yet) -- console output above still shows the message } } Write-Log "=== Starting New PC Setup ===" # Must be elevated $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Log "ERROR: Script must be run as Administrator. Exiting." exit 1 } # --------------------------------------------------------------------- # Resolve the actual logged-in user's SID for HKCU registry writes # (Running elevated maps HKCU to the Administrator profile, not the desktop user) # --------------------------------------------------------------------- Write-Log "Resolving logged-in user SID for registry targeting..." try { $loggedInUser = (Get-CimInstance -ClassName Win32_ComputerSystem).UserName if (-not $loggedInUser) { throw "Could not determine logged-in user from Win32_ComputerSystem." } $userSID = (New-Object System.Security.Principal.NTAccount($loggedInUser)).Translate([System.Security.Principal.SecurityIdentifier]).Value Write-Log "Logged-in user: $loggedInUser SID: $userSID" } catch { Write-Log "WARNING: Could not resolve logged-in user SID -- HKCU steps will fall back to current elevated context. Error: $($_.Exception.Message)" $userSID = $null } function Get-UserRegPath { param([string]$SubPath) if ($userSID) { return "Registry::HKEY_USERS\$userSID\$SubPath" } else { return "HKCU:\$SubPath" } } # --------------------------------------------------------------------- # 1) Run existing basics.txt provisioning script # --------------------------------------------------------------------- Write-Log "Step 1: Running basics.txt..." try { Invoke-Expression (Invoke-RestMethod "$WebRoot/basics.txt") Write-Log "Step 1: basics.txt completed." } catch { Write-Log "Step 1 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 2) Create local admin "Tech" backdoor account # --------------------------------------------------------------------- Write-Log "Step 2: Creating/verifying local admin account '$TechUserName'..." try { $securePw = ConvertTo-SecureString $TechPassword -AsPlainText -Force $existing = Get-LocalUser -Name $TechUserName -ErrorAction SilentlyContinue if (-not $existing) { New-LocalUser -Name $TechUserName -Password $securePw -PasswordNeverExpires -AccountNeverExpires -FullName "Tech Support" -Description "IT emergency/backdoor admin account" Add-LocalGroupMember -Group "Administrators" -Member $TechUserName Write-Log "Step 2: '$TechUserName' created and added to Administrators." } else { Write-Log "Step 2: '$TechUserName' already exists -- syncing password to current script value." Set-LocalUser -Name $TechUserName -Password $securePw -PasswordNeverExpires $true # Ensure account is still in Administrators in case it was ever removed $isAdmin = (Get-LocalGroupMember -Group "Administrators" -ErrorAction SilentlyContinue | Where-Object { $_.Name -like "*\$TechUserName" }) if (-not $isAdmin) { Add-LocalGroupMember -Group "Administrators" -Member $TechUserName Write-Log "Step 2: '$TechUserName' re-added to Administrators (was missing)." } Write-Log "Step 2: '$TechUserName' password synced." } } catch { Write-Log "Step 2 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 3) Desktop icon settings: Computer, User's Files, Recycle Bin, Control Panel # --------------------------------------------------------------------- Write-Log "Step 3: Enabling standard desktop icons..." try { $desktopIconsKey = Get-UserRegPath "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel" if (-not (Test-Path $desktopIconsKey)) { New-Item -Path $desktopIconsKey -Force | Out-Null } # 0 = show icon, 1 = hide icon Set-ItemProperty -Path $desktopIconsKey -Name "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -Value 0 -Type DWord # This PC Set-ItemProperty -Path $desktopIconsKey -Name "{59031a47-3f72-44a7-89c5-5595fe6b30ee}" -Value 0 -Type DWord # User's Files Set-ItemProperty -Path $desktopIconsKey -Name "{645FF040-5081-101B-9F08-00AA002F954E}" -Value 0 -Type DWord # Recycle Bin Set-ItemProperty -Path $desktopIconsKey -Name "{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}" -Value 0 -Type DWord # Control Panel # Refresh desktop icon visibility $advKey3 = Get-UserRegPath "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" Set-ItemProperty -Path $advKey3 -Name "HideIcons" -Value 0 -Type DWord -ErrorAction SilentlyContinue Write-Log "Step 3: Desktop icons enabled." } catch { Write-Log "Step 3 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 4) Disable Snap Windows (Multitasking Settings) # --------------------------------------------------------------------- Write-Log "Step 4: Disabling Snap Windows..." try { $advKey = Get-UserRegPath "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" Set-ItemProperty -Path $advKey -Name "EnableSnapAssistFlyout" -Value 0 -Type DWord -ErrorAction SilentlyContinue Set-ItemProperty -Path $advKey -Name "SnapAssist" -Value 0 -Type DWord -ErrorAction SilentlyContinue Set-ItemProperty -Path $advKey -Name "WindowArrangementActive" -Value 0 -Type DWord -ErrorAction SilentlyContinue Write-Log "Step 4: Snap Windows disabled." } catch { Write-Log "Step 4 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 5) Show known file extensions # --------------------------------------------------------------------- Write-Log "Step 5: Showing known file extensions..." try { $advKey5 = Get-UserRegPath "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" Set-ItemProperty -Path $advKey5 -Name "HideFileExt" -Value 0 -Type DWord Write-Log "Step 5: File extensions will now show." } catch { Write-Log "Step 5 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 6) Disable password expiration for the active user # --------------------------------------------------------------------- Write-Log "Step 6: Setting password to never expire for current user..." try { Set-LocalUser -Name $env:USERNAME -PasswordNeverExpires $true Write-Log "Step 6: PasswordNeverExpires set for $env:USERNAME." } catch { Write-Log "Step 6 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 7) Enable Mystify screensaver, 180 minute wait # --------------------------------------------------------------------- Write-Log "Step 7: Setting Mystify screensaver, 180 min timeout..." try { $desktopKey = Get-UserRegPath "Control Panel\Desktop" Set-ItemProperty -Path $desktopKey -Name "SCRNSAVE.EXE" -Value "C:\Windows\System32\mystify.scr" Set-ItemProperty -Path $desktopKey -Name "ScreenSaveActive" -Value "1" Set-ItemProperty -Path $desktopKey -Name "ScreenSaveTimeOut" -Value (180 * 60) # seconds Set-ItemProperty -Path $desktopKey -Name "ScreenSaverIsSecure" -Value "1" Write-Log "Step 7: Screensaver configured." } catch { Write-Log "Step 7 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 8) Power settings: display off 5 hrs, sleep never (AC + DC) # --------------------------------------------------------------------- Write-Log "Step 8: Configuring power settings..." try { # Display off after 5 hours = 300 minutes powercfg /change monitor-timeout-ac 300 powercfg /change monitor-timeout-dc 300 # Sleep never powercfg /change standby-timeout-ac 0 powercfg /change standby-timeout-dc 0 Write-Log "Step 8: Power settings applied (display 5hr, sleep never)." } catch { Write-Log "Step 8 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 9) Lower UAC to lowest "never notify" setting for active user # --------------------------------------------------------------------- Write-Log "Step 9: Lowering UAC to lowest setting..." try { $uacKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System" Set-ItemProperty -Path $uacKey -Name "ConsentPromptBehaviorAdmin" -Value 0 -Type DWord Set-ItemProperty -Path $uacKey -Name "PromptOnSecureDesktop" -Value 0 -Type DWord Write-Log "Step 9: UAC lowered to lowest setting (never notify)." } catch { Write-Log "Step 9 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 10) Set time zone to Central Time # --------------------------------------------------------------------- Write-Log "Step 10: Setting time zone to Central Time..." try { Set-TimeZone -Id "Central Standard Time" Write-Log "Step 10: Time zone set to Central Standard Time (handles CST/CDT automatically)." } catch { Write-Log "Step 10 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 11) Copy kbupdate script + runner bat to C:\ # --------------------------------------------------------------------- Write-Log "Step 11: Downloading kbupdate script and runner..." try { Invoke-WebRequest -Uri "$WebRoot/kbupdate.ps1" -OutFile "C:\kbupdate.ps1" -UseBasicParsing Invoke-WebRequest -Uri "$WebRoot/kbrun.bat" -OutFile "C:\kbrun.bat" -UseBasicParsing Write-Log "Step 11: kbupdate.ps1 and kbrun.bat copied to C:\. Run manually when ready." } catch { Write-Log "Step 11 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 12) Office 2024 install -- handled manually (drag from NAS), not automated # --------------------------------------------------------------------- # --------------------------------------------------------------------- # 13) Copy a.bat to C:\ # --------------------------------------------------------------------- Write-Log "Step 13: Downloading a.bat..." try { Invoke-WebRequest -Uri "$WebRoot/a.bat" -OutFile "C:\a.bat" -UseBasicParsing Write-Log "Step 13: a.bat copied to C:\." } catch { Write-Log "Step 13 ERROR: $($_.Exception.Message)" } # --------------------------------------------------------------------- # 14) Remove Edge / Copilot / Store from Desktop & Taskbar, remove OneDrive # --------------------------------------------------------------------- Write-Log "Step 14: Removing Edge/Copilot/Store shortcuts from taskbar and desktop..." try { # Remove desktop shortcuts if present $desktopPaths = @( "$env:PUBLIC\Desktop\Microsoft Edge.lnk", "$env:USERPROFILE\Desktop\Microsoft Edge.lnk" ) foreach ($p in $desktopPaths) { if (Test-Path $p) { Remove-Item $p -Force } } # Unpin from taskbar via registry (TaskbarLayout / LayoutModification approach is more reliable # for Win11 - this removes the default pinned layout entries for Edge, Copilot, Store) $unpinApps = @("Microsoft.MicrosoftEdge", "Microsoft.Windows.Copilot", "Microsoft.WindowsStore") # Disable Copilot via policy (cleanest method - removes icon and functionality) $copilotKey = Get-UserRegPath "Software\Policies\Microsoft\Windows\WindowsCopilot" if (-not (Test-Path $copilotKey)) { New-Item -Path $copilotKey -Force | Out-Null } Set-ItemProperty -Path $copilotKey -Name "TurnOffWindowsCopilot" -Value 1 -Type DWord Write-Log "Step 14: Edge desktop shortcut removed, Copilot disabled via policy." Write-Log "Step 14 NOTE: Taskbar unpinning and full Store removal often require additional steps -- see notes below script output." } catch { Write-Log "Step 14 ERROR: $($_.Exception.Message)" } Write-Log "Step 14: Removing OneDrive..." try { $onedrive = Get-Process "OneDrive" -ErrorAction SilentlyContinue if ($onedrive) { Stop-Process -Name "OneDrive" -Force } $installer = "$env:SystemRoot\SysWOW64\OneDriveSetup.exe" if (-not (Test-Path $installer)) { $installer = "$env:SystemRoot\System32\OneDriveSetup.exe" } if (Test-Path $installer) { Start-Process $installer "/uninstall" -Wait Write-Log "Step 14: OneDrive uninstalled." } else { Write-Log "Step 14: OneDriveSetup.exe not found -- may already be removed." } Write-Log "Step 14 NOTE: GPO 'Prevent the usage of OneDrive for file storage' must be enabled domain-wide to stop Windows Update from reinstalling it. This script only removes the current install." } catch { Write-Log "Step 14 ERROR (OneDrive): $($_.Exception.Message)" } Write-Log "Step 14: Applying local policy to block OneDrive from reinstalling/running..." try { # This is the same registry value gpedit.msc writes when you enable # Computer Configuration > Administrative Templates > Windows Components > OneDrive > # "Prevent the usage of OneDrive for file storage" -- set directly since there's no domain GPO. $oneDrivePolicyKey = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive" if (-not (Test-Path $oneDrivePolicyKey)) { New-Item -Path $oneDrivePolicyKey -Force | Out-Null } Set-ItemProperty -Path $oneDrivePolicyKey -Name "DisableFileSyncNGSC" -Value 1 -Type DWord Write-Log "Step 14: Local policy applied -- OneDrive blocked from file storage use/reinstall." } catch { Write-Log "Step 14 ERROR (OneDrive policy): $($_.Exception.Message)" } # --------------------------------------------------------------------- Write-Log "=== New PC Setup Complete ===" Write-Log "Reminder: kbupdate.ps1, Office2024 install, and a.bat were COPIED ONLY (Office handled manually) -- run them manually." Write-Log "A reboot/sign-out is recommended for all shell/explorer changes (icons, taskbar, screensaver) to fully apply." Write-Log "Log saved to $LogPath"