mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 03:10:46 +08:00
Fix Windows PowerShell parsing on Server 2012: UTF-8 BOM scripts.
Chinese packaging scripts without BOM were misread as ANSI and failed at first-run. Document that bundled Python 3.13+ needs Server 2016+ / Win10+. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
8c35922432
commit
41ab4921a0
24 changed files with 48 additions and 28 deletions
|
|
@ -21,6 +21,8 @@ This directory builds a Windows deliverable with:
|
||||||
|
|
||||||
**Offline:** Setup ships portable PostgreSQL, `.venv` (when built with `-CreateVenv`), and WinSW. First-run uses `-NonInteractive -DbMode bundled` — **no GitHub/EDB download on the target PC**. Service install uses bundled WinSW (pass `-AllowDownload` only on a build/dev machine if the binary is missing). Auto-update still needs network later, and is unchecked by default.
|
**Offline:** Setup ships portable PostgreSQL, `.venv` (when built with `-CreateVenv`), and WinSW. First-run uses `-NonInteractive -DbMode bundled` — **no GitHub/EDB download on the target PC**. Service install uses bundled WinSW (pass `-AllowDownload` only on a build/dev machine if the binary is missing). Auto-update still needs network later, and is unchecked by default.
|
||||||
|
|
||||||
|
**OS:** Windows 10/11 or Windows Server **2016+** recommended. Packaging scripts are UTF-8 **with BOM** so Chinese UI works on Windows PowerShell 5.x. Bundled Python in current releases is **3.13+**, which does **not** support Windows Server 2012 R2 — use Server 2016+ or a newer desktop OS.
|
||||||
|
|
||||||
## Build (developer machine)
|
## Build (developer machine)
|
||||||
|
|
||||||
Prerequisites: Python 3.11+, Node 20+, PowerShell, network (to download PG binaries once).
|
Prerequisites: Python 3.11+, Node 20+, PowerShell, network (to download PG binaries once).
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Shared path helpers for Windows packaging scripts.
|
# Shared path helpers for Windows packaging scripts.
|
||||||
# Dot-source: . "$PSScriptRoot\_common.ps1"
|
# Dot-source: . "$PSScriptRoot\_common.ps1"
|
||||||
|
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$Version = "",
|
[string]$Version = "",
|
||||||
[string]$OutDir = "",
|
[string]$OutDir = "",
|
||||||
[switch]$SkipWebBuild = $false,
|
[switch]$SkipWebBuild = $false,
|
||||||
|
|
@ -80,6 +80,22 @@ $webOut = Join-Path $stage "web\dist"
|
||||||
New-Item -ItemType Directory -Path (Split-Path $webOut -Parent) -Force | Out-Null
|
New-Item -ItemType Directory -Path (Split-Path $webOut -Parent) -Force | Out-Null
|
||||||
Copy-Item -Path $dist -Destination $webOut -Recurse -Force
|
Copy-Item -Path $dist -Destination $webOut -Recurse -Force
|
||||||
|
|
||||||
|
function Write-Utf8BomFile {
|
||||||
|
param([string]$Path)
|
||||||
|
# Windows PowerShell 4/5 (Server 2012+) mis-parses UTF-8 without BOM when scripts contain CJK.
|
||||||
|
$utf8Bom = New-Object System.Text.UTF8Encoding $true
|
||||||
|
$bytes = [IO.File]::ReadAllBytes($Path)
|
||||||
|
$hasBom = ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF)
|
||||||
|
$text = if ($hasBom) {
|
||||||
|
[Text.Encoding]::UTF8.GetString($bytes, 3, $bytes.Length - 3)
|
||||||
|
} else {
|
||||||
|
[Text.Encoding]::UTF8.GetString($bytes)
|
||||||
|
}
|
||||||
|
$text = $text -replace "`r`n", "`n" -replace "`n", "`r`n"
|
||||||
|
if (-not $text.EndsWith("`r`n")) { $text += "`r`n" }
|
||||||
|
[IO.File]::WriteAllText($Path, $text, $utf8Bom)
|
||||||
|
}
|
||||||
|
|
||||||
$packOut = Join-Path $stage "packaging"
|
$packOut = Join-Path $stage "packaging"
|
||||||
New-Item -ItemType Directory -Path $packOut -Force | Out-Null
|
New-Item -ItemType Directory -Path $packOut -Force | Out-Null
|
||||||
Copy-Item -Path (Join-Path $PSScriptRoot "_common.ps1") -Destination $packOut -Force
|
Copy-Item -Path (Join-Path $PSScriptRoot "_common.ps1") -Destination $packOut -Force
|
||||||
|
|
@ -87,13 +103,15 @@ foreach ($name in @(
|
||||||
"download_postgres.ps1", "setup_first_run.ps1", "start_netx_app.ps1",
|
"download_postgres.ps1", "setup_first_run.ps1", "start_netx_app.ps1",
|
||||||
"stop_netx_app.ps1", "update_netx.ps1", "check_update.ps1",
|
"stop_netx_app.ps1", "update_netx.ps1", "check_update.ps1",
|
||||||
"launch_shortcut.ps1", "netx_tray.ps1", "install_autostart.ps1", "install_service.ps1",
|
"launch_shortcut.ps1", "netx_tray.ps1", "install_autostart.ps1", "install_service.ps1",
|
||||||
|
|
||||||
"service_run.ps1", "install_update_task.ps1", "sign_release.ps1",
|
"service_run.ps1", "install_update_task.ps1", "sign_release.ps1",
|
||||||
"build_release.ps1", "publish_release.ps1", "publish_forgejo_release.ps1", "README.md", "manifest.example.json"
|
"build_release.ps1", "publish_release.ps1", "publish_forgejo_release.ps1", "README.md", "manifest.example.json"
|
||||||
)) {
|
)) {
|
||||||
$src = Join-Path $PSScriptRoot $name
|
$src = Join-Path $PSScriptRoot $name
|
||||||
if (Test-Path $src) { Copy-Item $src (Join-Path $packOut $name) -Force }
|
if (Test-Path $src) { Copy-Item $src (Join-Path $packOut $name) -Force }
|
||||||
}
|
}
|
||||||
|
Get-ChildItem -Path $packOut -Filter *.ps1 -File | ForEach-Object { Write-Utf8BomFile -Path $_.FullName }
|
||||||
|
Get-ChildItem -Path (Join-Path $stage "scripts") -Filter *.ps1 -File -ErrorAction SilentlyContinue |
|
||||||
|
ForEach-Object { Write-Utf8BomFile -Path $_.FullName }
|
||||||
Copy-Item -Path (Join-Path $PSScriptRoot "config") -Destination (Join-Path $packOut "config") -Recurse -Force
|
Copy-Item -Path (Join-Path $PSScriptRoot "config") -Destination (Join-Path $packOut "config") -Recurse -Force
|
||||||
Copy-Item -Path (Join-Path $PSScriptRoot "installer") -Destination (Join-Path $packOut "installer") -Recurse -Force
|
Copy-Item -Path (Join-Path $PSScriptRoot "installer") -Destination (Join-Path $packOut "installer") -Recurse -Force
|
||||||
$assetsSrc = Join-Path $PSScriptRoot "assets"
|
$assetsSrc = Join-Path $PSScriptRoot "assets"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[string]$UpdateUrl = "",
|
[string]$UpdateUrl = "",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$Version = "16.4-1",
|
[string]$Version = "16.4-1",
|
||||||
[string]$OutDir = ""
|
[string]$OutDir = ""
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[switch]$Remove = $false
|
[switch]$Remove = $false
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[ValidateSet("winsw", "task")]
|
[ValidateSet("winsw", "task")]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[ValidateSet("Daily", "AtLogOn", "Hourly")]
|
[ValidateSet("Daily", "AtLogOn", "Hourly")]
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#define MyAppName "NetX"
|
#define MyAppName "NetX"
|
||||||
#ifndef MyAppVersion
|
#ifndef MyAppVersion
|
||||||
#define MyAppVersion "0.4.2"
|
#define MyAppVersion "0.4.3"
|
||||||
#endif
|
#endif
|
||||||
#define MyAppPublisher "NetX"
|
#define MyAppPublisher "NetX"
|
||||||
#define MyAppURL "https://github.com/hansjone/netx"
|
#define MyAppURL "https://github.com/hansjone/netx"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[ValidateSet("tray", "start", "stop", "setup", "update")]
|
[ValidateSet("tray", "start", "stop", "setup", "update")]
|
||||||
[string]$Action = "tray",
|
[string]$Action = "tray",
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"channel": "stable",
|
"channel": "stable",
|
||||||
"latest": "0.4.2",
|
"latest": "0.4.3",
|
||||||
"min_compatible": "0.3.0",
|
"min_compatible": "0.3.0",
|
||||||
"notes_url": "https://github.com/hansjone/netx/releases/tag/v0.4.2",
|
"notes_url": "https://github.com/hansjone/netx/releases/tag/v0.4.3",
|
||||||
"windows": {
|
"windows": {
|
||||||
"url": "https://github.com/hansjone/netx/releases/download/v0.4.2/NetX-0.4.2-win64.zip",
|
"url": "https://github.com/hansjone/netx/releases/download/v0.4.3/NetX-0.4.3-win64.zip",
|
||||||
"setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.2/NetX-Setup-0.4.2.exe",
|
"setup_url": "https://github.com/hansjone/netx/releases/download/v0.4.3/NetX-Setup-0.4.3.exe",
|
||||||
"sha256": "",
|
"sha256": "",
|
||||||
"size": 0
|
"size": 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[switch]$StartOnLaunch = $true,
|
[switch]$StartOnLaunch = $true,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$Version = "",
|
[string]$Version = "",
|
||||||
[string]$ForgejoBase = "http://10.0.0.131:3000",
|
[string]$ForgejoBase = "http://10.0.0.131:3000",
|
||||||
[string]$Owner = "hansjone",
|
[string]$Owner = "hansjone",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$Version = "",
|
[string]$Version = "",
|
||||||
[switch]$SkipBuild = $false,
|
[switch]$SkipBuild = $false,
|
||||||
[switch]$SkipInstaller = $false,
|
[switch]$SkipInstaller = $false,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[int]$HealthFailLimit = 6,
|
[int]$HealthFailLimit = 6,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[ValidateSet("bundled", "external", "")]
|
[ValidateSet("bundled", "external", "")]
|
||||||
[string]$DbMode = "",
|
[string]$DbMode = "",
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string[]]$Files,
|
[string[]]$Files,
|
||||||
[string]$Thumbprint = "",
|
[string]$Thumbprint = "",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[switch]$SkipBrowser = $false,
|
[switch]$SkipBrowser = $false,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
[string]$DataRoot = "",
|
[string]$DataRoot = "",
|
||||||
[switch]$KeepPostgres = $false
|
[switch]$KeepPostgres = $false
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$PackagePath,
|
[string]$PackagePath,
|
||||||
[string]$ProgramRoot = "",
|
[string]$ProgramRoot = "",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netx-ops"
|
name = "netx-ops"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
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"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$PgHost = "127.0.0.1",
|
[string]$PgHost = "127.0.0.1",
|
||||||
[int]$PgPort = 5432,
|
[int]$PgPort = 5432,
|
||||||
[string]$SuperUser = "postgres",
|
[string]$SuperUser = "postgres",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[string]$BindHost = "127.0.0.1",
|
[string]$BindHost = "127.0.0.1",
|
||||||
[int]$Port = 8890,
|
[int]$Port = 8890,
|
||||||
[int]$WebPort = 5173,
|
[int]$WebPort = 5173,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
param(
|
param(
|
||||||
[int]$Port = 8890,
|
[int]$Port = 8890,
|
||||||
[int]$WebPort = 5173,
|
[int]$WebPort = 5173,
|
||||||
# Windows often ignores graceful Stop-Process on python; default hard-kill.
|
# Windows often ignores graceful Stop-Process on python; default hard-kill.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue