Release 0.4.9: update console exits cleanly; tray refreshes version.

Start NetX in-process after apply (no nested Wait hang) and reload version.json in the tray tip/menu.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-10-07 17:54:37 +08:00
parent 66f9fa9782
commit e14f983aeb
6 changed files with 45 additions and 26 deletions

View file

@ -5,7 +5,7 @@
#define MyAppName "NetX" #define MyAppName "NetX"
#ifndef MyAppVersion #ifndef MyAppVersion
#define MyAppVersion "0.4.8" #define MyAppVersion "0.4.9"
#endif #endif
#define MyAppPublisher "NetX" #define MyAppPublisher "NetX"
#define MyAppURL "https://github.com/hansjone/netx" #define MyAppURL "https://github.com/hansjone/netx"

View file

@ -1,11 +1,11 @@
{ {
"channel": "stable", "channel": "stable",
"latest": "0.4.8", "latest": "0.4.9",
"min_compatible": "0.3.0", "min_compatible": "0.3.0",
"notes_url": "https://github.com/hansjone/netx/releases/tag/v0.4.8", "notes_url": "https://github.com/hansjone/netx/releases/tag/v0.4.9",
"windows": { "windows": {
"url": "https://github.com/hansjone/netx/releases/download/v0.4.8/NetX-0.4.8-win64.zip", "url": "https://github.com/hansjone/netx/releases/download/v0.4.9/NetX-0.4.9-win64.zip",
"setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.8/NetX-Setup-0.4.8.exe", "setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.9/NetX-Setup-0.4.9.exe",
"sha256": "", "sha256": "",
"size": 0 "size": 0
} }

View file

@ -101,7 +101,8 @@ if ($autoVal -match '^(1|true|yes|on)$') {
$CheckUpdateOnLaunch = $true $CheckUpdateOnLaunch = $true
} }
$uiUrl = "http://${hostBind}:${port}/" $uiUrl = "http://${hostBind}:${port}/"
$ver = Get-NetxVersion -ProgramRoot $prog $script:ver = Get-NetxVersion -ProgramRoot $prog
$ver = $script:ver
$dbMode = Get-DbMode -EnvMap $map $dbMode = Get-DbMode -EnvMap $map
$dbModeLabel = if ($dbMode -eq "bundled") { $dbModeLabel = if ($dbMode -eq "bundled") {
if (([cultureinfo]::CurrentUICulture.Name -match '^(zh|zh-)')) { "内置库" } else { "built-in DB" } if (([cultureinfo]::CurrentUICulture.Name -match '^(zh|zh-)')) { "内置库" } else { "built-in DB" }
@ -160,16 +161,25 @@ function Invoke-NetxScript {
} }
function Update-NetxTrayTip { function Update-NetxTrayTip {
# Refresh version after in-place updates (tray process may outlive version.json).
try {
$nowVer = Get-NetxVersion -ProgramRoot $prog
if ($nowVer -and $nowVer -ne $script:ver) {
$script:ver = $nowVer
if ($null -ne $script:miHeader) { $script:miHeader.Text = "NetX $script:ver" }
}
} catch {}
$running = Test-NetxApiHealthy -HostName $hostBind -Port $port -TimeoutSec 1 $running = Test-NetxApiHealthy -HostName $hostBind -Port $port -TimeoutSec 1
$state = if ($running) { $state = if ($running) {
(T "Running" "运行中") (T "Running" "运行中")
} else { } else {
(T "Stopped" "已停止") (T "Stopped" "已停止")
} }
$tip = "NetX $ver · $state · $dbModeLabel`n$uiUrl" $v = $script:ver
$tip = "NetX $v · $state · $dbModeLabel`n$uiUrl"
if ($tip.Length -gt 63) { if ($tip.Length -gt 63) {
# NotifyIcon.Text max ~63 chars on older Windows. # NotifyIcon.Text max ~63 chars on older Windows.
$tip = "NetX $ver · $state · $dbModeLabel" $tip = "NetX $v · $state · $dbModeLabel"
} }
$notify.Text = $tip $notify.Text = $tip
} }
@ -297,7 +307,8 @@ $menu.Padding = New-Object System.Windows.Forms.Padding(4, 4, 4, 4)
$menu.Renderer = New-Object NetxMenuRenderer $menu.Renderer = New-Object NetxMenuRenderer
# --- header (info only) --- # --- header (info only) ---
$miHeader = New-NetxMenuItem -Text "NetX $ver" -Header $script:miHeader = New-NetxMenuItem -Text "NetX $script:ver" -Header
$miHeader = $script:miHeader
[void]$menu.Items.Add($miHeader) [void]$menu.Items.Add($miHeader)
$miSub = New-NetxMenuItem -Text "$dbModeLabel · ${hostBind}:$port" -Muted $miSub = New-NetxMenuItem -Text "$dbModeLabel · ${hostBind}:$port" -Muted
@ -478,10 +489,11 @@ $miUpdate.add_Click({
-WorkingDirectory $prog -WindowStyle Normal -Verb RunAs -Wait -PassThru -WorkingDirectory $prog -WindowStyle Normal -Verb RunAs -Wait -PassThru
$newVer = Get-NetxVersion -ProgramRoot $prog $newVer = Get-NetxVersion -ProgramRoot $prog
if ($null -ne $ap.ExitCode -and $ap.ExitCode -eq 0) { if ($null -ne $ap.ExitCode -and $ap.ExitCode -eq 0) {
$script:ver = $newVer
$ver = $newVer $ver = $newVer
$miHeader.Text = "NetX $ver" if ($script:miHeader) { $script:miHeader.Text = "NetX $script:ver" }
[System.Windows.Forms.MessageBox]::Show( [System.Windows.Forms.MessageBox]::Show(
(T "Updated to $ver. Restart the tray if the menu still shows the old version." "已更新到 $ver。若菜单仍显示旧版本,请退出托盘后重新打开。"), (T "Updated to $script:ver." "已更新到 $script:ver。"),
(T "NetX update" "NetX 更新"), (T "NetX update" "NetX 更新"),
[System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information [System.Windows.Forms.MessageBoxIcon]::Information

View file

@ -1,4 +1,4 @@
param( param(
[string]$ProgramRoot = "", [string]$ProgramRoot = "",
[string]$DataRoot = "", [string]$DataRoot = "",
[switch]$SkipBrowser = $false, [switch]$SkipBrowser = $false,
@ -118,21 +118,25 @@ if (-not (Test-Path $startScript)) {
throw "start_netx.ps1 not found at $startScript" throw "start_netx.ps1 not found at $startScript"
} }
$startExtra = @(
"-SkipInstall", "-Background",
"-BindHost", $hostBind, "-Port", "$port"
)
if ($InlineSchedulers) { $startExtra += "-InlineSchedulers" }
Write-Host "==> Starting NetX (API + workers; UI via API on :$port)" Write-Host "==> Starting NetX (API + workers; UI via API on :$port)"
$startProc = Start-NetxPowerShell -File $startScript -Arguments $startExtra ` # Run in-process with -Background so this console exits after /health (nested
-WorkingDirectory $prog -WindowStyle Hidden -Wait -PassThru # Start-Process -Wait on a Hidden child often never returns under UAC update).
if ($startProc.ExitCode -ne 0) { exit $startProc.ExitCode } $startArgs = @{
SkipInstall = $true
Background = $true
BindHost = $hostBind
Port = $port
}
if ($InlineSchedulers) { $startArgs["InlineSchedulers"] = $true }
& $startScript @startArgs
if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$url = "http://${hostBind}:${port}/" $url = "http://${hostBind}:${port}/"
if (-not (Wait-NetxApiHealthy -HostName $hostBind -Port $port -TimeoutSec 30)) { if (-not (Test-NetxApiHealthy -HostName $hostBind -Port $port -TimeoutSec 2)) {
Write-Host "[ERR] NetX process exited 0 but /health not ready: $url" -ForegroundColor Red if (-not (Wait-NetxApiHealthy -HostName $hostBind -Port $port -TimeoutSec 30)) {
exit 1 Write-Host "[ERR] NetX started but /health not ready: $url" -ForegroundColor Red
exit 1
}
} }
Write-Host "==> Open: $url" -ForegroundColor Green Write-Host "==> Open: $url" -ForegroundColor Green
if (-not $SkipBrowser) { if (-not $SkipBrowser) {

View file

@ -130,9 +130,12 @@ try {
Write-Host "==> Update files applied" -ForegroundColor Green Write-Host "==> Update files applied" -ForegroundColor Green
if (-not $NoStart) { if (-not $NoStart) {
& powershell -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot "start_netx_app.ps1") ` # Same process (no nested powershell) so the update console can exit cleanly.
& (Join-Path $PSScriptRoot "start_netx_app.ps1") `
-ProgramRoot $prog -DataRoot $data -SkipBrowser -ProgramRoot $prog -DataRoot $data -SkipBrowser
if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
} }
Write-Host "==> Update complete. You can close this window." -ForegroundColor Green
} finally { } finally {
if (Test-Path $work) { if (Test-Path $work) {
Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue Remove-Item -Recurse -Force $work -ErrorAction SilentlyContinue

View file

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "netx-ops" name = "netx-ops"
version = "0.4.8" version = "0.4.9"
description = "netx operations tool: alarm-centric workflows with REST API and stdio MCP" description = "netx operations tool: alarm-centric workflows with REST API and stdio MCP"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"