# ScoutIT Remote Support (RustDesk) - Standalone Install Script $ErrorActionPreference = 'SilentlyContinue' # ── Config ──────────────────────────────────────────────────────────────────── $rustdeskMsi = 'estudio-scoutit-remotesupport.msi' $rustdeskDl = 'https://files.scoutitsystems.com/public/api/raw?file=%2F&hash=VOG5D5aP2ih-2KAaDT0h4Q' $rustdeskInstallDir = 'C:\Program Files\ScoutIT-RemoteSupport' $rustdeskService = 'ScoutIT-RemoteSupport' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # ── Check if already installed ──────────────────────────────────────────────── $svcCheck = Get-Service -Name $rustdeskService -ErrorAction SilentlyContinue if ($null -ne $svcCheck) { Write-Host "ScoutIT Remote Support is already installed. Exiting." exit 0 } # ── Download ────────────────────────────────────────────────────────────────── $msiPath = "$env:SystemRoot\Temp\$rustdeskMsi" Write-Host "Downloading ScoutIT Remote Support client..." Try { (New-Object System.Net.WebClient).DownloadFile($rustdeskDl, $msiPath) } Catch { Write-Error "Download failed: $($_.Exception.Message)" exit 1 } # Verify the downloaded file is a valid MSI (OLE compound doc magic bytes: D0 CF 11 E0) $fileSize = (Get-Item $msiPath).Length Write-Host "Downloaded file size: $fileSize bytes" $magic = [System.IO.File]::ReadAllBytes($msiPath) | Select-Object -First 4 $magicHex = ($magic | ForEach-Object { $_.ToString('X2') }) -join ' ' Write-Host "File header bytes: $magicHex" if ($magicHex -ne 'D0 CF 11 E0') { Write-Error "Downloaded file is not a valid MSI (expected D0 CF 11 E0, got $magicHex). Check the download URL." Remove-Item $msiPath -Force -ErrorAction SilentlyContinue exit 1 } Write-Host "File verified as valid MSI." # ── Silent MSI install ──────────────────────────────────────────────────────── Write-Host "Installing ScoutIT Remote Support client silently..." Try { Start-Process -FilePath "msiexec.exe" ` -ArgumentList "/i `"$msiPath`" /qn" ` -Wait Start-Sleep -Seconds 10 } Catch { Write-Error "MSI install failed: $($_.Exception.Message)" exit 1 } Finally { if (Test-Path $msiPath) { Remove-Item -Path $msiPath -Force } } # ── Locate the installed exe ────────────────────────────────────────────────── # First try: registry InstallLocation from the MSI uninstall entry $uninstallKeys = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' ) $rustdeskExe = $null foreach ($key in $uninstallKeys) { $entry = Get-ItemProperty $key -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match 'scoutit|remotesupport|rustdesk' -or $_.Publisher -match 'scoutit|rustdesk' } | Select-Object -First 1 if ($entry -and $entry.InstallLocation) { $candidate = Get-ChildItem $entry.InstallLocation -Filter '*.exe' -ErrorAction SilentlyContinue | Select-Object -First 1 if ($candidate) { $rustdeskExe = $candidate.FullName Write-Host "Found exe via registry: $rustdeskExe" break } } } # Second try: search only within directories whose name matches expected install folder if (-not $rustdeskExe) { Write-Host "Searching for RustDesk exe in matching install directories..." $found = Get-ChildItem 'C:\Program Files', 'C:\Program Files (x86)' -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'rustdesk|scoutit|remotesupport' } | ForEach-Object { Get-ChildItem $_.FullName -Filter '*.exe' -ErrorAction SilentlyContinue } | Select-Object -First 1 if ($found) { $rustdeskExe = $found.FullName Write-Host "Found exe at: $rustdeskExe" } } # Last resort: list what the MSI actually installed so we can identify the exe if (-not $rustdeskExe) { Write-Warning "Could not locate RustDesk exe. Listing Program Files for diagnosis:" Get-ChildItem 'C:\Program Files', 'C:\Program Files (x86)' -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -gt (Get-Date).AddMinutes(-5) } | ForEach-Object { Write-Host " $($_.FullName)" } Write-Error "Could not locate RustDesk exe after install." exit 1 } $exeDir = Split-Path $rustdeskExe # ── Install service if not present ──────────────────────────────────────────── $svc = Get-Service -Name $rustdeskService -ErrorAction SilentlyContinue if ($null -eq $svc) { Write-Host "Registering ScoutIT Remote Support service..." Start-Process -FilePath $rustdeskExe -ArgumentList '--install-service' -Wait Start-Sleep -Seconds 20 $svc = Get-Service -Name $rustdeskService -ErrorAction SilentlyContinue } # ── Ensure service is running ───────────────────────────────────────────────── if ($null -ne $svc) { $attempts = 0 while ($svc.Status -ne 'Running' -and $attempts -lt 5) { Write-Host "Starting ScoutIT Remote Support service (attempt $($attempts + 1))..." Start-Service -Name $rustdeskService -ErrorAction SilentlyContinue Start-Sleep -Seconds 5 $svc.Refresh() $attempts++ } if ($svc.Status -eq 'Running') { Write-Host "ScoutIT Remote Support service is running." } else { Write-Warning "Service did not reach Running state after $attempts attempts." } } else { Write-Warning "Service '$rustdeskService' not found after install." } # ── Output RustDesk ID ──────────────────────────────────────────────────────── Push-Location $exeDir $rustdeskId = & $rustdeskExe --get-id 2>&1 Pop-Location Write-Output "................................................." Write-Output "ScoutIT Remote Support ID: $rustdeskId" Write-Output "................................................." exit 0