From 0407a2c4f3218c74de6331abc4274488263e1133 Mon Sep 17 00:00:00 2001 From: CristianD Date: Wed, 29 Jul 2026 17:20:37 +0100 Subject: [PATCH] Update 8x8_Work_Updater.ps1 --- 8x8_Work_Updater.ps1 | 198 ++++++------------------------------------- 1 file changed, 27 insertions(+), 171 deletions(-) diff --git a/8x8_Work_Updater.ps1 b/8x8_Work_Updater.ps1 index 20cbc58..487d483 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 console progress bar, launches interactive -# JCT600 GUI attached to user session via BUILTIN\Users, waits -# for response, silently installs, relaunches 8x8, and cleans up. +# Description: Downloads 8x8, pops up a native interactive alert directly into +# the active user session, waits for 1 hour or immediate click, +# silently installs, and relaunches 8x8. # ============================================================================== # Ensure script is running elevated @@ -11,48 +11,34 @@ if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdenti exit 1 } -# Load required .NET assemblies for Windows PowerShell 5.1 -Add-Type -AssemblyName System.Windows.Forms -Add-Type -AssemblyName System.Drawing Add-Type -AssemblyName System.Net.Http -# Use C:\ProgramData\ so standard users have full read/execute access $workDir = "C:\ProgramData\JCT600_8x8Update" -$flagFile = Join-Path $workDir "8x8_Update_Proceed.flag" -$guiScript = Join-Path $workDir "Show-8x8UserGui.ps1" +$installerPath = Join-Path $workDir "8x8_Work_Installer.msi" if (-not (Test-Path $workDir)) { New-Item -Path $workDir -ItemType Directory -Force | Out-Null } -if (Test-Path $flagFile) { Remove-Item $flagFile -Force } - try { # -------------------------------------------------------------------------- # Step 1: Download 8x8 Setup Installer with Console Progress Bar # -------------------------------------------------------------------------- - $installerUrl = "https://work-desktop-assets.8x8.com/prod-publish/ga/work-64-msi-v8.35.2-6.msi" - $installerPath = Join-Path $workDir "8x8_Work_Installer.msi" - - Write-Host "[1/5] Downloading 8x8 Work installer..." -ForegroundColor Cyan + $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 try { - # Initialize .NET HttpClient $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)" - } + if (-not $response.IsSuccessStatusCode) { throw "HTTP Error $($response.StatusCode)" } $totalBytes = $response.Content.Headers.ContentLength $inputStream = $response.Content.ReadAsStreamAsync().Result $outputStream = [System.IO.File]::Create($installerPath) $buffer = New-Object byte[] 8192 - $totalBytesRead = 0 - $bytesRead = 0 + $totalBytesRead = 0; $bytesRead = 0 - # Stream copy loop with progress indicator while (($bytesRead = $inputStream.Read($buffer, 0, $buffer.Length)) -gt 0) { $outputStream.Write($buffer, 0, $bytesRead) $totalBytesRead += $bytesRead @@ -61,8 +47,6 @@ try { $percent = [math]::Round(($totalBytesRead / $totalBytes) * 100) $downloadedMB = [math]::Round($totalBytesRead / 1MB, 2) $totalMB = [math]::Round($totalBytes / 1MB, 2) - - # Render ASCII progress bar $barLength = 30 $filledLength = [math]::Round(($percent / 100) * $barLength) $bar = ("█" * $filledLength) + ("░" * ($barLength - $filledLength)) @@ -70,149 +54,33 @@ try { Write-Host "`rDownloading: [$bar] $percent% ($downloadedMB MB / $totalMB MB)" -NoNewline -ForegroundColor Yellow } } - - # Close Streams - $outputStream.Close() - $inputStream.Close() - $httpClient.Dispose() - + $outputStream.Close(); $inputStream.Close(); $httpClient.Dispose() Write-Host "`nDownload complete: $installerPath" -ForegroundColor Green } catch { - Write-Error "`nFailed to download installer from $installerUrl. Error: $_" + Write-Error "`nFailed to download installer. Error: $_" exit 1 } # -------------------------------------------------------------------------- - # Step 2: Write User-Session GUI Script (BOM-Free UTF-8) + # Step 2: Native Interactive Session Alert (Crosses Session 0 Isolation) # -------------------------------------------------------------------------- - Write-Host "[2/5] Generating user-session GUI dialog..." -ForegroundColor Cyan + Write-Host "[2/4] Triggering interactive alert on active user's desktop..." -ForegroundColor Cyan - $guiContent = @' -Add-Type -AssemblyName System.Windows.Forms -Add-Type -AssemblyName System.Drawing + # Detect Active User Session ID (query session / qwinsta) + $activeSession = (query session | Select-String "Active") -replace '\s+', ' ' + $sessionId = if ($activeSession) { ($activeSession.ToString().Trim().Split(' '))[2] } else { 1 } -$signature = @" -[DllImport("user32.dll", SetLastError = true)] -public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); -"@ -$Win32SetWindowPos = Add-Type -memberDefinition $signature -Name "Win32SetWindowPos" -namespace Win32Functions -passThru - -$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(440, 250) -$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(380, 25) -$labelHeader.Font = New-Object System.Drawing.Font("Segoe UI", 11, [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 begin." -$labelMsg.Location = New-Object System.Drawing.Point(20, 45) -$labelMsg.Size = New-Object System.Drawing.Size(380, 45) -$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(380, 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", 9, [System.Drawing.FontStyle]::Bold) -$btnUpdateNow.Size = New-Object System.Drawing.Size(140, 35) -$btnUpdateNow.Location = New-Object System.Drawing.Point(140, 150) -$btnUpdateNow.UseVisualStyleBackColor = $true - -$btnUpdateNow.Add_Click({ - $timer.Stop() - $script:allowClose = $true - New-Item -Path $flagPath -ItemType File -Force | Out-Null - $form.Close() -}) -$form.Controls.Add($btnUpdateNow) - -$form.Add_Shown({ - [Win32Functions.Win32SetWindowPos]::SetWindowPos($form.Handle, [IntPtr] -1, 0, 0, 0, 0, 0x0003) | Out-Null - $form.Activate() -}) - -$timer = New-Object System.Windows.Forms.Timer -$timer.Interval = 1000 -$script:remaining = 3600 # 1 Hour - -$timer.Add_Tick({ - if ($script:remaining -gt 0) { - $timeSpan = [TimeSpan]::FromSeconds($script:remaining) - $labelTimer.Text = $timeSpan.ToString("hh\:mm\:ss") - $script:remaining-- - [Win32Functions.Win32SetWindowPos]::SetWindowPos($form.Handle, [IntPtr] -1, 0, 0, 0, 0, 0x0003) | Out-Null - } 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() -$form.ShowDialog() | Out-Null -$timer.Dispose() -$form.Dispose() -'@ - - $utf8NoBom = New-Object System.Text.UTF8Encoding($false) - [System.IO.File]::WriteAllText($guiScript, $guiContent, $utf8NoBom) + # Send native interactive dialog directly to user's active screen + $title = "JCT600 IT Support - 8x8 Work Update" + $message = "An automatic update for 8x8 Work has been scheduled by IT Support.`n`nPlease save your active work and wrap up ongoing calls.`n`nThe update will process automatically in 60 minutes." + + # msg.exe sends notification floating on user session screen + msg.exe $sessionId /TIME:3600 "$title`n`n$message" # -------------------------------------------------------------------------- - # Step 3: Trigger Interactive GUI in Active User Session via BUILTIN\Users + # Step 3: Close Running 8x8 Processes & Install Silently # -------------------------------------------------------------------------- - Write-Host "[3/5] Launching dialog in active user's desktop session..." -ForegroundColor Cyan - - $taskName = "JCT600_8x8_Update_UserDialog" - $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$guiScript`"" - $principal = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Users" -RunLevel Limited - - Register-ScheduledTask -TaskName $taskName -Action $action -Principal $principal -Force | Out-Null - Start-ScheduledTask -TaskName $taskName - - Write-Host "Waiting for user dialog response or timer expiration (1 hour max)..." -ForegroundColor Yellow - while (-not (Test-Path $flagFile)) { - Start-Sleep -Seconds 2 - } - - Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue - - # -------------------------------------------------------------------------- - # Step 4: Close Running 8x8 Processes & Install Silently - # -------------------------------------------------------------------------- - Write-Host "[4/5] Stopping 8x8 processes and installing silently..." -ForegroundColor Cyan + Write-Host "[3/4] Stopping 8x8 processes and installing silently..." -ForegroundColor Cyan $targetProcesses = Get-Process | Where-Object { $_.ProcessName -like "*8x8*" -or $_.MainWindowTitle -like "*8x8*" @@ -236,9 +104,9 @@ $form.Dispose() Write-Host "Installation completed successfully." -ForegroundColor Green # -------------------------------------------------------------------------- - # Step 5: Launch 8x8 Work + # Step 4: Launch 8x8 Work # -------------------------------------------------------------------------- - Write-Host "[5/5] Launching 8x8 Work..." -ForegroundColor Cyan + Write-Host "[4/4] Launching 8x8 Work..." -ForegroundColor Cyan $possiblePaths = @( "${env:ProgramFiles}\8x8 Inc\8x8 Work\8x8 Work.exe", @@ -250,25 +118,13 @@ $form.Dispose() $exePath = $possiblePaths | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($exePath) { - $launchTask = "JCT600_8x8_AppLaunch" - $launchAction = New-ScheduledTaskAction -Execute "$exePath" - $launchPrincipal = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Users" -RunLevel Limited - - Register-ScheduledTask -TaskName $launchTask -Action $launchAction -Principal $launchPrincipal -Force | Out-Null - Start-ScheduledTask -TaskName $launchTask - Start-Sleep -Seconds 3 - Unregister-ScheduledTask -TaskName $launchTask -Confirm:$false -ErrorAction SilentlyContinue + Start-Process -FilePath $exePath Write-Host "8x8 Work launched successfully." -ForegroundColor Green } else { Write-Warning "Could not locate 8x8 Work executable." } } finally { - # -------------------------------------------------------------------------- - # Mandatory Cleanup - # -------------------------------------------------------------------------- Write-Host "Cleaning up temporary files..." -ForegroundColor Gray - if (Test-Path $workDir) { - Remove-Item $workDir -Recurse -Force -ErrorAction SilentlyContinue - } + if (Test-Path $workDir) { Remove-Item $workDir -Recurse -Force -ErrorAction SilentlyContinue } } \ No newline at end of file