diff --git a/scripts/02-software.ps1 b/scripts/02-software.ps1
index 4dd45d5..7fa150c 100644
--- a/scripts/02-software.ps1
+++ b/scripts/02-software.ps1
@@ -14,7 +14,7 @@
7-zip-7zip-7zip: Installs 7-Zip (winget ID: 7zip.7zip). Used for archive management. Silent install with --accept-package-agreements --accept-source-agreements flags required for unattended deployment.
adobe-acrobat-reader-64-bit-adobe-acroba: Installs Adobe Acrobat Reader DC 64-bit (Adobe.Acrobat.Reader.64-bit). Required as the default PDF viewer to prevent Edge from handling PDFs in browser mode, which limits functionality.
openvpn-connect-openvpntechnologies-open: Installs OpenVPN Connect client. Used for client VPN access when the client network requires a VPN. The ovpn profile and credentials are configured separately per client.
- atera-agent-install: Atera RMM agent downloaded from x9.servicedesk.atera.com and installed via msiexec /qb. During install, Atera MSI shows an interactive MFA window - technician enters the code to complete registration. Agent enables MSP monitoring, remote access, and ticketing integration.
+ atera-agent-install: Atera RMM agent downloaded from x9.servicedesk.atera.com and installed under NT AUTHORITY\SYSTEM via a one-shot scheduled task (msiexec /qn). Running as SYSTEM registers the agent silently with no interactive MFA window, so no technician input is needed. Agent enables MSP monitoring, remote access, and ticketing integration.
adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install via HKCR (system-wide, no UserChoice hash issue). UCPD driver is stopped immediately before the write and restarted after to ensure the association persists across Edge updates.
ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) is stopped before the PDF association write and restarted after. Pattern: Stop-Service ucpd -> set HKCR\.pdf -> Start-Service ucpd. Implemented in this script.
#>
@@ -208,27 +208,48 @@ if (Get-Feature $Config "software" "pdfDefault") {
# -----------------------------------------------------------------------
# Install Atera RMM Agent
-# Download MSI from Atera dashboard API, install via msiexec /qb.
-# During install, the Atera MSI shows an interactive MFA window -
-# the technician enters the code to complete agent registration.
+# Download the MSI from the Atera dashboard API, then install it under the
+# SYSTEM account via a one-shot scheduled task. Under SYSTEM the Atera
+# installer registers silently and does NOT show the interactive MFA window
+# that appears when installing in a user context - so no technician input
+# is needed.
# -----------------------------------------------------------------------
if (Get-Feature $Config "software" "ateraAgent") {
- Write-Log "Installing Atera RMM Agent" -Level INFO
+ Write-Log "Installing Atera RMM Agent (under SYSTEM)" -Level INFO
- $ateraMsi = "$env:TEMP\AteraAgent.msi"
- $ateraUrl = "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337"
+ # Machine-wide temp dir readable by SYSTEM (a per-user TEMP may not be)
+ $ateraMsi = "$env:WINDIR\Temp\AteraAgent.msi"
+ $ateraUrl = "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337"
+ $ateraTask = "X9-AteraInstall"
try {
Write-Log " Downloading Atera MSI..." -Level INFO
Invoke-WebRequest -Uri $ateraUrl -OutFile $ateraMsi -UseBasicParsing -ErrorAction Stop
Write-Log " Download complete" -Level OK
- Write-Log " Running installer (MFA window will appear)..." -Level INFO
- $msiProc = Start-Process msiexec -ArgumentList "/i `"$ateraMsi`" /qb" -Wait -PassThru
- if ($msiProc.ExitCode -eq 0) {
- Write-Log " Atera agent installed (msiexec exit 0)" -Level OK
+ # Run msiexec as NT AUTHORITY\SYSTEM via a temporary scheduled task.
+ # SYSTEM runs in non-interactive session 0, hence /qn (no UI) and no MFA.
+ Write-Log " Installing as SYSTEM via scheduled task (no MFA)..." -Level INFO
+ $action = New-ScheduledTaskAction -Execute "msiexec.exe" -Argument "/i `"$ateraMsi`" /qn /norestart"
+ $principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
+ $stTask = New-ScheduledTask -Action $action -Principal $principal
+ Register-ScheduledTask -TaskName $ateraTask -InputObject $stTask -Force | Out-Null
+ Start-ScheduledTask -TaskName $ateraTask
+
+ # Wait for the task to finish (msiexec install can take a few minutes)
+ $deadline = (Get-Date).AddMinutes(10)
+ do {
+ Start-Sleep -Seconds 3
+ $state = (Get-ScheduledTask -TaskName $ateraTask -ErrorAction SilentlyContinue).State
+ } while ($state -eq "Running" -and (Get-Date) -lt $deadline)
+
+ $result = (Get-ScheduledTaskInfo -TaskName $ateraTask -ErrorAction SilentlyContinue).LastTaskResult
+ if ($state -eq "Running") {
+ Write-Log " Atera install timed out after 10 min" -Level WARN
+ } elseif ($result -eq 0) {
+ Write-Log " Atera installer finished (SYSTEM, exit 0)" -Level OK
} else {
- Write-Log " Atera agent install exit code: $($msiProc.ExitCode)" -Level WARN
+ Write-Log " Atera installer exit code: $result" -Level WARN
}
# Verify install. The AteraAgent service is the most reliable signal -
@@ -255,6 +276,7 @@ if (Get-Feature $Config "software" "ateraAgent") {
Write-Log " Atera agent install failed: $_" -Level ERROR
}
finally {
+ Unregister-ScheduledTask -TaskName $ateraTask -Confirm:$false -ErrorAction SilentlyContinue
Remove-Item $ateraMsi -ErrorAction SilentlyContinue
}
} else {
diff --git a/scripts/04-default-profile.ps1 b/scripts/04-default-profile.ps1
index 6cf8ea2..4f214ef 100644
--- a/scripts/04-default-profile.ps1
+++ b/scripts/04-default-profile.ps1
@@ -176,15 +176,11 @@ try {
$wsh = New-Object -ComObject WScript.Shell
$defRoaming = "C:\Users\Default\AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
- $explorerLnkDir = "$defRoaming\System Tools"
- $explorerLnk = "$explorerLnkDir\File Explorer.lnk"
- if (-not (Test-Path $explorerLnk)) {
- if (-not (Test-Path $explorerLnkDir)) { New-Item -ItemType Directory -Path $explorerLnkDir -Force | Out-Null }
- $sc = $wsh.CreateShortcut($explorerLnk)
- $sc.TargetPath = "$env:WINDIR\explorer.exe"
- $sc.Save()
- Write-Log " Created File Explorer.lnk in Default profile Start Menu" -Level OK
- }
+ # File Explorer is pinned via its AppUserModelID (see pin list below),
+ # not a custom .lnk. A hand-made shortcut to explorer.exe pins as a
+ # separate app: clicking it launches a second Explorer that does not
+ # group with the running window, and the icon cannot be unpinned
+ # normally. The AUMID pin behaves like the built-in Explorer button.
if ($ProfileType -eq "admin") {
$psLnkDir = "$defRoaming\Windows PowerShell"
@@ -206,14 +202,14 @@ try {
$pinList = switch ($ProfileType) {
"admin" {
@'
-
+
'@
}
default {
@'
-
+
'@
}