From 0105719ddc583e8c4563468d154d01dc012c9737 Mon Sep 17 00:00:00 2001
From: xyc <jc_xiong@hotmail.com>
Date: 星期六, 03 十月 2026 13:08:10 +0800
Subject: [PATCH] fix(部署): 修复 install-service.ps1 密码解析崩溃(Trim 参数类型错误)并加 trap 友好报错

---
 HANDOFF.md                                   |    8 ++++
 deploy-templates/backend/install-service.ps1 |   76 +++++++++++++++++++++++++++----------
 2 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/HANDOFF.md b/HANDOFF.md
index d4ab142..3e2bcc5 100644
--- a/HANDOFF.md
+++ b/HANDOFF.md
@@ -52,6 +52,14 @@
   - 鏂板寘锛歚deploy/traffic-audit-deploy-20261003-4/`锛�394 鏂囦欢 / 110.50 MB锛寊ip 83.78 MB锛夆�斺��**褰撳墠鍞竴鍙敤鍖�**銆�
 - **鍙戝竷鍖呮竻鐞嗭紙10-03 鏅氾紝鐢ㄦ埛纭鈥滃彧鐣� -4鈥濓級**锛氬凡鍒犻櫎 `traffic-audit-release-20261002/`(+zip)銆乣traffic-audit-deploy-20261003/`(+zip)銆乣-2/`(+zip)銆乣-3/`(+zip) 鍙婄┖鐨� `server-fix/`锛宍deploy\` 鐜板湪鍙湁 `traffic-audit-deploy-20261003-4/` 鍜屽畠鐨� zip锛堥噴鏀剧害 671MB锛夈��
   > 鍥犳鏈枃浠朵笂闈㈡彁鍒扮殑 `deploy/traffic-audit-deploy-20261003/`锛�388 鏂囦欢锛変笌 `deploy/traffic-audit-release-20261002/` 鍧囦负**鍘嗗彶璁板綍**锛岀鐩樹笂宸蹭笉瀛樺湪锛屽埆鍐嶅幓鎵俱��
+- **绱ф�ヤ慨澶嶏紙10-03 鏅氾級锛歚install-service.ps1` 瀵嗙爜瑙f瀽宕╂簝锛屾湇鍔℃牴鏈病瑁呬笂**
+  - 鐜拌薄锛氱敤鎴峰湪鏈嶅姟鍣紙`D:\trafficAudit`锛夊弻鍑� `install-service.cmd`锛屾姤 `鏃犳硶灏嗏�淭rim鈥濈殑鍙傛暟鈥渢rimChars鈥濊浆鎹负绫诲瀷鈥淪ystem.Char鈥漙锛屼綅缃� `install-service.ps1:210`銆�
+  - 鏍瑰洜锛氶偅琛屾槸 `.Trim(' ''', '"')`锛屽叾涓� `' '''` 琚� PowerShell 瑙f瀽鎴愪竴涓�**闀垮害 2 鐨勫瓧绗︿覆**锛堢┖鏍� + 鍗曞紩鍙凤級锛宍Trim(char[])` 鏃犳硶鎶� 2 瀛楃涓茶浆鎴愬崟涓� char 鈫� 鏁磋鎶涘紓甯革紙`MethodArgumentConversionInvalidCastArgument`锛夈��
+  - 淇锛氭妸杩欐鎶芥垚绾嚱鏁� `Test-AppConfigPassword`锛屾敼鍐欎负 `Trim()` 鈫� `Trim("'")` 鈫� `Trim('"')`锛涘苟鍔犺剼鏈骇 `trap`锛屼换浣曞紓甯稿彧鎵撳嵃涓�琛岃鏄� + 琛屽彿锛屼笉鍐嶇敥绾㈠瓧鍫嗘爤銆�
+  - 楠岃瘉锛�8 涓牱鏈紙缂烘枃浠� / 绌哄�� / 涓枃鍗犱綅绗� / 瑁稿�� / 鍙屽紩鍙� / 鍗曞紩鍙� / 鍚┖鏍肩壒娈婂瓧绗� / 鐪熷疄妯℃澘鏂囦欢锛夊叏閮ㄧ鍚堥鏈燂紱鎵撳寘鍐呰剼鏈娉曡В鏋愰�氳繃銆乣-Status` 瀹炶窇姝e父銆侀潪绠$悊鍛樻椂 trap 杈撳嚭骞插噣閿欒骞� exit 1銆�
+  - 鏁欒锛氳繖鏉″垎鏀箣鍓嶆病琚换浣曟祴璇曡鐩栵紙`-Status` 鎻愬墠 exit銆侀潪绠$悊鍛樺湪 `Assert-Admin` 灏遍��鍑猴級锛屾墍浠ヨВ鏋愮被閫昏緫瑕佹娊鎴愮函鍑芥暟骞剁敤鏍锋湰娴嬨��
+  - 鍖呭悕锛氫慨澶嶇増閲嶆墦鍖呮椂鑴氭湰澶嶇敤浜嗗凡閲婃斁鐨勫熀纭�鍚嶏紝鏈�缁堝凡鍒犳帀鏃у潖鍖呭苟鏀瑰悕锛宍deploy\` 浠嶇劧鏄�**鍞竴**鐨� `traffic-audit-deploy-20261003-4\`锛堝惈淇鍚庣殑 install-service.ps1锛変笌鍚屽悕 zip銆�
+  - 鐢ㄦ埛渚ф渶灏忎慨澶嶏細鍙渶鐢ㄦ柊鍖呴噷鐨� `backend\install-service.ps1` 瑕嗙洊鏈嶅姟鍣� `D:\trafficAudit\install-service.ps1`锛屽啀閲嶈窇 `install-service.cmd`锛堜笉蹇呴噸鎷� 110MB锛夈��
 
 ## 鏈�鏂帮紙2026-10-02锛�
 
diff --git a/deploy-templates/backend/install-service.ps1 b/deploy-templates/backend/install-service.ps1
index 2b8f094..98373d6 100644
--- a/deploy-templates/backend/install-service.ps1
+++ b/deploy-templates/backend/install-service.ps1
@@ -45,6 +45,21 @@
 $appConfig = Join-Path $root 'application.yml'
 $serviceId = 'TrafficAuditBackend'
 
+# Any terminating error below lands here instead of dumping a raw stack trace
+# at the operator. The line number is kept so a copy of this window is enough
+# to diagnose a report.
+trap {
+  Write-Host ''
+  Write-Host '=============================================================='
+  Write-Host ' ERROR: the installer stopped before finishing.'
+  Write-Host ('        ' + $_.Exception.Message)
+  Write-Host ('        at line ' + $_.InvocationInfo.ScriptLineNumber + ' of install-service.ps1')
+  Write-Host ' The service may not be installed. Send this window text to the'
+  Write-Host ' developer if the reason is not obvious.'
+  Write-Host '=============================================================='
+  exit 1
+}
+
 function Assert-Admin {
   $identity  = [Security.Principal.WindowsIdentity]::GetCurrent()
   $principal = New-Object Security.Principal.WindowsPrincipal($identity)
@@ -146,6 +161,45 @@
   }
 }
 
+function Test-AppConfigPassword {
+  param([string]$Path)
+
+  # Returns $true when the datasource password looks usable. Prints a WARN and
+  # returns $false for the states that break startup with
+  # "Access denied ... (using password: NO)": missing file / empty value / placeholder.
+  if (-not (Test-Path -LiteralPath $Path)) {
+    Write-Host 'WARN: application.yml is missing next to the jar.'
+    Write-Host '      The built-in password placeholder resolves to an empty string and startup will fail with'
+    Write-Host "      Java SQLException: Access denied for user 'root'@'localhost' (using password: NO)."
+    return $false
+  }
+
+  $line = Select-String -LiteralPath $Path -Pattern '^\s*password\s*:' | Select-Object -First 1
+  if (-not $line) {
+    Write-Host "WARN: no 'password:' entry found in application.yml; check the datasource block."
+    return $false
+  }
+
+  # Trim() takes a single char, so strip whitespace, then one quote kind at a
+  # time. Passing a 2-char string here throws
+  # "cannot convert value ... to type System.Char" and aborts the script.
+  $value = $line.Line -replace '^\s*password\s*:\s*', ''
+  $value = $value.Trim()
+  $value = $value.Trim("'")
+  $value = $value.Trim('"')
+
+  if ($value -eq '') {
+    Write-Host "WARN: spring.datasource.password is empty in application.yml; startup may fail with '(using password: NO)'."
+    return $false
+  }
+  if ($value -match '[^\x00-\x7F]') {
+    Write-Host 'WARN: the datasource password contains non-ASCII characters.'
+    Write-Host '      If it is still the Chinese placeholder text, replace it with the real MySQL password first.'
+    return $false
+  }
+  return $true
+}
+
 # ---------- read-only status: no elevation needed ----------
 if ($Status) {
   $service = Get-ServiceState
@@ -197,27 +251,7 @@
 if (-not (Test-Path $wrapper)) {
   throw "Missing wrapper executable: $wrapper`nRebuild the deploy package with pack-deploy.ps1 (it provides WinSW), or copy WinSW-x64.exe here renamed to trafficAudit.exe."
 }
-$passwordOk = $false
-if (-not (Test-Path $appConfig)) {
-  Write-Host "WARN: application.yml is missing next to the jar."
-  Write-Host "      The built-in password placeholder resolves to an empty string and startup will fail with"
-  Write-Host "      Java SQLException: Access denied for user 'root'@'localhost' (using password: NO)."
-} else {
-  $line = Select-String -LiteralPath $appConfig -Pattern '^\s*password\s*:' | Select-Object -First 1
-  if (-not $line) {
-    Write-Host "WARN: no 'password:' entry found in application.yml; check the datasource block."
-  } else {
-    $value = ($line.Line -replace '^\s*password\s*:\s*', '').Trim(' ''', '"')
-    if ($value -eq '') {
-      Write-Host "WARN: spring.datasource.password is empty in application.yml; startup may fail with '(using password: NO)'."
-    } elseif ($value -match '[^\x00-\x7F]') {
-      Write-Host "WARN: the datasource password contains non-ASCII characters."
-      Write-Host "      If it is still the Chinese placeholder text, replace it with the real MySQL password first."
-    } else {
-      $passwordOk = $true
-    }
-  }
-}
+$passwordOk = Test-AppConfigPassword -Path $appConfig
 
 $java = Resolve-JavaPath -Explicit $JavaPath
 Set-WrapperJavaPath -JavaExe $java

--
Gitblit v1.9.1