# NeuralInverse Community Edition - Windows Installer # # Usage: irm https://cdn.neuralinverse.io/ce/install.ps1 | iex # # Features: # - Reads latest version from cdn.neuralinverse.io/ce/latest.json # - Auto-detects architecture (x64/ARM64) # - Tries formats: .exe (Inno Setup) > .msi > .zip (Portable) # - Registry verification # - Retry logic (up to 2 retries) $ErrorActionPreference = "Stop" $APP_NAME = "NeuralInverse" $CDN_BASE = "https://cdn.neuralinverse.io/ce" $TEMP_DIR = "$env:TEMP\neuralinverse-ce-install" $SUPPORT_EMAIL = "support@neuralinverse.io" $TRACK_URL = "https://ucaeexhc9h.execute-api.us-east-1.amazonaws.com/" Write-Host "========================================" Write-Host " NeuralInverse Community Edition" -ForegroundColor Cyan Write-Host "========================================" Write-Host "" # Fetch version from ce/latest.json Write-Host "Fetching latest CE version..." -ForegroundColor Cyan try { $latestJson = Invoke-WebRequest -Uri "$CDN_BASE/latest.json" -UseBasicParsing -ErrorAction Stop $VERSION = ($latestJson.Content | ConvertFrom-Json).version if ([string]::IsNullOrEmpty($VERSION)) { throw "empty version" } } catch { Write-Host "Could not fetch $CDN_BASE/latest.json : $_" -ForegroundColor Red Write-Host "Check your internet connection or visit https://neuralinverse.io" exit 1 } Write-Host "Version: $VERSION" -ForegroundColor Green # Detect architecture $ARCH = [System.Environment]::GetEnvironmentVariable("PROCESSOR_ARCHITECTURE") if ($ARCH -eq "AMD64") { $ARCH_SUFFIX = "x64" Write-Host "Detected: Windows x64" -ForegroundColor Green } elseif ($ARCH -eq "ARM64") { $ARCH_SUFFIX = "arm64" Write-Host "Detected: Windows ARM64" -ForegroundColor Green } else { Write-Host "Unsupported architecture: $ARCH" -ForegroundColor Red exit 1 } # Fire-and-forget download tracking (failure silently ignored) try { $trackBody = "{`"version`":`"$VERSION`",`"platform`":`"win32-$ARCH_SUFFIX`"}" Invoke-WebRequest -Uri $TRACK_URL -Method POST -Body $trackBody ` -ContentType "application/json" -TimeoutSec 4 ` -UseBasicParsing -ErrorAction SilentlyContinue | Out-Null } catch {} # Try formats: .exe > .msi > .zip $PREFERRED_FORMATS = @("exe", "msi", "zip") $SELECTED_FORMAT = $null $DOWNLOAD_FILE = $null $DOWNLOAD_URL = $null Write-Host "Checking available formats..." -ForegroundColor Cyan foreach ($format in $PREFERRED_FORMATS) { $testFile = "$APP_NAME-$VERSION-win32-$ARCH_SUFFIX.$format" $testUrl = "$CDN_BASE/$VERSION/$testFile" try { $response = Invoke-WebRequest -Uri $testUrl -Method Head -UseBasicParsing -ErrorAction Stop if ($response.StatusCode -eq 200) { $SELECTED_FORMAT = $format $DOWNLOAD_FILE = $testFile $DOWNLOAD_URL = $testUrl Write-Host "Found: .$format" -ForegroundColor Green break } } catch { } } if (-not $SELECTED_FORMAT) { Write-Host "No packages found on CDN for win32-$ARCH_SUFFIX v$VERSION" -ForegroundColor Red exit 1 } $INSTALLER_PATH = "$TEMP_DIR\$DOWNLOAD_FILE" function Cleanup { if (Test-Path $TEMP_DIR) { Remove-Item -Path $TEMP_DIR -Recurse -Force -ErrorAction SilentlyContinue } } function Check-ExistingInstallation { foreach ($root in @("HKLM", "HKCU")) { $installed = Get-ItemProperty -Path "${root}:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*$APP_NAME*" } | Select-Object -First 1 if ($installed) { Write-Host "Existing installation found: $($installed.DisplayVersion) -- removing..." -ForegroundColor Yellow $uninstaller = $installed.UninstallString if ($uninstaller) { if ($uninstaller -match "msiexec") { $productCode = $uninstaller -replace '.*(\{.*\}).*', '$1' Start-Process msiexec.exe -ArgumentList "/x $productCode /qn" -Wait } else { Start-Process -FilePath $uninstaller -ArgumentList "/VERYSILENT /SUPPRESSMSGBOXES" -Wait } Start-Sleep -Seconds 2 Write-Host "Uninstalled" -ForegroundColor Green } break } } } function Download-App { Write-Host "" Write-Host "[1/3] Downloading $APP_NAME (.$SELECTED_FORMAT)..." -ForegroundColor Cyan New-Item -ItemType Directory -Force -Path $TEMP_DIR | Out-Null try { try { Import-Module BitsTransfer -ErrorAction Stop Start-BitsTransfer -Source $DOWNLOAD_URL -Destination $INSTALLER_PATH -Description "Downloading $APP_NAME CE" } catch { Invoke-WebRequest -Uri $DOWNLOAD_URL -OutFile $INSTALLER_PATH -UseBasicParsing } } catch { Write-Host "Download failed: $_" -ForegroundColor Red return $false } $fileInfo = Get-Item $INSTALLER_PATH if ($fileInfo.Length -lt 1MB) { Write-Host "Downloaded file too small ($($fileInfo.Length) bytes)" -ForegroundColor Red return $false } Write-Host "File size: $([math]::Round($fileInfo.Length / 1MB, 1)) MB" -ForegroundColor Green return $true } function Install-EXE { Write-Host "" Write-Host "[2/3] Installing (Inno Setup)..." -ForegroundColor Cyan try { $p = Start-Process -FilePath $INSTALLER_PATH -ArgumentList "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-" -Wait -PassThru if ($p.ExitCode -eq 0) { Write-Host "Installation completed" -ForegroundColor Green; return $true } Write-Host "Installer exited with code: $($p.ExitCode)" -ForegroundColor Red; return $false } catch { Write-Host "Installation failed: $_" -ForegroundColor Red; return $false } } function Install-MSI { Write-Host "" Write-Host "[2/3] Installing (MSI)..." -ForegroundColor Cyan try { $p = Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$INSTALLER_PATH`" /qn /norestart ALLUSERS=1" -Wait -PassThru if ($p.ExitCode -eq 0) { Write-Host "MSI installation completed" -ForegroundColor Green; return $true } Write-Host "MSI failed with code: $($p.ExitCode)" -ForegroundColor Red; return $false } catch { Write-Host "Installation failed: $_" -ForegroundColor Red; return $false } } function Install-ZIP { Write-Host "" Write-Host "[2/3] Installing (Portable)..." -ForegroundColor Cyan try { $installPath = "$env:ProgramFiles\$APP_NAME" $extractDir = "$TEMP_DIR\extracted" Expand-Archive -Path $INSTALLER_PATH -DestinationPath $extractDir -Force $exeFile = Get-ChildItem -Path $extractDir -Filter "$APP_NAME.exe" -Recurse | Select-Object -First 1 if (-not $exeFile) { Write-Host "Could not find $APP_NAME.exe in archive" -ForegroundColor Red; return $false } if (Test-Path $installPath) { Remove-Item -Path $installPath -Recurse -Force } Copy-Item -Path $exeFile.Directory.FullName -Destination $installPath -Recurse -Force $shell = New-Object -ComObject WScript.Shell foreach ($dir in @([Environment]::GetFolderPath("CommonStartMenu") + "\Programs\$APP_NAME", [Environment]::GetFolderPath("Desktop"))) { New-Item -ItemType Directory -Force -Path (Split-Path $dir) | Out-Null $sc = $shell.CreateShortcut($(if ($dir -like "*Programs*") { "$dir\$APP_NAME.lnk" } else { "$dir\$APP_NAME.lnk" })) $sc.TargetPath = "$installPath\$APP_NAME.exe"; $sc.WorkingDirectory = $installPath; $sc.Save() } Write-Host "Portable installation completed: $installPath" -ForegroundColor Green return $true } catch { Write-Host "Installation failed: $_" -ForegroundColor Red; return $false } } function Install-App { switch ($SELECTED_FORMAT) { "exe" { return Install-EXE } "msi" { return Install-MSI } "zip" { return Install-ZIP } default { Write-Host "Unknown format: $SELECTED_FORMAT" -ForegroundColor Red; return $false } } } function Verify-Installation { Write-Host "" Write-Host "[3/3] Verifying..." -ForegroundColor Cyan Start-Sleep -Seconds 2 foreach ($root in @("HKLM", "HKCU")) { $installed = Get-ItemProperty -Path "${root}:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*$APP_NAME*" } | Select-Object -First 1 if ($installed) { Write-Host "Verified in registry" -ForegroundColor Green if ($installed.InstallLocation) { Write-Host "Location: $($installed.InstallLocation)" -ForegroundColor Green } return $true } } if (Test-Path "$env:ProgramFiles\$APP_NAME\$APP_NAME.exe") { Write-Host "Portable installation verified" -ForegroundColor Green return $true } Write-Host "Could not verify -- check Start Menu or Desktop" -ForegroundColor Yellow return $true } function Main { Check-ExistingInstallation $retryCount = 0 while ($retryCount -le 2) { if ($retryCount -gt 0) { Write-Host ""; Write-Host "Retry $retryCount of 2..." -ForegroundColor Yellow; Cleanup } if ((Download-App) -and (Install-App) -and (Verify-Installation)) { Cleanup Write-Host "" Write-Host "========================================" Write-Host " + NeuralInverse CE $VERSION installed" -ForegroundColor Green Write-Host "========================================" Write-Host "" Write-Host "Launch from Start Menu or Desktop shortcut" Write-Host "" exit 0 } $retryCount++ } Cleanup Write-Host "" Write-Host "========================================" Write-Host " x Installation failed" -ForegroundColor Red Write-Host "========================================" Write-Host "" Write-Host "Manual download: Invoke-WebRequest -Uri `"$DOWNLOAD_URL`" -OutFile `"$env:USERPROFILE\Downloads\$DOWNLOAD_FILE`"" Write-Host "Contact: $SUPPORT_EMAIL" exit 1 } Main