Add reboot mode, TLS fallback, kiosk app detection, and user registry scanning
- Add -Reboot/-MinUptimeDays parameter set to reboot high-uptime PCs via API - Add WebClient fallback for TLS/SSL connection errors on API calls - Add per-user registry scanning (HKU hives) for installed app detection - Add Dashboard and Lobby Display kiosk app detection (app IDs 82, 83) - Add SkipCertificateCheck support for PowerShell 7+ - Increase session timeouts (20s connect, 120s operation) - Increase default ThrottleLimit from 10 to 25 - Add Install-KioskApp.ps1 and user registry detection test scripts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
273
remote-execution/Install-KioskApp.ps1
Normal file
273
remote-execution/Install-KioskApp.ps1
Normal file
@@ -0,0 +1,273 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Remote installer for Dashboard and Lobby Display kiosk applications.
|
||||
|
||||
.DESCRIPTION
|
||||
Deploys GE Aerospace Dashboard or Lobby Display kiosk installers to remote PCs via WinRM.
|
||||
Pushes the installer file and runs it silently.
|
||||
|
||||
.PARAMETER ComputerName
|
||||
Single computer name, IP address, or array of computers to target.
|
||||
|
||||
.PARAMETER ComputerListFile
|
||||
Path to text file containing computer names/IPs (one per line).
|
||||
|
||||
.PARAMETER App
|
||||
Which application to install: Dashboard or LobbyDisplay
|
||||
|
||||
.PARAMETER InstallerPath
|
||||
Path to the installer .exe file. If not specified, looks in the script directory.
|
||||
|
||||
.PARAMETER Credential
|
||||
PSCredential for remote authentication. Prompts if not provided.
|
||||
|
||||
.PARAMETER Uninstall
|
||||
Uninstall the application instead of installing.
|
||||
|
||||
.EXAMPLE
|
||||
# Install Dashboard on a single PC
|
||||
.\Install-KioskApp.ps1 -ComputerName "PC001" -App Dashboard
|
||||
|
||||
.EXAMPLE
|
||||
# Install Lobby Display on multiple PCs from file
|
||||
.\Install-KioskApp.ps1 -ComputerListFile ".\lobby-pcs.txt" -App LobbyDisplay
|
||||
|
||||
.EXAMPLE
|
||||
# Uninstall Dashboard from a PC
|
||||
.\Install-KioskApp.ps1 -ComputerName "PC001" -App Dashboard -Uninstall
|
||||
|
||||
.NOTES
|
||||
Author: Shop Floor Tools
|
||||
Requires: PowerShell 5.1+, WinRM enabled on targets, Admin credentials
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Position=0)]
|
||||
[string[]]$ComputerName,
|
||||
|
||||
[Parameter()]
|
||||
[string]$ComputerListFile,
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet('Dashboard', 'LobbyDisplay')]
|
||||
[string]$App,
|
||||
|
||||
[Parameter()]
|
||||
[string]$InstallerPath,
|
||||
|
||||
[Parameter()]
|
||||
[PSCredential]$Credential,
|
||||
|
||||
[Parameter()]
|
||||
[string]$DnsSuffix = "logon.ds.ge.com",
|
||||
|
||||
[Parameter()]
|
||||
[switch]$Uninstall
|
||||
)
|
||||
|
||||
# =============================================================================
|
||||
# Configuration
|
||||
# =============================================================================
|
||||
$AppConfig = @{
|
||||
'Dashboard' = @{
|
||||
InstallerName = 'GEAerospaceDashboardSetup.exe'
|
||||
AppName = 'GE Aerospace Dashboard'
|
||||
UninstallGuid = '{9D9EEE25-4D24-422D-98AF-2ADEDA4745ED}'
|
||||
}
|
||||
'LobbyDisplay' = @{
|
||||
InstallerName = 'GEAerospaceLobbyDisplaySetup.exe'
|
||||
AppName = 'GE Aerospace Lobby Display'
|
||||
UninstallGuid = '{42FFB952-0B72-493F-8869-D957344CA305}'
|
||||
}
|
||||
}
|
||||
|
||||
$config = $AppConfig[$App]
|
||||
|
||||
# =============================================================================
|
||||
# Helper Functions
|
||||
# =============================================================================
|
||||
|
||||
function Write-Log {
|
||||
param([string]$Message, [string]$Level = "INFO")
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$color = switch ($Level) {
|
||||
"ERROR" { "Red" }
|
||||
"WARNING" { "Yellow" }
|
||||
"SUCCESS" { "Green" }
|
||||
"TASK" { "Cyan" }
|
||||
default { "White" }
|
||||
}
|
||||
Write-Host "[$timestamp] [$Level] $Message" -ForegroundColor $color
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Main Execution
|
||||
# =============================================================================
|
||||
|
||||
Write-Host ""
|
||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||
Write-Host " Kiosk App Installer - $($config.AppName)" -ForegroundColor Cyan
|
||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Get credentials
|
||||
if (-not $Credential) {
|
||||
Write-Log "Enter credentials for remote PCs:" -Level "INFO"
|
||||
$Credential = Get-Credential -Message "Enter admin credentials for remote PCs"
|
||||
if (-not $Credential) {
|
||||
Write-Log "Credentials required. Exiting." -Level "ERROR"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Build computer list
|
||||
$computers = @()
|
||||
|
||||
if ($ComputerListFile) {
|
||||
if (Test-Path $ComputerListFile) {
|
||||
$computers = Get-Content $ComputerListFile | Where-Object { $_.Trim() -and -not $_.StartsWith("#") }
|
||||
} else {
|
||||
Write-Log "Computer list file not found: $ComputerListFile" -Level "ERROR"
|
||||
exit 1
|
||||
}
|
||||
} elseif ($ComputerName) {
|
||||
$computers = $ComputerName
|
||||
} else {
|
||||
Write-Log "No computers specified. Use -ComputerName or -ComputerListFile" -Level "ERROR"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($computers.Count -eq 0) {
|
||||
Write-Log "No computers to process." -Level "ERROR"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Target computers: $($computers.Count)" -Level "INFO"
|
||||
Write-Log "Action: $(if ($Uninstall) { 'Uninstall' } else { 'Install' })" -Level "TASK"
|
||||
Write-Host ""
|
||||
|
||||
# Find installer if not specified (for install only)
|
||||
if (-not $Uninstall) {
|
||||
if (-not $InstallerPath) {
|
||||
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$InstallerPath = Join-Path $scriptDir $config.InstallerName
|
||||
}
|
||||
|
||||
if (-not (Test-Path $InstallerPath)) {
|
||||
Write-Log "Installer not found: $InstallerPath" -Level "ERROR"
|
||||
Write-Log "Please specify -InstallerPath or place $($config.InstallerName) in the script directory" -Level "ERROR"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Installer: $InstallerPath" -Level "INFO"
|
||||
}
|
||||
|
||||
# Build FQDNs
|
||||
$targetFQDNs = $computers | ForEach-Object {
|
||||
if ($_ -like "*.*") { $_ } else { "$_.$DnsSuffix" }
|
||||
}
|
||||
|
||||
# Create session options
|
||||
$sessionOption = New-PSSessionOption -OpenTimeout 30000 -OperationTimeout 300000 -NoMachineProfile
|
||||
|
||||
$successCount = 0
|
||||
$failCount = 0
|
||||
|
||||
foreach ($fqdn in $targetFQDNs) {
|
||||
Write-Host ""
|
||||
Write-Log "Processing: $fqdn" -Level "TASK"
|
||||
|
||||
try {
|
||||
# Create session
|
||||
$session = New-PSSession -ComputerName $fqdn -Credential $Credential -SessionOption $sessionOption -Authentication Negotiate -ErrorAction Stop
|
||||
|
||||
if ($Uninstall) {
|
||||
# Uninstall
|
||||
Write-Log " Uninstalling $($config.AppName)..." -Level "INFO"
|
||||
|
||||
$result = Invoke-Command -Session $session -ScriptBlock {
|
||||
param($guid, $appName)
|
||||
$result = @{ Success = $false; Output = ""; Error = $null }
|
||||
|
||||
# Find uninstaller
|
||||
$uninstallPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$guid`_is1"
|
||||
if (-not (Test-Path $uninstallPath)) {
|
||||
$uninstallPath = "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$guid`_is1"
|
||||
}
|
||||
|
||||
if (Test-Path $uninstallPath) {
|
||||
$uninstallString = (Get-ItemProperty $uninstallPath).UninstallString
|
||||
if ($uninstallString) {
|
||||
# Run uninstaller silently
|
||||
$uninstallExe = $uninstallString -replace '"', ''
|
||||
$proc = Start-Process -FilePath $uninstallExe -ArgumentList "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART" -Wait -PassThru -WindowStyle Hidden
|
||||
$result.Success = ($proc.ExitCode -eq 0)
|
||||
$result.Output = "Exit code: $($proc.ExitCode)"
|
||||
} else {
|
||||
$result.Error = "No uninstall string found"
|
||||
}
|
||||
} else {
|
||||
$result.Error = "$appName not found in registry"
|
||||
}
|
||||
|
||||
return $result
|
||||
} -ArgumentList $config.UninstallGuid, $config.AppName
|
||||
|
||||
} else {
|
||||
# Install
|
||||
$remoteTempPath = "C:\Windows\Temp\$($config.InstallerName)"
|
||||
|
||||
Write-Log " Pushing installer to remote PC..." -Level "INFO"
|
||||
Copy-Item -Path $InstallerPath -Destination $remoteTempPath -ToSession $session -Force -ErrorAction Stop
|
||||
|
||||
Write-Log " Running installer silently..." -Level "INFO"
|
||||
$result = Invoke-Command -Session $session -ScriptBlock {
|
||||
param($installerPath)
|
||||
$result = @{ Success = $false; Output = ""; Error = $null }
|
||||
|
||||
try {
|
||||
$proc = Start-Process -FilePath $installerPath -ArgumentList "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART" -Wait -PassThru -WindowStyle Hidden
|
||||
$result.Success = ($proc.ExitCode -eq 0)
|
||||
$result.Output = "Exit code: $($proc.ExitCode)"
|
||||
|
||||
# Clean up installer
|
||||
Remove-Item $installerPath -Force -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
$result.Error = $_.Exception.Message
|
||||
}
|
||||
|
||||
return $result
|
||||
} -ArgumentList $remoteTempPath
|
||||
}
|
||||
|
||||
# Close session
|
||||
Remove-PSSession $session -ErrorAction SilentlyContinue
|
||||
|
||||
# Process result
|
||||
if ($result.Success) {
|
||||
Write-Log "[OK] $fqdn - $($result.Output)" -Level "SUCCESS"
|
||||
$successCount++
|
||||
} else {
|
||||
$errorMsg = if ($result.Error) { $result.Error } else { $result.Output }
|
||||
Write-Log "[FAIL] $fqdn - $errorMsg" -Level "ERROR"
|
||||
$failCount++
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Log "[FAIL] ${fqdn}: $($_.Exception.Message)" -Level "ERROR"
|
||||
$failCount++
|
||||
if ($session) { Remove-PSSession $session -ErrorAction SilentlyContinue }
|
||||
}
|
||||
}
|
||||
|
||||
# Summary
|
||||
Write-Host ""
|
||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||
Write-Host " SUMMARY" -ForegroundColor Cyan
|
||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||
Write-Host " App: $($config.AppName)" -ForegroundColor White
|
||||
Write-Host " Action: $(if ($Uninstall) { 'Uninstall' } else { 'Install' })" -ForegroundColor White
|
||||
Write-Host " Successful: $successCount" -ForegroundColor Green
|
||||
Write-Host " Failed: $failCount" -ForegroundColor $(if ($failCount -gt 0) { "Red" } else { "White" })
|
||||
Write-Host ("=" * 70) -ForegroundColor Cyan
|
||||
Reference in New Issue
Block a user