From d94ef876581155a9e11c63757d28d66a0a54605d Mon Sep 17 00:00:00 2001 From: CristianD Date: Mon, 24 Aug 2026 15:21:00 +0100 Subject: [PATCH] Update 8x8_Work_Updater.ps1 --- 8x8_Work_Updater.ps1 | 169 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 142 insertions(+), 27 deletions(-) diff --git a/8x8_Work_Updater.ps1 b/8x8_Work_Updater.ps1 index 6ece69b..1dba053 100644 --- a/8x8_Work_Updater.ps1 +++ b/8x8_Work_Updater.ps1 @@ -1,8 +1,8 @@ # ============================================================================== # Script Name: 8x8_Work_Updater.ps1 -# Description: Downloads 8x8 with a progress bar, triggers a native service -# notification modal dialog on the user screen (bypasses non-interactive -# Session 0 blocks), silently installs, and relaunches 8x8. +# Description: Self-contained updater script runnable directly from console. +# Downloads PsExec + 8x8, pops up the live countdown GUI on the +# active user's desktop, silently updates, and relaunches 8x8. # ============================================================================== # Ensure script is running elevated @@ -11,25 +11,40 @@ if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdenti exit 1 } -# Load required assemblies -Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Net.Http $workDir = "C:\ProgramData\JCT600_8x8Update" +$flagFile = Join-Path $workDir "8x8_Update_Proceed.flag" +$guiScript = Join-Path $workDir "Show-8x8UserGui.ps1" +$psexecPath = Join-Path $workDir "PsExec.exe" $installerPath = Join-Path $workDir "8x8_Work_Installer.msi" if (-not (Test-Path $workDir)) { New-Item -Path $workDir -ItemType Directory -Force | Out-Null } +# Ensure standard user has full read/write access to folder and signal flags +$acl = Get-Acl $workDir +$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Users", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") +$acl.AddAccessRule($rule) +Set-Acl $workDir $acl + +if (Test-Path $flagFile) { Remove-Item $flagFile -Force } + try { # -------------------------------------------------------------------------- - # Step 1: Download 8x8 Installer with Stream Progress Bar + # Step 1: Download 8x8 Setup Installer with Console Progress Bar & PsExec # -------------------------------------------------------------------------- $installerUrl = "https://work-desktop-assets.8x8.com/prod-publish/ga/work-64-msi-v8.35.2-6.msi" - Write-Host "[1/4] Downloading 8x8 Work installer..." -ForegroundColor Cyan + $psexecUrl = "https://live.sysinternals.com/PsExec.exe" + + Write-Host "[1/4] Downloading 8x8 Work installer and helper tools..." -ForegroundColor Cyan try { + # Download PsExec directly from Microsoft Sysinternals + Invoke-WebRequest -Uri $psexecUrl -OutFile $psexecPath -UseBasicParsing + + # Download 8x8 Installer with Stream Progress Bar $httpClient = New-Object System.Net.Http.HttpClient $response = $httpClient.GetAsync($installerUrl, [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead).Result if (-not $response.IsSuccessStatusCode) { throw "HTTP Error $($response.StatusCode)" } @@ -58,30 +73,127 @@ try { $outputStream.Close(); $inputStream.Close(); $httpClient.Dispose() Write-Host "`nDownload complete: $installerPath" -ForegroundColor Green } catch { - Write-Error "`nFailed to download installer. Error: $_" + Write-Error "`nFailed to download installer or tools. Error: $_" exit 1 } # -------------------------------------------------------------------------- - # Step 2: Show ServiceNotification Dialog (Crosses Session 0 Isolation) + # Step 2: Generate User-Session GUI Script (BOM-Free UTF-8) # -------------------------------------------------------------------------- - Write-Host "[2/4] Displaying interactive notification on user desktop..." -ForegroundColor Cyan + Write-Host "[2/4] Generating countdown dialog for active desktop..." -ForegroundColor Cyan - $title = "JCT600 IT Support — 8x8 Work Update" - $message = "An automatic update for 8x8 Work has been scheduled by IT Support.`n`nPlease save active work and wrap up ongoing calls.`n`nClick OK to proceed with the update." + $guiContent = @' +Add-Type -AssemblyName System.Windows.Forms +Add-Type -AssemblyName System.Drawing - # Use ServiceNotification flag to display onto the interactive desktop - [System.Windows.Forms.MessageBox]::Show( - $message, - $title, - [System.Windows.Forms.MessageBoxButtons]::OK, - [System.Windows.Forms.MessageBoxIcon]::Information, - [System.Windows.Forms.MessageBoxDefaultButton]::Button1, - [System.Windows.Forms.MessageBoxOptions]::ServiceNotification - ) | Out-Null +$flagPath = "C:\ProgramData\JCT600_8x8Update\8x8_Update_Proceed.flag" + +$form = New-Object System.Windows.Forms.Form +$form.Text = "JCT600 IT Support — 8x8 Work Update" +$form.Size = New-Object System.Drawing.Size(460, 260) +$form.StartPosition = 'CenterScreen' +$form.FormBorderStyle = 'FixedDialog' +$form.MaximizeBox = $false +$form.MinimizeBox = $false +$form.ControlBox = $false +$form.TopMost = $true + +$script:allowClose = $false +$form.Add_FormClosing({ + param($sender, $e) + if (-not $script:allowClose) { $e.Cancel = $true } +}) + +$labelHeader = New-Object System.Windows.Forms.Label +$labelHeader.Text = "JCT600 — IT SUPPORT" +$labelHeader.Location = New-Object System.Drawing.Point(20, 15) +$labelHeader.Size = New-Object System.Drawing.Size(400, 25) +$labelHeader.Font = New-Object System.Drawing.Font("Segoe UI", 12, [System.Drawing.FontStyle]::Bold) +$labelHeader.ForeColor = [System.Drawing.Color]::Navy +$labelHeader.TextAlign = 'TopCenter' +$form.Controls.Add($labelHeader) + +$labelMsg = New-Object System.Windows.Forms.Label +$labelMsg.Text = "An automatic update for 8x8 Work has been scheduled by IT Support.`nPlease save active work or click 'Update Now' to proceed." +$labelMsg.Location = New-Object System.Drawing.Point(20, 48) +$labelMsg.Size = New-Object System.Drawing.Size(400, 40) +$labelMsg.Font = New-Object System.Drawing.Font("Segoe UI", 9) +$labelMsg.TextAlign = 'TopCenter' +$form.Controls.Add($labelMsg) + +$labelTimer = New-Object System.Windows.Forms.Label +$labelTimer.Location = New-Object System.Drawing.Point(20, 95) +$labelTimer.Size = New-Object System.Drawing.Size(400, 40) +$labelTimer.Font = New-Object System.Drawing.Font("Segoe UI", 20, [System.Drawing.FontStyle]::Bold) +$labelTimer.ForeColor = [System.Drawing.Color]::DarkRed +$labelTimer.TextAlign = 'MiddleCenter' +$form.Controls.Add($labelTimer) + +$btnUpdateNow = New-Object System.Windows.Forms.Button +$btnUpdateNow.Text = "Update Now" +$btnUpdateNow.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold) +$btnUpdateNow.Size = New-Object System.Drawing.Size(150, 40) +$btnUpdateNow.Location = New-Object System.Drawing.Point(145, 155) +$btnUpdateNow.UseVisualStyleBackColor = $true + +$timer = New-Object System.Windows.Forms.Timer +$timer.Interval = 1000 +$script:remaining = 3600 # 1 Hour + +$btnUpdateNow.Add_Click({ + $timer.Stop() + $script:allowClose = $true + New-Item -Path $flagPath -ItemType File -Force | Out-Null + $form.Close() +}) +$form.Controls.Add($btnUpdateNow) + +$timer.Add_Tick({ + if ($script:remaining -gt 0) { + $timeSpan = [TimeSpan]::FromSeconds($script:remaining) + $labelTimer.Text = $timeSpan.ToString("hh\:mm\:ss") + $script:remaining-- + } else { + $timer.Stop() + $script:allowClose = $true + New-Item -Path $flagPath -ItemType File -Force | Out-Null + $form.Close() + } +}) + +$initialSpan = [TimeSpan]::FromSeconds($script:remaining) +$labelTimer.Text = $initialSpan.ToString("hh\:mm\:ss") + +$timer.Start() +[System.Windows.Forms.Application]::Run($form) +'@ + + $utf8NoBom = New-Object System.Text.UTF8Encoding($false) + [System.IO.File]::WriteAllText($guiScript, $guiContent, $utf8NoBom) # -------------------------------------------------------------------------- - # Step 3: Close Running 8x8 Processes & Install Silently + # Step 3: Launch GUI Directly onto User's Screen & Wait + # -------------------------------------------------------------------------- + $explorerProc = Get-Process -Name explorer -ErrorAction SilentlyContinue | Select-Object -First 1 + + if (-not $explorerProc) { + Write-Warning "No active user desktop session detected. Proceeding directly to update." + } else { + $sessionId = $explorerProc.SessionId + Write-Host "Targeting Active Desktop Session ID: $sessionId" -ForegroundColor Green + + # Launch the GUI directly into the active user's physical screen via PsExec + $psExe = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" + & $psexecPath -accepteula -nobanner -i $sessionId -d $psExe -ExecutionPolicy Bypass -WindowStyle Hidden -File "$guiScript" + + Write-Host "Dialog displayed on screen. Waiting for user response or 1-hour expiration..." -ForegroundColor Yellow + while (-not (Test-Path $flagFile)) { + Start-Sleep -Seconds 2 + } + } + + # -------------------------------------------------------------------------- + # Step 4: Stop 8x8, Silently Install & Relaunch # -------------------------------------------------------------------------- Write-Host "[3/4] Stopping 8x8 processes and installing silently..." -ForegroundColor Cyan @@ -107,9 +219,9 @@ try { Write-Host "Installation completed successfully." -ForegroundColor Green # -------------------------------------------------------------------------- - # Step 4: Launch 8x8 Work + # Step 5: Launch 8x8 Work # -------------------------------------------------------------------------- - Write-Host "[4/4] Launching 8x8 Work..." -ForegroundColor Cyan + Write-Host "[4/4] Launching updated 8x8 Work..." -ForegroundColor Cyan $possiblePaths = @( "${env:ProgramFiles}\8x8 Inc\8x8 Work\8x8 Work.exe", @@ -121,9 +233,12 @@ try { $exePath = $possiblePaths | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($exePath) { - # Using explorer.exe to launch the executable forces standard user graphics execution - Start-Process "explorer.exe" -ArgumentList "`"$exePath`"" - Write-Host "8x8 Work launched successfully." -ForegroundColor Green + if ($explorerProc) { + & $psexecPath -accepteula -nobanner -i $sessionId -d "$exePath" + Write-Host "8x8 Work launched successfully in user context." -ForegroundColor Green + } else { + Start-Process -FilePath $exePath + } } else { Write-Warning "Could not locate 8x8 Work executable." }