# === CONFIGURATION === $ScriptRoot = "$env:ProgramData\AteraAgentSetup" $UninstallScript = Join-Path $ScriptRoot "UninstallAtera.ps1" $InstallScript = Join-Path $ScriptRoot "InstallAtera.ps1" $UninstallLog = Join-Path $ScriptRoot "UninstallLog.txt" $InstallLog = Join-Path $ScriptRoot "InstallLog.txt" $MSIUrl = "https://XSTRA755464.servicedesk.atera.com/GetAgent/Windows/?cid=118&aid=001D0000025zs4jIAA" $UninstallTask = "Atera_Uninstall" $InstallTask = "Atera_Install" $UninstallTime = (Get-Date).AddMinutes(2) $InstallTime = (Get-Date).AddMinutes(10) # === HEADER === Write-Output "`n========== ATERA UNINSTALL + INSTALL SETUP ==========" Write-Output "Time started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" # === CREATE SCRIPT DIRECTORY IF NEEDED === if (-not (Test-Path $ScriptRoot)) { New-Item -ItemType Directory -Path $ScriptRoot -Force | Out-Null Write-Output "Created script directory: $ScriptRoot" } else { Write-Output "Script directory already exists: $ScriptRoot" } # === CLEANUP OLD SCRIPTS === foreach ($file in @($UninstallScript, $InstallScript, $UninstallLog, $InstallLog)) { if (Test-Path $file) { Remove-Item $file -Force -ErrorAction SilentlyContinue Write-Output "Deleted old file: $file" } } # === REMOVE OLD SCHEDULED TASKS IF THEY EXIST === foreach ($task in @($UninstallTask, $InstallTask)) { if (Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $task -Confirm:$false -ErrorAction SilentlyContinue Write-Output "Removed existing scheduled task: $task" } } # === WRITE UNINSTALL SCRIPT === $UninstallScriptContent = @' $UninstallLog = "$env:ProgramData\AteraAgentSetup\UninstallLog.txt" try { function Remove-Atera { Write-Output "`n===== Starting Atera + Splashtop Cleanup =====" # Check for Atera Agent service $ateraService = Get-Service -Name "AteraAgent" -ErrorAction SilentlyContinue if (-not $ateraService) { Write-Output "Atera Agent service not detected. Will attempt to clean up any old agent install files anyway." } else { Write-Output "Atera Agent service found. Proceeding with removal..." } # Helper: Get uninstall codes from registry function Get-UninstallCodes ([string]$DisplayName) { 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' | ForEach-Object { Get-ChildItem -Path $_ -ErrorAction SilentlyContinue | ForEach-Object { if ((Get-ItemProperty -Path $_.PSPath -ErrorAction SilentlyContinue).DisplayName -eq $DisplayName) { $str = (Get-ItemPropertyValue -Path $_.PSPath -Name 'UninstallString') if ($str.Length -ge 37) { $UninstallCodes.Add($str.Substring(($str.Length - 37), 36)) | Out-Null } } } } } # Helper: Get MSI product keys function Get-ProductKeys ([string]$ProductName) { Get-ChildItem -Path 'HKCR:Installer\Products' -ErrorAction SilentlyContinue | ForEach-Object { if ((Get-ItemProperty -Path $_.PSPath -ErrorAction SilentlyContinue).ProductName -eq $ProductName) { $ProductKeys.Add($_.PSPath.Substring($_.PSPath.Length - 32)) | Out-Null } } } function Get-ServiceStatus ([string]$Name) { (Get-Service -Name $Name -ErrorAction SilentlyContinue).Status } function Stop-RunningService ([string]$Name) { if ((Get-ServiceStatus -Name $Name) -eq "Running") { Write-Output "Stopping service: $Name" Stop-Service -Name $Name -Force -ErrorAction SilentlyContinue } } function Remove-StoppedService ([string]$Name) { $status = Get-ServiceStatus -Name $Name if ($status -eq "Stopped") { Write-Output "Deleting service: $Name" sc.exe delete "$Name" | Out-Null } elseif (-not $status) { Write-Output "Service not found: $Name" } } function Stop-RunningProcess ([string]$Name) { $p = Get-Process -Name $Name -ErrorAction SilentlyContinue if ($p) { Write-Output "Stopping process: $Name.exe" $p | Stop-Process -Force } } function Remove-Path ([string]$Path) { if (Test-Path $Path) { Write-Output "Deleting path: $Path" Remove-Item $Path -Recurse -Force -ErrorAction SilentlyContinue } } function Get-AllExeFiles ([string]$Path) { if (Test-Path $Path) { Get-ChildItem -Path $Path -Filter *.exe -Recurse | ForEach-Object { $ExeFiles.Add($_.BaseName) | Out-Null } } } # Mount registry hive for HKCR if not already mounted if (-not (Get-PSDrive -Name HKCR -ErrorAction SilentlyContinue)) { New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null } # Initialize lists $UninstallCodes = New-Object System.Collections.ArrayList $ProductKeys = New-Object System.Collections.ArrayList $ExeFiles = New-Object System.Collections.ArrayList # Collect uninstall and product keys 'AteraAgent', 'Splashtop for RMM', 'Splashtop Streamer' | ForEach-Object { Get-UninstallCodes -DisplayName $_ Get-ProductKeys -ProductName $_ } # Define services to remove $ServiceList = @('AteraAgent', 'SplashtopRemoteService', 'SSUService') # Define folders to delete $Directories = @( "${Env:ProgramFiles}\ATERA Networks", "${Env:ProgramFiles(x86)}\ATERA Networks", "${Env:ProgramFiles}\Splashtop\Splashtop Remote\Server", "${Env:ProgramFiles(x86)}\Splashtop\Splashtop Remote\Server", "${Env:ProgramFiles}\Splashtop\Splashtop Software Updater", "${Env:ProgramFiles(x86)}\Splashtop\Splashtop Software Updater", "${Env:ProgramData}\Splashtop\Splashtop Software Updater" ) # Define registry keys to clean $RegistryKeys = @( 'HKLM:SOFTWARE\ATERA Networks', 'HKLM:SOFTWARE\Splashtop Inc.', 'HKLM:SOFTWARE\WOW6432Node\Splashtop Inc.' ) # Collect running exe files from Atera "${Env:ProgramFiles}\ATERA Networks" | ForEach-Object { Get-AllExeFiles -Path $_ } # Uninstall MSI packages $UninstallCodes | ForEach-Object { Write-Output "Uninstalling MSI: $_" Start-Process "msiexec.exe" -ArgumentList @("/X{$($_.Trim())}", "/qn") -Wait } # Stop services $ServiceList | ForEach-Object { Stop-RunningService -Name $_ } # Stop processes $ExeFiles.Add('reg') | Out-Null $ExeFiles | ForEach-Object { Stop-RunningProcess $_ } # Delete services $ServiceList | ForEach-Object { Remove-StoppedService -Name $_ } # Remove product registry entries $ProductKeys | ForEach-Object { Remove-Path -Path "HKCR:Installer\Products\$_" } # Remove uninstall entries in case they linger 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' | ForEach-Object { Get-ChildItem -Path $_ -ErrorAction SilentlyContinue | ForEach-Object { $key = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue if ($key.DisplayName -and $key.DisplayName -match "Atera|Splashtop") { Write-Output "Removing lingering uninstall entry: $($key.DisplayName)" Remove-Item -Path $_.PSPath -Recurse -Force -ErrorAction SilentlyContinue } } } # Remove leftover registry keys $RegistryKeys | ForEach-Object { Remove-Path -Path $_ } # Remove install folders $Directories | ForEach-Object { Remove-Path -Path $_ } # Remove Atera scheduled tasks (but preserve install task) Get-ScheduledTask | Where-Object { $_.TaskName -like "*Atera*" -and $_.TaskName -ne "Atera_Install" } | ForEach-Object { Write-Output "Removing scheduled task: $($_.TaskName)" Unregister-ScheduledTask -TaskName $_.TaskName -Confirm:$false -ErrorAction SilentlyContinue } # Unmount HKCR drive if we created it if ((Get-PSDrive -Name HKCR -ErrorAction SilentlyContinue)) { Remove-PSDrive -Name HKCR -Force -ErrorAction SilentlyContinue } Write-Output "Atera and Splashtop removal complete." } "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting Atera uninstall" | Out-File $UninstallLog -Append Remove-Atera | Tee-Object -FilePath $UninstallLog -Append "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Atera uninstall completed" | Out-File $UninstallLog -Append Write-Output "Deleting uninstall script after execution: $($MyInvocation.MyCommand.Path)" Remove-Item "$($MyInvocation.MyCommand.Path)" -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 10 Restart-Computer -Force } catch { "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ERROR: $($_.Exception.Message)" | Out-File $UninstallLog -Append Write-Output "Error occurred during uninstall: $($_.Exception.Message)" } '@ Set-Content -Path $UninstallScript -Value $UninstallScriptContent -Encoding UTF8 Write-Output "Wrote uninstall script: $UninstallScript" # === WRITE INSTALL SCRIPT === $InstallScriptContent = @" `$InstallLog = "`$env:ProgramData\AteraAgentSetup\InstallLog.txt" try { "`$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting Atera install" | Out-File `$InstallLog -Append `$msiPath = "`$env:TEMP\AteraAgent.msi" Write-Output "Downloading Atera Agent MSI..." Invoke-WebRequest -Uri "$MSIUrl" -OutFile `$msiPath -UseBasicParsing if (-not (Test-Path `$msiPath)) { throw "Failed to download MSI file" } Write-Output "Installing Atera Agent..." `$installProcess = Start-Process "msiexec.exe" -ArgumentList @("/i", "`$msiPath", "/qn", "/l*v", "`$env:TEMP\AteraInstall.log") -Wait -PassThru if (`$installProcess.ExitCode -eq 0) { Write-Output "Atera Agent installed successfully." | Tee-Object -FilePath `$InstallLog -Append } else { throw "MSI installation failed with exit code: `$(`$installProcess.ExitCode)" } # Clean up downloaded MSI Remove-Item `$msiPath -Force -ErrorAction SilentlyContinue "`$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Atera install completed successfully" | Out-File `$InstallLog -Append Write-Output "Removing install scheduled task..." Unregister-ScheduledTask -TaskName "Atera_Install" -Confirm:`$false -ErrorAction SilentlyContinue Write-Output "Deleting install script after execution: `$(`$MyInvocation.MyCommand.Path)" Remove-Item "`$(`$MyInvocation.MyCommand.Path)" -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 10 Restart-Computer -Force } catch { "`$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ERROR: `$(`$_.Exception.Message)" | Out-File `$InstallLog -Append Write-Output "Error occurred during install: `$(`$_.Exception.Message)" # Clean up downloaded MSI on error if (Test-Path `$msiPath) { Remove-Item `$msiPath -Force -ErrorAction SilentlyContinue } } "@ Set-Content -Path $InstallScript -Value $InstallScriptContent -Encoding UTF8 Write-Output "Wrote install script: $InstallScript" # === REGISTER UNINSTALL TASK === $UninstallTrigger = New-ScheduledTaskTrigger -Once -At $UninstallTime $UninstallAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$UninstallScript`"" $Principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest $Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable Register-ScheduledTask -TaskName $UninstallTask -Trigger $UninstallTrigger -Action $UninstallAction -Principal $Principal -Settings $Settings -Force Write-Output "Created scheduled task: $UninstallTask to run at $($UninstallTime.ToString("HH:mm"))" # === REGISTER INSTALL TASK === $InstallTrigger = New-ScheduledTaskTrigger -Once -At $InstallTime $InstallAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$InstallScript`"" Register-ScheduledTask -TaskName $InstallTask -Trigger $InstallTrigger -Action $InstallAction -Principal $Principal -Settings $Settings -Force Write-Output "Created scheduled task: $InstallTask to run at $($InstallTime.ToString("HH:mm"))" Write-Output "`nSetup complete." Write-Output "Uninstall will run at: $($UninstallTime.ToString("yyyy-MM-dd HH:mm:ss"))" Write-Output "Install will run at: $($InstallTime.ToString("yyyy-MM-dd HH:mm:ss"))"