mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 00:50:46 +08:00
Add update checker, tray controller, and slimmer release venv.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
54c6bc9298
commit
fe9df32024
7 changed files with 367 additions and 13 deletions
|
|
@ -7,7 +7,8 @@ This directory builds a Windows deliverable with:
|
|||
- Optional **bundled** portable PostgreSQL **or** **external** existing Postgres
|
||||
- API-hosted UI (`web/dist`) — no separate Vite process for end users
|
||||
- Program / data split so upgrades do not wipe the database
|
||||
- Manual update script + auto-update **manifest contract** (fetch not implemented yet)
|
||||
- Manual update script + check/apply updates (GitHub Releases or custom manifest)
|
||||
- Optional system tray + start-at-logon
|
||||
|
||||
## What users get
|
||||
|
||||
|
|
@ -77,14 +78,35 @@ Existing Windows deploys that only set `NETX_DATABASE_URL` keep working: never s
|
|||
## Manual update
|
||||
|
||||
```powershell
|
||||
.\packaging\update_netx.ps1 -PackagePath .\NetX-0.3.0-win64.zip
|
||||
.\packaging\update_netx.ps1 -PackagePath .\NetX-0.4.0-win64.zip
|
||||
```
|
||||
|
||||
Stops services, replaces program folders (`netx_api`, `web`, `packaging`, `postgres`, …), **keeps** the data root, restarts. Schema migrations still run via Alembic on API start.
|
||||
|
||||
## Auto-update (reserved)
|
||||
Or reinstall a newer `NetX-Setup-*.exe` over the same program directory.
|
||||
|
||||
See `manifest.example.json`. Future: set `NETX_UPDATE_URL` + `NETX_UPDATE_CHANNEL`; a checker will download the zip and call `update_netx.ps1`. Not implemented in this phase.
|
||||
## Check / apply updates
|
||||
|
||||
Default source: latest GitHub Release for `hansjone/netx`. Optional custom manifest via `NETX_UPDATE_URL` (see `manifest.example.json`).
|
||||
|
||||
```powershell
|
||||
# Report only (exit 0 = up to date, 10 = update available)
|
||||
.\packaging\check_update.ps1
|
||||
|
||||
# Download zip + run update_netx.ps1
|
||||
.\packaging\check_update.ps1 -Apply
|
||||
```
|
||||
|
||||
## Tray & autostart
|
||||
|
||||
```powershell
|
||||
# System tray: Start / Stop / Open UI / Check updates
|
||||
.\packaging\netx_tray.ps1 -StartOnLaunch
|
||||
|
||||
# Start tray at Windows logon (current user)
|
||||
.\packaging\install_autostart.ps1
|
||||
# Remove: .\packaging\install_autostart.ps1 -Remove
|
||||
```
|
||||
|
||||
## Layout reminder
|
||||
|
||||
|
|
|
|||
|
|
@ -71,8 +71,9 @@ New-Item -ItemType Directory -Path $packOut -Force | Out-Null
|
|||
Copy-Item -Path (Join-Path $PSScriptRoot "_common.ps1") -Destination $packOut -Force
|
||||
foreach ($name in @(
|
||||
"download_postgres.ps1", "setup_first_run.ps1", "start_netx_app.ps1",
|
||||
"stop_netx_app.ps1", "update_netx.ps1", "build_release.ps1",
|
||||
"README.md", "manifest.example.json"
|
||||
"stop_netx_app.ps1", "update_netx.ps1", "check_update.ps1",
|
||||
"netx_tray.ps1", "install_autostart.ps1", "build_release.ps1",
|
||||
"publish_release.ps1", "README.md", "manifest.example.json"
|
||||
)) {
|
||||
$src = Join-Path $PSScriptRoot $name
|
||||
if (Test-Path $src) { Copy-Item $src (Join-Path $packOut $name) -Force }
|
||||
|
|
@ -104,8 +105,28 @@ if ($CreateVenv) {
|
|||
$py = (Get-Command python -ErrorAction SilentlyContinue)
|
||||
if (-not $py) { throw "python_not_found_for_venv" }
|
||||
& $py.Source -m venv (Join-Path $stage ".venv")
|
||||
& (Join-Path $stage ".venv\Scripts\python.exe") -m pip install --upgrade pip
|
||||
& (Join-Path $stage ".venv\Scripts\python.exe") -m pip install -r (Join-Path $stage "requirements.txt")
|
||||
$venvPy = Join-Path $stage ".venv\Scripts\python.exe"
|
||||
& $venvPy -m pip install --upgrade pip
|
||||
& $venvPy -m pip install -r (Join-Path $stage "requirements.txt")
|
||||
if ($LASTEXITCODE -ne 0) { throw "pip_install_failed" }
|
||||
|
||||
Write-Host "==> Slimming .venv (drop tests / __pycache__ / *.pyc)"
|
||||
$site = Join-Path $stage ".venv\Lib\site-packages"
|
||||
if (Test-Path $site) {
|
||||
Get-ChildItem -Path $site -Recurse -Directory -Force -ErrorAction SilentlyContinue |
|
||||
Where-Object {
|
||||
$_.Name -in @('__pycache__', 'tests', 'test', 'testing', 'Tests') -or
|
||||
$_.FullName -match '\\pandas\\tests(\\|$)' -or
|
||||
$_.FullName -match '\\numpy\\(_*tests|tests)(\\|$)' -or
|
||||
$_.FullName -match '\\scipy\\(_*tests|tests)(\\|$)'
|
||||
} |
|
||||
Sort-Object { $_.FullName.Length } -Descending |
|
||||
ForEach-Object {
|
||||
Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Get-ChildItem -Path $site -Recurse -Include *.pyc,*.pyo -Force -ErrorAction SilentlyContinue |
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "==> Stage ready: $stage" -ForegroundColor Green
|
||||
|
|
|
|||
148
packaging/check_update.ps1
Normal file
148
packaging/check_update.ps1
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
param(
|
||||
[string]$ProgramRoot = "",
|
||||
[string]$DataRoot = "",
|
||||
[string]$UpdateUrl = "",
|
||||
[string]$Channel = "",
|
||||
[switch]$Apply = $false,
|
||||
[switch]$Quiet = $false
|
||||
)
|
||||
|
||||
# Check for a newer NetX Windows package.
|
||||
# Sources (first that works):
|
||||
# 1) -UpdateUrl / NETX_UPDATE_URL → JSON manifest (see manifest.example.json)
|
||||
# 2) GitHub Releases API for hansjone/netx (default)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
. "$PSScriptRoot\_common.ps1"
|
||||
|
||||
$prog = Get-NetxProgramRoot -Override $ProgramRoot
|
||||
$data = Get-NetxDataRoot -ProgramRoot $prog -Override $DataRoot
|
||||
$envPath = Join-Path $data ".env"
|
||||
$map = @{}
|
||||
if (Test-Path $envPath) { $map = Read-DotEnv -Path $envPath }
|
||||
|
||||
if (-not $UpdateUrl) {
|
||||
if ($map["NETX_UPDATE_URL"]) { $UpdateUrl = $map["NETX_UPDATE_URL"] }
|
||||
elseif ($env:NETX_UPDATE_URL) { $UpdateUrl = $env:NETX_UPDATE_URL }
|
||||
}
|
||||
if (-not $Channel) {
|
||||
if ($map["NETX_UPDATE_CHANNEL"]) { $Channel = $map["NETX_UPDATE_CHANNEL"] }
|
||||
elseif ($env:NETX_UPDATE_CHANNEL) { $Channel = $env:NETX_UPDATE_CHANNEL }
|
||||
else { $Channel = "stable" }
|
||||
}
|
||||
|
||||
$current = Get-NetxVersion -ProgramRoot $prog
|
||||
|
||||
function Compare-SemVer {
|
||||
param([string]$A, [string]$B)
|
||||
$pa = @($A.TrimStart('v','V').Split('.') | ForEach-Object { try { [int]$_ } catch { 0 } })
|
||||
$pb = @($B.TrimStart('v','V').Split('.') | ForEach-Object { try { [int]$_ } catch { 0 } })
|
||||
while ($pa.Count -lt 3) { $pa += 0 }
|
||||
while ($pb.Count -lt 3) { $pb += 0 }
|
||||
for ($i = 0; $i -lt 3; $i++) {
|
||||
if ($pa[$i] -lt $pb[$i]) { return -1 }
|
||||
if ($pa[$i] -gt $pb[$i]) { return 1 }
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function Get-ManifestFromUrl {
|
||||
param([string]$Url)
|
||||
$resp = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 30
|
||||
return ($resp.Content | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
function Get-FromGitHubReleases {
|
||||
$api = "https://api.github.com/repos/hansjone/netx/releases/latest"
|
||||
$headers = @{ "User-Agent" = "NetX-UpdateCheck"; "Accept" = "application/vnd.github+json" }
|
||||
$rel = Invoke-RestMethod -Uri $api -Headers $headers -TimeoutSec 30
|
||||
$tag = [string]$rel.tag_name
|
||||
$ver = $tag.TrimStart('v', 'V')
|
||||
$zipAsset = $rel.assets | Where-Object { $_.name -match 'win64\.zip$' } | Select-Object -First 1
|
||||
$setupAsset = $rel.assets | Where-Object { $_.name -match 'Setup-.*\.exe$' } | Select-Object -First 1
|
||||
if (-not $zipAsset) { throw "github_release_missing_zip" }
|
||||
return [pscustomobject]@{
|
||||
channel = "stable"
|
||||
latest = $ver
|
||||
min_compatible = $ver
|
||||
notes_url = [string]$rel.html_url
|
||||
windows = [pscustomobject]@{
|
||||
url = [string]$zipAsset.browser_download_url
|
||||
sha256 = ""
|
||||
size = [int64]$zipAsset.size
|
||||
setup_url = $(if ($setupAsset) { [string]$setupAsset.browser_download_url } else { "" })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "==> Current version: $current"
|
||||
$manifest = $null
|
||||
try {
|
||||
if ($UpdateUrl) {
|
||||
Write-Host "==> Fetching manifest: $UpdateUrl"
|
||||
$manifest = Get-ManifestFromUrl -Url $UpdateUrl
|
||||
if ($manifest.channel -and $Channel -and ($manifest.channel -ne $Channel)) {
|
||||
Write-Host "[WARN] manifest channel=$($manifest.channel) requested=$Channel"
|
||||
}
|
||||
} else {
|
||||
Write-Host "==> Fetching latest from GitHub Releases"
|
||||
$manifest = Get-FromGitHubReleases
|
||||
}
|
||||
} catch {
|
||||
if ($Quiet) { exit 2 }
|
||||
throw "update_check_failed: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
$latest = [string]$manifest.latest
|
||||
$cmp = Compare-SemVer -A $current -B $latest
|
||||
$result = [pscustomobject]@{
|
||||
current = $current
|
||||
latest = $latest
|
||||
update_available = ($cmp -lt 0)
|
||||
download_url = [string]$manifest.windows.url
|
||||
setup_url = $(if ($manifest.windows.setup_url) { [string]$manifest.windows.setup_url } else { "" })
|
||||
notes_url = $(if ($manifest.notes_url) { [string]$manifest.notes_url } else { "" })
|
||||
sha256 = $(if ($manifest.windows.sha256) { [string]$manifest.windows.sha256 } else { "" })
|
||||
}
|
||||
|
||||
if (-not $result.update_available) {
|
||||
Write-Host "==> Up to date (latest=$latest)" -ForegroundColor Green
|
||||
if (-not $Quiet) {
|
||||
$result | ConvertTo-Json -Compress | Write-Output
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "==> Update available: $current -> $latest" -ForegroundColor Cyan
|
||||
if ($result.notes_url) { Write-Host " Notes: $($result.notes_url)" }
|
||||
|
||||
if (-not $Apply) {
|
||||
Write-Host " Download (zip): $($result.download_url)"
|
||||
if ($result.setup_url) { Write-Host " Or install: $($result.setup_url)" }
|
||||
Write-Host " To apply: .\packaging\check_update.ps1 -Apply"
|
||||
$result | ConvertTo-Json -Compress | Write-Output
|
||||
exit 10
|
||||
}
|
||||
|
||||
$dlDir = Join-Path $data "backups\downloads"
|
||||
if (-not (Test-Path $dlDir)) {
|
||||
New-Item -ItemType Directory -Path $dlDir -Force | Out-Null
|
||||
}
|
||||
$zipName = "NetX-$latest-win64.zip"
|
||||
$zipPath = Join-Path $dlDir $zipName
|
||||
Write-Host "==> Downloading $zipName ..."
|
||||
Invoke-WebRequest -Uri $result.download_url -OutFile $zipPath -UseBasicParsing
|
||||
if ($result.sha256 -and $result.sha256 -notmatch 'REPLACE') {
|
||||
$hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
$expect = $result.sha256.ToLowerInvariant()
|
||||
if ($hash -ne $expect) {
|
||||
throw "sha256_mismatch: got $hash expected $expect"
|
||||
}
|
||||
Write-Host "==> SHA256 OK"
|
||||
}
|
||||
|
||||
Write-Host "==> Applying update via update_netx.ps1"
|
||||
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "update_netx.ps1") `
|
||||
-PackagePath $zipPath -ProgramRoot $prog -DataRoot $data
|
||||
Write-Host "==> Update applied to $latest" -ForegroundColor Green
|
||||
exit 0
|
||||
25
packaging/install_autostart.ps1
Normal file
25
packaging/install_autostart.ps1
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
param(
|
||||
[string]$ProgramRoot = "",
|
||||
[switch]$Remove = $false
|
||||
)
|
||||
|
||||
# Register / unregister NetX tray at current-user logon.
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
. "$PSScriptRoot\_common.ps1"
|
||||
|
||||
$prog = Get-NetxProgramRoot -Override $ProgramRoot
|
||||
$tray = Join-Path $PSScriptRoot "netx_tray.ps1"
|
||||
$runKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run"
|
||||
$name = "NetX"
|
||||
|
||||
if ($Remove) {
|
||||
Remove-ItemProperty -Path $runKey -Name $name -ErrorAction SilentlyContinue
|
||||
Write-Host "==> Removed NetX from startup"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$cmd = "powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$tray`" -ProgramRoot `"$prog`" -StartOnLaunch"
|
||||
New-ItemProperty -Path $runKey -Name $name -Value $cmd -PropertyType String -Force | Out-Null
|
||||
Write-Host "==> NetX tray will start at logon"
|
||||
Write-Host " $cmd"
|
||||
|
|
@ -54,15 +54,19 @@ Name: "{commonappdata}\NetX\pgdata"
|
|||
Name: "{commonappdata}\NetX\backups"
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\NetX Tray"; Filename: "powershell.exe"; Parameters: "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ""{app}\packaging\netx_tray.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"" -StartOnLaunch"; WorkingDir: "{app}"
|
||||
Name: "{group}\Start NetX"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\start_netx_app.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"
|
||||
Name: "{group}\Stop NetX"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\stop_netx_app.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"
|
||||
Name: "{group}\Check for updates"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\check_update.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"
|
||||
Name: "{group}\Open NetX UI"; Filename: "http://127.0.0.1:8890/"
|
||||
Name: "{group}\First-time setup"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\setup_first_run.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"
|
||||
Name: "{autodesktop}\Start NetX"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\start_netx_app.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
Name: "{group}\Enable start at logon"; Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\install_autostart.ps1"" -ProgramRoot ""{app}"""; WorkingDir: "{app}"
|
||||
Name: "{autodesktop}\NetX"; Filename: "powershell.exe"; Parameters: "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ""{app}\packaging\netx_tray.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"" -StartOnLaunch"; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\setup_first_run.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"; Flags: postinstall skipifsilent; Tasks: firstrun
|
||||
Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\start_netx_app.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"""; WorkingDir: "{app}"; Description: "Start NetX now"; Flags: postinstall nowait skipifsilent unchecked
|
||||
Filename: "powershell.exe"; Parameters: "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File ""{app}\packaging\netx_tray.ps1"" -ProgramRoot ""{app}"" -DataRoot ""{commonappdata}\NetX"" -StartOnLaunch"; WorkingDir: "{app}"; Description: "Start NetX tray now"; Flags: postinstall nowait skipifsilent unchecked
|
||||
Filename: "powershell.exe"; Parameters: "-ExecutionPolicy Bypass -File ""{app}\packaging\install_autostart.ps1"" -ProgramRoot ""{app}"""; WorkingDir: "{app}"; Description: "Start NetX at Windows logon"; Flags: postinstall skipifsilent unchecked
|
||||
|
||||
[UninstallDelete]
|
||||
; Do NOT delete {commonappdata}\NetX — preserves DB and secrets across reinstall
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
"channel": "stable",
|
||||
"latest": "0.3.0",
|
||||
"min_compatible": "0.3.0",
|
||||
"notes_url": "",
|
||||
"notes_url": "https://github.com/hansjone/netx/releases/tag/v0.3.0",
|
||||
"windows": {
|
||||
"url": "https://example.com/netx/NetX-0.2.0-win64.zip",
|
||||
"sha256": "REPLACE_WITH_SHA256",
|
||||
"url": "https://github.com/hansjone/netx/releases/download/v0.3.0/NetX-0.3.0-win64.zip",
|
||||
"setup_url": "https://github.com/hansjone/netx/releases/download/v0.3.0/NetX-Setup-0.3.0.exe",
|
||||
"sha256": "",
|
||||
"size": 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
133
packaging/netx_tray.ps1
Normal file
133
packaging/netx_tray.ps1
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
param(
|
||||
[string]$ProgramRoot = "",
|
||||
[string]$DataRoot = "",
|
||||
[switch]$StartOnLaunch = $true,
|
||||
[switch]$CheckUpdateOnLaunch = $false
|
||||
)
|
||||
|
||||
# Simple system-tray controller for NetX (Windows packaged installs).
|
||||
# Start / Stop / Open UI / Check update / Exit
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
. "$PSScriptRoot\_common.ps1"
|
||||
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$prog = Get-NetxProgramRoot -Override $ProgramRoot
|
||||
$data = Get-NetxDataRoot -ProgramRoot $prog -Override $DataRoot
|
||||
$hostBind = "127.0.0.1"
|
||||
$port = 8890
|
||||
$envPath = Join-Path $data ".env"
|
||||
if (Test-Path $envPath) {
|
||||
$map = Read-DotEnv -Path $envPath
|
||||
if ($map["NETX_HOST"]) { $hostBind = $map["NETX_HOST"] }
|
||||
if ($map["NETX_PORT"]) { try { $port = [int]$map["NETX_PORT"] } catch {} }
|
||||
}
|
||||
$uiUrl = "http://${hostBind}:${port}/"
|
||||
$ver = Get-NetxVersion -ProgramRoot $prog
|
||||
|
||||
$startPs1 = Join-Path $PSScriptRoot "start_netx_app.ps1"
|
||||
$stopPs1 = Join-Path $PSScriptRoot "stop_netx_app.ps1"
|
||||
$checkPs1 = Join-Path $PSScriptRoot "check_update.ps1"
|
||||
|
||||
function Invoke-NetxScript {
|
||||
param([string]$File, [string[]]$ExtraArgs = @())
|
||||
$args = @(
|
||||
"-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $File,
|
||||
"-ProgramRoot", $prog, "-DataRoot", $data
|
||||
) + $ExtraArgs
|
||||
Start-Process -FilePath "powershell.exe" -ArgumentList $args -WorkingDirectory $prog -WindowStyle Hidden
|
||||
}
|
||||
|
||||
$form = New-Object System.Windows.Forms.Form
|
||||
$form.Text = "NetX"
|
||||
$form.ShowInTaskbar = $false
|
||||
$form.WindowState = "Minimized"
|
||||
$form.Visible = $false
|
||||
$form.Size = New-Object System.Drawing.Size(0, 0)
|
||||
|
||||
$notify = New-Object System.Windows.Forms.NotifyIcon
|
||||
$notify.Text = "NetX $ver"
|
||||
$notify.Visible = $true
|
||||
try {
|
||||
$notify.Icon = [System.Drawing.SystemIcons]::Application
|
||||
} catch {}
|
||||
|
||||
$menu = New-Object System.Windows.Forms.ContextMenuStrip
|
||||
|
||||
$miOpen = $menu.Items.Add("Open UI ($uiUrl)")
|
||||
$miOpen.add_Click({ Start-Process $uiUrl })
|
||||
|
||||
$miStart = $menu.Items.Add("Start NetX")
|
||||
$miStart.add_Click({
|
||||
$notify.ShowBalloonTip(3000, "NetX", "Starting…", [System.Windows.Forms.ToolTipIcon]::Info)
|
||||
Invoke-NetxScript -File $startPs1 -ExtraArgs @("-SkipBrowser")
|
||||
})
|
||||
|
||||
$miStop = $menu.Items.Add("Stop NetX")
|
||||
$miStop.add_Click({
|
||||
$notify.ShowBalloonTip(3000, "NetX", "Stopping…", [System.Windows.Forms.ToolTipIcon]::Info)
|
||||
Invoke-NetxScript -File $stopPs1
|
||||
})
|
||||
|
||||
$miUpdate = $menu.Items.Add("Check for updates")
|
||||
$miUpdate.add_Click({
|
||||
try {
|
||||
$p = Start-Process -FilePath "powershell.exe" -ArgumentList @(
|
||||
"-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $checkPs1,
|
||||
"-ProgramRoot", $prog, "-DataRoot", $data
|
||||
) -Wait -PassThru -WindowStyle Normal
|
||||
if ($p.ExitCode -eq 10) {
|
||||
$ans = [System.Windows.Forms.MessageBox]::Show(
|
||||
"A newer NetX is available. Download and apply now?",
|
||||
"NetX update",
|
||||
[System.Windows.Forms.MessageBoxButtons]::YesNo,
|
||||
[System.Windows.Forms.MessageBoxIcon]::Question
|
||||
)
|
||||
if ($ans -eq [System.Windows.Forms.DialogResult]::Yes) {
|
||||
Start-Process -FilePath "powershell.exe" -ArgumentList @(
|
||||
"-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $checkPs1,
|
||||
"-ProgramRoot", $prog, "-DataRoot", $data, "-Apply"
|
||||
) -WorkingDirectory $prog
|
||||
}
|
||||
} elseif ($p.ExitCode -eq 0) {
|
||||
[System.Windows.Forms.MessageBox]::Show("NetX is up to date ($ver).", "NetX update")
|
||||
}
|
||||
} catch {
|
||||
[System.Windows.Forms.MessageBox]::Show("Update check failed: $($_.Exception.Message)", "NetX")
|
||||
}
|
||||
})
|
||||
|
||||
[void]$menu.Items.Add("-")
|
||||
|
||||
$miExit = $menu.Items.Add("Exit tray (services keep running)")
|
||||
$miExit.add_Click({
|
||||
$notify.Visible = $false
|
||||
$form.Close()
|
||||
[System.Windows.Forms.Application]::Exit()
|
||||
})
|
||||
|
||||
$notify.ContextMenuStrip = $menu
|
||||
$notify.add_DoubleClick({ Start-Process $uiUrl })
|
||||
|
||||
$form.add_Shown({
|
||||
if ($StartOnLaunch) {
|
||||
Invoke-NetxScript -File $startPs1 -ExtraArgs @("-SkipBrowser")
|
||||
Start-Sleep -Seconds 2
|
||||
try { Start-Process $uiUrl } catch {}
|
||||
}
|
||||
if ($CheckUpdateOnLaunch) {
|
||||
Start-Process -FilePath "powershell.exe" -ArgumentList @(
|
||||
"-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $checkPs1,
|
||||
"-ProgramRoot", $prog, "-DataRoot", $data, "-Quiet"
|
||||
) -WindowStyle Hidden
|
||||
}
|
||||
})
|
||||
|
||||
$form.add_FormClosing({
|
||||
$notify.Visible = $false
|
||||
$notify.Dispose()
|
||||
})
|
||||
|
||||
[System.Windows.Forms.Application]::Run($form)
|
||||
Loading…
Add table
Add a link
Reference in a new issue