From 7a31af24b69f8fd4021f09d0527db88170c7e002 Mon Sep 17 00:00:00 2001 From: CristianD Date: Wed, 29 Jul 2026 17:23:57 +0100 Subject: [PATCH] Update 8x8_Work_Updater.ps1 --- 8x8_Work_Updater.ps1 | 194 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 165 insertions(+), 29 deletions(-) diff --git a/8x8_Work_Updater.ps1 b/8x8_Work_Updater.ps1 index 92a031e..c51d92b 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 blocking 1-hour -# popup alert, silently installs, and launches 8x8 under the standard -# user session via Explorer. +# Description: Downloads 8x8, launches an interactive JCT600 GUI inside the +# active user's desktop session using Explorer process injection, +# waits for response/timer, silently installs, and relaunches 8x8. # ============================================================================== # Ensure script is running elevated @@ -11,23 +11,32 @@ if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdenti exit 1 } -# Load required .NET assemblies Add-Type -AssemblyName System.Net.Http -$workDir = "C:\ProgramData\JCT600_8x8Update" -$installerPath = Join-Path $workDir "8x8_Work_Installer.msi" -$vbsAlertPath = Join-Path $workDir "ShowUserAlert.vbs" +$workDir = "C:\ProgramData\JCT600_8x8Update" +$flagFile = Join-Path $workDir "8x8_Update_Proceed.flag" +$guiScript = Join-Path $workDir "Show-8x8UserGui.ps1" if (-not (Test-Path $workDir)) { New-Item -Path $workDir -ItemType Directory -Force | Out-Null } +# Ensure standard users have full read/execute permissions to the folder +$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 Setup Installer with Console Progress Bar # -------------------------------------------------------------------------- - $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 + $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 try { $httpClient = New-Object System.Net.Http.HttpClient @@ -64,26 +73,148 @@ try { } # -------------------------------------------------------------------------- - # Step 2: Trigger Blocking Interactive Popup (Waits for Click or 1 Hour) + # Step 2: Write User-Session GUI Script (BOM-Free UTF-8) # -------------------------------------------------------------------------- - Write-Host "[2/4] Triggering interactive alert on active user's desktop..." -ForegroundColor Cyan + Write-Host "[2/5] Generating user-session GUI dialog script..." -ForegroundColor Cyan - # Generate a blocking VBScript WshShell.Popup (Type 48 = Exclamation, 4096 = System Modal / Always on top) - $vbsContent = @" -Set wshShell = CreateObject("WScript.Shell") -intButton = wshShell.Popup("An automatic update for 8x8 Work has been scheduled by JCT600 IT Support." & vbCrLf & vbCrLf & "Please save active work and finish ongoing calls." & vbCrLf & vbCrLf & "Click OK or close this window to update immediately, or wait for the 1-hour timer.", 3600, "JCT600 IT Support — 8x8 Work Update", 48 + 4096) + $guiContent = @' +Add-Type -AssemblyName System.Windows.Forms +Add-Type -AssemblyName System.Drawing + +$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); "@ - - [System.IO.File]::WriteAllText($vbsAlertPath, $vbsContent, [System.Text.Encoding]::ASCII) +$Win32SetWindowPos = Add-Type -memberDefinition $signature -Name "Win32SetWindowPos" -namespace Win32Functions -passThru - # Launch popup and WAIT for user click or 3600-second timeout - Write-Host "Waiting for user acknowledgment or 1-hour timeout..." -ForegroundColor Yellow - $popupProcess = Start-Process "wscript.exe" -ArgumentList "`"$vbsAlertPath`"" -Wait -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) # -------------------------------------------------------------------------- - # Step 3: Close Running 8x8 Processes & Install Silently + # Step 3: Trigger Interactive GUI in Active Desktop Session # -------------------------------------------------------------------------- - Write-Host "[3/4] Stopping 8x8 processes and installing silently..." -ForegroundColor Cyan + Write-Host "[3/5] Launching interactive dialog on user desktop..." -ForegroundColor Cyan + + $explorerProc = Get-Process -Name explorer -ErrorAction SilentlyContinue | Select-Object -First 1 + + if (-not $explorerProc) { + Write-Warning "No active desktop session detected. Proceeding directly to update." + } else { + # Inject GUI execution trigger into the active user's explorer shell context + $taskName = "JCT600_8x8_GUI_Task" + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -WindowStyle Hidden -File `"$guiScript`"" + + # Using Interactive logon trigger bypasses Session 0 isolation + $trigger = New-ScheduledTaskTrigger -At (Get-Date).AddSeconds(1) -Once + $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Priority 0 + + # Register task under INTERACTIVE user token + $task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings + Register-ScheduledTask -TaskName $taskName -InputObject $task -User "INTERACTIVE" -Force | Out-Null + Start-ScheduledTask -TaskName $taskName | Out-Null + + 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 $targetProcesses = Get-Process | Where-Object { $_.ProcessName -like "*8x8*" -or $_.MainWindowTitle -like "*8x8*" @@ -107,9 +238,9 @@ intButton = wshShell.Popup("An automatic update for 8x8 Work has been scheduled Write-Host "Installation completed successfully." -ForegroundColor Green # -------------------------------------------------------------------------- - # Step 4: Launch 8x8 Work via Explorer (User Context) + # Step 5: Launch 8x8 Work via Explorer Shell # -------------------------------------------------------------------------- - Write-Host "[4/4] Launching 8x8 Work in user session..." -ForegroundColor Cyan + Write-Host "[5/5] Launching 8x8 Work..." -ForegroundColor Cyan $possiblePaths = @( "${env:ProgramFiles}\8x8 Inc\8x8 Work\8x8 Work.exe", @@ -121,15 +252,20 @@ intButton = wshShell.Popup("An automatic update for 8x8 Work has been scheduled $exePath = $possiblePaths | Where-Object { Test-Path $_ } | Select-Object -First 1 if ($exePath) { - # Using explorer.exe to launch the executable forces Windows to run 8x8 in - # the interactive standard user's desktop context, preventing GPU crashes. - Start-Process "explorer.exe" -ArgumentList "`"$exePath`"" - Write-Host "8x8 Work launched successfully." -ForegroundColor Green + if ($explorerProc) { + # Run 8x8 via explorer.exe to launch under standard user graphics context + Start-Process "explorer.exe" -ArgumentList "`"$exePath`"" + Write-Host "8x8 Work launched successfully." -ForegroundColor Green + } else { + Start-Process -FilePath $exePath + } } else { Write-Warning "Could not locate 8x8 Work executable." } } finally { 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