Update 8x8_Work_Updater.ps1
This commit is contained in:
+123
-38
@@ -1,9 +1,8 @@
|
|||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# Script Name: 8x8_Work_Updater.ps1
|
# Script Name: 8x8_Work_Updater.ps1
|
||||||
# Description: Downloads 8x8 with a progress bar, schedules and launches an unclosable
|
# Description: Downloads 8x8 with a progress bar, launches an unclosable HTA
|
||||||
# VBScript interactive countdown directly in the user session,
|
# countdown prompt in the user's session (no X button), waits for
|
||||||
# waits for user confirmation or 1-hour timeout, silently installs,
|
# user action or 1-hour timeout, installs silently, and relaunches 8x8.
|
||||||
# and relaunches 8x8 Work seamlessly.
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
# Ensure script is running elevated
|
# Ensure script is running elevated
|
||||||
@@ -16,7 +15,7 @@ Add-Type -AssemblyName System.Net.Http
|
|||||||
|
|
||||||
$workDir = "C:\ProgramData\JCT600_8x8Update"
|
$workDir = "C:\ProgramData\JCT600_8x8Update"
|
||||||
$flagFile = Join-Path $workDir "8x8_Update_Proceed.flag"
|
$flagFile = Join-Path $workDir "8x8_Update_Proceed.flag"
|
||||||
$vbsScript = Join-Path $workDir "Show-8x8Prompt.vbs"
|
$htaPromptPath = Join-Path $workDir "Show-8x8Prompt.hta"
|
||||||
$installerPath = Join-Path $workDir "8x8_Work_Installer.msi"
|
$installerPath = Join-Path $workDir "8x8_Work_Installer.msi"
|
||||||
|
|
||||||
if (-not (Test-Path $workDir)) {
|
if (-not (Test-Path $workDir)) {
|
||||||
@@ -71,45 +70,131 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# Step 2: Generate Persistent VBScript UI Dialog (Cannot be dismissed via X)
|
# Step 2: Generate Unclosable HTA Countdown Dialog (No Close/X Button)
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
Write-Host "[2/4] Generating user dialog..." -ForegroundColor Cyan
|
Write-Host "[2/4] Generating unclosable dialog..." -ForegroundColor Cyan
|
||||||
|
|
||||||
$vbsContent = @"
|
$htaContent = @"
|
||||||
Set objShell = CreateObject("WScript.Shell")
|
<!DOCTYPE html>
|
||||||
Set objFSO = CreateObject("Scripting.FileSystemObject")
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>JCT600 IT Support — 8x8 Work Update</title>
|
||||||
|
<HTA:APPLICATION
|
||||||
|
ID="o8x8Update"
|
||||||
|
APPLICATIONNAME="JCT600 8x8 Work Update"
|
||||||
|
BORDER="dialog"
|
||||||
|
BORDERSTYLE="normal"
|
||||||
|
CAPTION="yes"
|
||||||
|
CONTEXTMENU="no"
|
||||||
|
ICON=""
|
||||||
|
INNERBORDER="no"
|
||||||
|
MAXIMIZEBUTTON="no"
|
||||||
|
MINIMIZEBUTTON="no"
|
||||||
|
NAVIGABLE="no"
|
||||||
|
SCROLL="no"
|
||||||
|
SCROLLFLAT="no"
|
||||||
|
SELECTION="no"
|
||||||
|
SHOWINTASKBAR="yes"
|
||||||
|
SINGLEINSTANCE="yes"
|
||||||
|
SYSMENU="no"
|
||||||
|
WINDOWSTATE="normal"
|
||||||
|
/>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #F0F2F5;
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
color: #002B49;
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.message {
|
||||||
|
color: #333333;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.timer {
|
||||||
|
color: #C00000;
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
.btn-update {
|
||||||
|
background-color: #002B49;
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px 32px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.btn-update:hover {
|
||||||
|
background-color: #004B7D;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script language="javascript">
|
||||||
|
var totalSeconds = 3600;
|
||||||
|
|
||||||
strMsg = "An automatic update for 8x8 Work has been scheduled by IT Support." & vbCrLf & vbCrLf & _
|
function initWindow() {
|
||||||
"Please save your active work and finish ongoing calls." & vbCrLf & vbCrLf & _
|
window.resizeTo(480, 270);
|
||||||
"Click OK to update now, or the update will proceed automatically in 60 minutes."
|
window.moveTo((screen.width - 480) / 2, (screen.height - 270) / 2);
|
||||||
|
updateDisplay();
|
||||||
|
setInterval(tick, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
startTime = Timer
|
function tick() {
|
||||||
totalSeconds = 3600
|
if (totalSeconds > 0) {
|
||||||
|
totalSeconds--;
|
||||||
|
updateDisplay();
|
||||||
|
} else {
|
||||||
|
proceedUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Do
|
function updateDisplay() {
|
||||||
elapsed = Timer - startTime
|
var mins = Math.floor(totalSeconds / 60);
|
||||||
If elapsed < 0 Then elapsed = elapsed + 86400 ' Handle midnight rollover
|
var secs = totalSeconds % 60;
|
||||||
remaining = Int(totalSeconds - elapsed)
|
var formattedMins = mins < 10 ? "0" + mins : mins;
|
||||||
|
var formattedSecs = secs < 10 ? "0" + secs : secs;
|
||||||
|
document.getElementById("timerDisplay").innerText = formattedMins + ":" + formattedSecs;
|
||||||
|
}
|
||||||
|
|
||||||
If remaining <= 0 Then Exit Do
|
function proceedUpdate() {
|
||||||
|
try {
|
||||||
' 64 = Information Icon, 4096 = System Modal (Always on Top)
|
var fso = new ActiveXObject("Scripting.FileSystemObject");
|
||||||
intReturn = objShell.Popup(strMsg, remaining, "JCT600 IT Support - 8x8 Work Update", 64 + 4096)
|
var file = fso.CreateTextFile("$($flagFile.Replace('\', '\\'))", true);
|
||||||
|
file.WriteLine("proceed");
|
||||||
' If user clicked OK (1), break loop
|
file.Close();
|
||||||
If intReturn = 1 Then Exit Do
|
} catch(e) {}
|
||||||
Loop
|
window.close();
|
||||||
|
}
|
||||||
' Create flag file to signal main script
|
</script>
|
||||||
Set objFile = objFSO.CreateTextFile("$flagFile", True)
|
</head>
|
||||||
objFile.WriteLine("proceed")
|
<body onload="initWindow()">
|
||||||
objFile.Close
|
<div class="header">JCT600 — IT SUPPORT</div>
|
||||||
|
<div class="message">
|
||||||
|
An automatic update for 8x8 Work has been scheduled.<br>
|
||||||
|
Please save active work or click <b>Update Now</b> to begin.
|
||||||
|
</div>
|
||||||
|
<div class="timer" id="timerDisplay">60:00</div>
|
||||||
|
<button class="btn-update" onclick="proceedUpdate()">Update Now</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($vbsScript, $vbsContent, [System.Text.Encoding]::ASCII)
|
[System.IO.File]::WriteAllText($htaPromptPath, $htaContent, [System.Text.Encoding]::ASCII)
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# Step 3: Launch Native Dialog inside Active User Session
|
# Step 3: Launch Unclosable Dialog in Active User Session
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
Write-Host "[3/4] Launching prompt on logged-in user desktop..." -ForegroundColor Cyan
|
Write-Host "[3/4] Launching prompt on logged-in user desktop..." -ForegroundColor Cyan
|
||||||
|
|
||||||
@@ -120,10 +205,11 @@ objFile.Close
|
|||||||
} else {
|
} else {
|
||||||
$taskName = "JCT600_8x8_UpdatePrompt"
|
$taskName = "JCT600_8x8_UpdatePrompt"
|
||||||
|
|
||||||
schtasks.exe /Create /TN $taskName /TR "wscript.exe `"$vbsScript`"" /SC ONCE /ST 00:00 /IT /RU "$loggedUser" /F | Out-Null
|
# mshta.exe runs the HTML Application natively inside the user's interactive desktop
|
||||||
|
schtasks.exe /Create /TN $taskName /TR "mshta.exe `"$htaPromptPath`"" /SC ONCE /ST 00:00 /IT /RU "$loggedUser" /F | Out-Null
|
||||||
schtasks.exe /Run /TN $taskName | Out-Null
|
schtasks.exe /Run /TN $taskName | Out-Null
|
||||||
|
|
||||||
Write-Host "Prompt sent to $loggedUser. Waiting for user confirmation or 1-hour expiration..." -ForegroundColor Yellow
|
Write-Host "Prompt active for $loggedUser. Waiting for user action or timer expiration..." -ForegroundColor Yellow
|
||||||
while (-not (Test-Path $flagFile)) {
|
while (-not (Test-Path $flagFile)) {
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
}
|
}
|
||||||
@@ -175,9 +261,8 @@ objFile.Close
|
|||||||
if ($exePath) {
|
if ($exePath) {
|
||||||
if (-not [string]::IsNullOrWhiteSpace($loggedUser)) {
|
if (-not [string]::IsNullOrWhiteSpace($loggedUser)) {
|
||||||
$launchTask = "JCT600_8x8_Launch"
|
$launchTask = "JCT600_8x8_Launch"
|
||||||
|
|
||||||
# Using explorer.exe inside the scheduled task ensures the UI process spawns detached into the user shell
|
|
||||||
$taskRunCmd = "explorer.exe `"$exePath`""
|
$taskRunCmd = "explorer.exe `"$exePath`""
|
||||||
|
|
||||||
schtasks.exe /Create /TN $launchTask /TR "$taskRunCmd" /SC ONCE /ST 00:00 /IT /RU "$loggedUser" /F | Out-Null
|
schtasks.exe /Create /TN $launchTask /TR "$taskRunCmd" /SC ONCE /ST 00:00 /IT /RU "$loggedUser" /F | Out-Null
|
||||||
schtasks.exe /Run /TN $launchTask | Out-Null
|
schtasks.exe /Run /TN $launchTask | Out-Null
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user