|
| 1 | +# Copyright 2026 The MathWorks, Inc. |
| 2 | +# |
| 3 | +# Install script for matlab-proxy on Windows. |
| 4 | +# Downloads the latest release binary from GitHub and installs it. |
| 5 | +# |
| 6 | +# Usage: |
| 7 | +# powershell -ExecutionPolicy ByPass -c "irm https://raw.githubusercontent.com/prabhakk-mw/matlab-proxy-go/main/install.ps1 | iex" |
| 8 | +# |
| 9 | +# Options (via environment variables): |
| 10 | +# VERSION Install a specific version (e.g. 0.5.1) |
| 11 | +# INSTALL_DIR Install to a custom directory |
| 12 | +# MWI_NO_MODIFY_PATH=1 Don't add the install directory to PATH |
| 13 | + |
| 14 | +<# |
| 15 | +.SYNOPSIS |
| 16 | +Installer for matlab-proxy. |
| 17 | +
|
| 18 | +.DESCRIPTION |
| 19 | +This script detects your platform architecture and downloads the appropriate |
| 20 | +matlab-proxy binary from GitHub releases, then installs it to the first of: |
| 21 | +
|
| 22 | + $env:INSTALL_DIR (if set) |
| 23 | + $env:XDG_BIN_HOME |
| 24 | + $HOME\.local\bin |
| 25 | +
|
| 26 | +It will then add that directory to PATH by editing the user-level |
| 27 | +Environment registry key. |
| 28 | +
|
| 29 | +.PARAMETER NoModifyPath |
| 30 | +Don't add the install directory to PATH |
| 31 | +
|
| 32 | +.PARAMETER Help |
| 33 | +Print help |
| 34 | +#> |
| 35 | + |
| 36 | +param ( |
| 37 | + [Parameter(HelpMessage = "Don't add the install directory to PATH")] |
| 38 | + [switch]$NoModifyPath, |
| 39 | + [Parameter(HelpMessage = "Print Help")] |
| 40 | + [switch]$Help |
| 41 | +) |
| 42 | + |
| 43 | +$app_name = 'matlab-proxy' |
| 44 | +$repo = 'prabhakk-mw/matlab-proxy-go' |
| 45 | + |
| 46 | +if ($env:MWI_NO_MODIFY_PATH) { |
| 47 | + $NoModifyPath = $true |
| 48 | +} |
| 49 | + |
| 50 | +function Install-Binary($install_args) { |
| 51 | + if ($Help) { |
| 52 | + Get-Help $PSCommandPath -Detailed |
| 53 | + Exit |
| 54 | + } |
| 55 | + |
| 56 | + Initialize-Environment |
| 57 | + |
| 58 | + $arch = Get-Arch |
| 59 | + $version = Get-Version |
| 60 | + |
| 61 | + $tag = "v$version" |
| 62 | + $artifact = "$app_name-$tag-windows-$arch.zip" |
| 63 | + $url = "https://github.com/$repo/releases/download/$tag/$artifact" |
| 64 | + |
| 65 | + Write-Information "Installing $app_name $version (windows/$arch)..." |
| 66 | + Write-Information " From: $url" |
| 67 | + |
| 68 | + # Download and extract |
| 69 | + $tmp = New-Temp-Dir |
| 70 | + $zip_path = Join-Path $tmp $artifact |
| 71 | + |
| 72 | + try { |
| 73 | + $wc = New-Object Net.WebClient |
| 74 | + $proxy = Get-WebProxyFromEnvironment |
| 75 | + if ($null -ne $proxy) { |
| 76 | + $wc.Proxy = $proxy |
| 77 | + } |
| 78 | + $wc.DownloadFile($url, $zip_path) |
| 79 | + } catch { |
| 80 | + throw "ERROR: failed to download $url`n$_" |
| 81 | + } |
| 82 | + |
| 83 | + Expand-Archive -Path $zip_path -DestinationPath $tmp |
| 84 | + |
| 85 | + # Determine install directory |
| 86 | + $dest_dir = $null |
| 87 | + if ($env:INSTALL_DIR) { |
| 88 | + $dest_dir = $env:INSTALL_DIR |
| 89 | + } |
| 90 | + if (-not $dest_dir) { |
| 91 | + $dest_dir = if ($env:XDG_BIN_HOME) { $env:XDG_BIN_HOME } else { $null } |
| 92 | + } |
| 93 | + if (-not $dest_dir) { |
| 94 | + $dest_dir = if ($HOME) { Join-Path $HOME ".local\bin" } else { $null } |
| 95 | + } |
| 96 | + if (-not $dest_dir) { |
| 97 | + throw "ERROR: could not determine install directory. Set INSTALL_DIR." |
| 98 | + } |
| 99 | + |
| 100 | + $dest_dir = New-Item -Force -ItemType Directory -Path $dest_dir |
| 101 | + Write-Information " To: $dest_dir\$app_name.exe" |
| 102 | + |
| 103 | + Copy-Item (Join-Path $tmp "$app_name.exe") -Destination $dest_dir -ErrorAction Stop |
| 104 | + |
| 105 | + # Clean up temp directory |
| 106 | + Remove-Item $tmp -Recurse -Force -ErrorAction SilentlyContinue |
| 107 | + |
| 108 | + Write-Information "" |
| 109 | + Write-Information "$app_name $version installed successfully!" |
| 110 | + |
| 111 | + # Verify installation |
| 112 | + $installed_bin = Join-Path $dest_dir "$app_name.exe" |
| 113 | + & $installed_bin --version |
| 114 | + |
| 115 | + # Update PATH |
| 116 | + if (-not $NoModifyPath) { |
| 117 | + Add-Ci-Path $dest_dir |
| 118 | + if (Add-Path $dest_dir) { |
| 119 | + Write-Information "" |
| 120 | + Write-Information "To add $dest_dir to your PATH, either restart your shell or run:" |
| 121 | + Write-Information "" |
| 122 | + Write-Information " set Path=$dest_dir;%Path% (cmd)" |
| 123 | + Write-Information " `$env:Path = `"$dest_dir;`$env:Path`" (powershell)" |
| 124 | + } |
| 125 | + } |
| 126 | +} |
| 127 | + |
| 128 | +function Get-Version() { |
| 129 | + if ($env:VERSION) { |
| 130 | + return $env:VERSION |
| 131 | + } |
| 132 | + |
| 133 | + Write-Information "Fetching latest release..." |
| 134 | + try { |
| 135 | + $release = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest" -ErrorAction Stop |
| 136 | + $tag = $release.tag_name |
| 137 | + if ($tag -match '^v(.+)$') { |
| 138 | + return $Matches[1] |
| 139 | + } |
| 140 | + throw "Unexpected tag format: $tag" |
| 141 | + } catch { |
| 142 | + throw "ERROR: could not determine latest version. Set VERSION manually.`n$_" |
| 143 | + } |
| 144 | +} |
| 145 | + |
| 146 | +function Get-Arch() { |
| 147 | + try { |
| 148 | + # Use .NET to detect OS architecture |
| 149 | + # Works correctly on PowerShell Core 7.3+ and Windows PowerShell on Win 11 22H2+ |
| 150 | + $a = [System.Reflection.Assembly]::LoadWithPartialName("System.Runtime.InteropServices.RuntimeInformation") |
| 151 | + $t = $a.GetType("System.Runtime.InteropServices.RuntimeInformation") |
| 152 | + $p = $t.GetProperty("OSArchitecture") |
| 153 | + switch ($p.GetValue($null).ToString()) { |
| 154 | + "X64" { return "amd64" } |
| 155 | + "Arm64" { return "arm64" } |
| 156 | + } |
| 157 | + } catch { |
| 158 | + Write-Verbose "Could not detect architecture via RuntimeInformation: $_" |
| 159 | + } |
| 160 | + |
| 161 | + # Fallback for older .NET |
| 162 | + if ([System.Environment]::Is64BitOperatingSystem) { |
| 163 | + return "amd64" |
| 164 | + } |
| 165 | + |
| 166 | + throw "ERROR: unsupported architecture. Only 64-bit Windows is supported." |
| 167 | +} |
| 168 | + |
| 169 | +function Get-WebProxyFromEnvironment() { |
| 170 | + $proxy_url = if ($env:HTTPS_PROXY) { $env:HTTPS_PROXY } else { $env:ALL_PROXY } |
| 171 | + if ([string]::IsNullOrWhiteSpace($proxy_url)) { |
| 172 | + return $null |
| 173 | + } |
| 174 | + try { |
| 175 | + $uri = [System.Uri]$proxy_url |
| 176 | + $proxy = New-Object System.Net.WebProxy($uri) |
| 177 | + if (-not [string]::IsNullOrEmpty($uri.UserInfo)) { |
| 178 | + $parts = $uri.UserInfo.Split(':') |
| 179 | + $user = [System.Uri]::UnescapeDataString($parts[0]) |
| 180 | + $pass = if ($null -eq $parts[1]) { "" } else { [System.Uri]::UnescapeDataString($parts[1]) } |
| 181 | + $proxy.Credentials = New-Object System.Net.NetworkCredential($user, $pass) |
| 182 | + } |
| 183 | + return $proxy |
| 184 | + } catch { |
| 185 | + Write-Verbose "Failed to parse proxy URL: $_" |
| 186 | + return $null |
| 187 | + } |
| 188 | +} |
| 189 | + |
| 190 | +function Initialize-Environment() { |
| 191 | + if (($PSVersionTable.PSVersion.Major) -lt 5) { |
| 192 | + throw @" |
| 193 | +Error: PowerShell 5 or later is required to install $app_name. |
| 194 | +Upgrade PowerShell: |
| 195 | +
|
| 196 | + https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell |
| 197 | +
|
| 198 | +"@ |
| 199 | + } |
| 200 | + |
| 201 | + $allowedExecutionPolicy = @('Unrestricted', 'RemoteSigned', 'Bypass') |
| 202 | + if ((Get-ExecutionPolicy).ToString() -notin $allowedExecutionPolicy) { |
| 203 | + throw @" |
| 204 | +Error: PowerShell requires an execution policy in [$($allowedExecutionPolicy -join ", ")] to run $app_name. For example, to set the execution policy to 'RemoteSigned' please run: |
| 205 | +
|
| 206 | + Set-ExecutionPolicy RemoteSigned -scope CurrentUser |
| 207 | +
|
| 208 | +"@ |
| 209 | + } |
| 210 | + |
| 211 | + if ([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls12') { |
| 212 | + throw @" |
| 213 | +Error: Installing $app_name requires at least .NET Framework 4.5 |
| 214 | +Please download and install it first: |
| 215 | +
|
| 216 | + https://www.microsoft.com/net/download |
| 217 | +
|
| 218 | +"@ |
| 219 | + } |
| 220 | +} |
| 221 | + |
| 222 | +# Add to PATH in GitHub Actions |
| 223 | +function Add-Ci-Path($PathToAdd) { |
| 224 | + if (($gh_path = $env:GITHUB_PATH)) { |
| 225 | + Write-Output "$PathToAdd" | Out-File -FilePath "$gh_path" -Encoding utf8 -Append |
| 226 | + } |
| 227 | +} |
| 228 | + |
| 229 | +# Permanently add to user-level PATH via the registry |
| 230 | +# Returns $true if the registry was modified, $false if already on PATH |
| 231 | +function Add-Path($LiteralPath) { |
| 232 | + $RegistryPath = 'registry::HKEY_CURRENT_USER\Environment' |
| 233 | + $CurrentDirectories = (Get-Item -LiteralPath $RegistryPath).GetValue('Path', '', 'DoNotExpandEnvironmentNames') -split ';' -ne '' |
| 234 | + |
| 235 | + if ($LiteralPath -in $CurrentDirectories) { |
| 236 | + return $false |
| 237 | + } |
| 238 | + |
| 239 | + $NewPath = (,$LiteralPath + $CurrentDirectories) -join ';' |
| 240 | + Set-ItemProperty -Type ExpandString -LiteralPath $RegistryPath Path $NewPath |
| 241 | + |
| 242 | + # Broadcast WM_SETTINGCHANGE so the shell reloads the updated PATH |
| 243 | + $DummyName = 'matlab-proxy-' + [guid]::NewGuid().ToString() |
| 244 | + [Environment]::SetEnvironmentVariable($DummyName, 'dummy', 'User') |
| 245 | + [Environment]::SetEnvironmentVariable($DummyName, [NullString]::value, 'User') |
| 246 | + |
| 247 | + return $true |
| 248 | +} |
| 249 | + |
| 250 | +function New-Temp-Dir() { |
| 251 | + [CmdletBinding(SupportsShouldProcess)] |
| 252 | + param() |
| 253 | + $parent = [System.IO.Path]::GetTempPath() |
| 254 | + [string] $name = [System.Guid]::NewGuid() |
| 255 | + New-Item -ItemType Directory -Path (Join-Path $parent $name) |
| 256 | +} |
| 257 | + |
| 258 | +# Suppress PSScriptAnalyzer warnings for globals |
| 259 | +$Null = $NoModifyPath, $Help |
| 260 | +$InformationPreference = "Continue" |
| 261 | + |
| 262 | +try { |
| 263 | + Install-Binary "$Args" |
| 264 | +} catch { |
| 265 | + Write-Information $_ |
| 266 | + exit 1 |
| 267 | +} |
0 commit comments