panrouter 2.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.mjs CHANGED
@@ -1,9 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- /**
4
- * Pan Router CLI — 一键安装 + 启动
5
- */
6
-
7
3
  import { execSync, spawn } from "node:child_process";
8
4
  import http from "node:http";
9
5
  import fs from "node:fs";
@@ -14,7 +10,6 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
10
  const HOME = process.env.USERPROFILE || process.env.HOME;
15
11
  const CLAUDE_DIR = path.join(HOME, ".claude");
16
12
  const SETTINGS_PATH = path.join(CLAUDE_DIR, "settings.json");
17
- const BACKUP_PATH = path.join(CLAUDE_DIR, "settings.json.panrouter.backup");
18
13
 
19
14
  function log(label, msg, color = "") {
20
15
  const colors = { green: "\x1b[32m", yellow: "\x1b[33m", red: "\x1b[31m", cyan: "\x1b[36m", reset: "\x1b[0m" };
@@ -22,46 +17,28 @@ function log(label, msg, color = "") {
22
17
  console.log(`${c}[${label}]${colors.reset} ${msg}`);
23
18
  }
24
19
 
25
- function run(cmd) {
26
- try {
27
- execSync(cmd, { stdio: "inherit" });
28
- return true;
29
- } catch {
30
- return false;
31
- }
32
- }
33
-
34
- function runSilent(cmd) {
35
- try {
36
- execSync(cmd, { stdio: "pipe" });
37
- return true;
38
- } catch {
39
- return false;
40
- }
41
- }
42
-
43
- // ─── 1. 安装与配置 ──────────────────────────────────────────
44
-
45
20
  function installClaudeCode() {
46
21
  log("..", "正在检查 Claude Code...", "yellow");
47
- if (runSilent("claude --version")) {
22
+ try {
23
+ execSync("claude --version", { stdio: "pipe" });
48
24
  log("OK", "Claude Code 已就绪", "green");
49
25
  return true;
26
+ } catch {
27
+ log("..", "正在安装 Claude Code...", "yellow");
28
+ try {
29
+ execSync("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
30
+ log("OK", "Claude Code 安装成功", "green");
31
+ return true;
32
+ } catch {
33
+ log("!!", "Claude Code 安装失败", "red");
34
+ return false;
35
+ }
50
36
  }
51
- log("..", "正在安装 Claude Code...", "yellow");
52
- if (!run("npm install -g @anthropic-ai/claude-code")) {
53
- log("!!", "Claude Code 安装失败", "red");
54
- return false;
55
- }
56
- log("OK", "Claude Code 安装成功", "green");
57
- return true;
58
37
  }
59
38
 
60
39
  function writeConfig() {
61
- log("..", "正在写入配置...", "yellow");
40
+ log("..", "正在配置 Claude Code 路由...", "yellow");
62
41
  if (!fs.existsSync(CLAUDE_DIR)) fs.mkdirSync(CLAUDE_DIR, { recursive: true });
63
- if (fs.existsSync(SETTINGS_PATH)) fs.copyFileSync(SETTINGS_PATH, BACKUP_PATH);
64
-
65
42
  const config = {
66
43
  env: {
67
44
  ANTHROPIC_BASE_URL: "http://127.0.0.1:50816",
@@ -73,7 +50,7 @@ function writeConfig() {
73
50
  hasCompletedOnboarding: true,
74
51
  };
75
52
  fs.writeFileSync(SETTINGS_PATH, JSON.stringify(config, null, 2), "utf-8");
76
- log("OK", "配置文件已写入", "green");
53
+ log("OK", "配置完成", "green");
77
54
  }
78
55
 
79
56
  async function isPortOpen() {
@@ -85,8 +62,6 @@ async function isPortOpen() {
85
62
  });
86
63
  }
87
64
 
88
- // ─── 2. 启动服务(前台黑框) ────────────────────────────────
89
-
90
65
  async function startServer() {
91
66
  const serverPath = path.join(__dirname, "server.mjs");
92
67
  try {
@@ -97,111 +72,94 @@ async function startServer() {
97
72
  }
98
73
  } catch {}
99
74
 
100
- log("..", "正在启动 Pan Router(端口 50816)...", "yellow");
75
+ log("..", "正在启动代理...", "yellow");
101
76
  if (process.platform === "win32") {
102
77
  execSync(`start "Pan Router" cmd /c "node ${serverPath} & pause"`, { stdio: "pipe" });
103
78
  } else {
104
- const child = spawn("node", [serverPath], { cwd: __dirname, stdio: "ignore", detached: true });
105
- child.unref();
79
+ spawn("node", [serverPath], { cwd: __dirname, stdio: "ignore", detached: true }).unref();
106
80
  }
107
81
 
108
82
  for (let i = 0; i < 15; i++) {
109
83
  if (await isPortOpen()) break;
110
84
  await new Promise(rs => setTimeout(rs, 1000));
111
85
  }
112
- log("OK", "Pan Router 已启动!现在可以运行 claude ", "green");
86
+ log("OK", "Pan Router 运行中,可以执行 claude 命令了", "green");
113
87
  }
114
88
 
115
- // ─── 3. 托盘模式(后台静默) ────────────────────────────────
116
-
117
89
  async function startTray() {
118
90
  const serverPath = path.join(__dirname, "server.mjs");
119
- const vbsPath = path.join(__dirname, "panrouter-tray.vbs");
91
+ const psPath = path.join(__dirname, "tray-daemon.ps1");
92
+ log("..", "正在后台启动代理...", "yellow");
120
93
 
121
- log("..", "正在启动代理并加载托盘...", "yellow");
94
+ // 1. 由主程序直接启动 Node 代理,彻底杜绝 PowerShell 启动慢导致的超时
95
+ try {
96
+ if (process.platform === "win32") {
97
+ execSync('taskkill /f /fi "WINDOWTITLE eq Pan Router*" >nul 2>&1', { stdio: "pipe" });
98
+ }
99
+ } catch {}
122
100
 
123
- // 【核心修复1】:由 Node 主进程直接启动 Server,确保 API 百分百可用
124
101
  const srv = spawn(process.execPath, [serverPath], {
125
- cwd: __dirname,
126
- stdio: "ignore",
127
- detached: true,
128
- windowsHide: true
102
+ cwd: __dirname,
103
+ stdio: "ignore",
104
+ windowsHide: true,
105
+ detached: true
129
106
  });
130
107
  srv.unref();
131
108
 
132
- // 【核心修复2】:将 Node 的绝对路径通过环境变量塞给 VBS/PowerShell
133
- process.env.PANROUTER_NODE_PATH = process.execPath;
134
-
135
- // 启动托盘 UI
136
- if (fs.existsSync(vbsPath)) {
137
- const tray = spawn("wscript.exe", ["//B", "//NoLogo", vbsPath], {
138
- cwd: __dirname,
139
- stdio: "ignore",
140
- windowsHide: true,
141
- detached: true,
142
- env: process.env // 传递环境变量
143
- });
144
- tray.unref();
145
- }
146
-
147
- // 验证端口
109
+ // 2. 验证端口(由于是直接用 Node 启动,这步通常 1 秒内就会通过)
148
110
  let ok = false;
149
111
  for (let i = 0; i < 15; i++) {
150
- if (await isPortOpen()) { ok = true; break; }
112
+ if (await isPortOpen()) {
113
+ ok = true;
114
+ break;
115
+ }
151
116
  await new Promise(rs => setTimeout(rs, 1000));
152
117
  }
153
118
 
154
119
  if (ok) {
155
- log("OK", "Pan Router 代理已在后台运行 (端口: 50816)", "green");
156
- console.log(" 托盘图标应该已出现。如果系统原因导致图标没出来,代理依然可用。");
120
+ log("OK", "代理服务已就绪!(端口 50816)", "green");
157
121
  } else {
158
- log("!!", "代理启动超时,请检查端口 50816 是否被占用", "red");
122
+ log("!!", "服务启动超时,但仍将尝试加载托盘", "red");
159
123
  }
160
- }
161
124
 
162
- // ─── 主流程 ──────────────────────────────────────────────────
125
+ // 3. 独立拉起系统托盘
126
+ log("..", "正在加载系统托盘...", "yellow");
127
+ const tray = spawn("powershell.exe", [
128
+ "-NoProfile",
129
+ "-ExecutionPolicy", "Bypass",
130
+ "-WindowStyle", "Hidden",
131
+ "-File", psPath
132
+ ], {
133
+ cwd: __dirname,
134
+ stdio: "ignore",
135
+ windowsHide: true,
136
+ detached: true,
137
+ env: { ...process.env, PANROUTER_NODE: process.execPath }
138
+ });
139
+ tray.unref();
163
140
 
164
- function printBanner() {
165
- console.log(`\n\x1b[36m=== Pan Router - Claude Code 代理 ===\x1b[0m\n`);
141
+ console.log(" API 代理已立即可用。托盘图标稍后将在右下角显示。");
166
142
  }
167
143
 
168
144
  async function main() {
169
145
  const args = process.argv.slice(2);
170
-
171
146
  if (args.includes("--help") || args.includes("-h")) {
172
147
  console.log("用法:\n panrouter --server (带命令行窗口运行)\n panrouter --tray (后台隐藏运行 + 托盘)\n panrouter --tray-install (安装配置 + 托盘)");
173
148
  return;
174
149
  }
175
150
 
176
- if (args.includes("--install") || args.includes("-i")) {
177
- printBanner();
178
- if (!installClaudeCode()) process.exit(1);
179
- writeConfig();
180
- return;
181
- }
151
+ if (args.includes("--server") || args.includes("-s")) { await startServer(); return; }
152
+ if (args.includes("--tray") || args.includes("-t")) { await startTray(); return; }
182
153
 
183
- if (args.includes("--server") || args.includes("-s")) {
184
- await startServer();
185
- return;
186
- }
187
-
188
- if (args.includes("--tray") || args.includes("-t")) {
189
- await startTray();
190
- return;
191
- }
154
+ console.log(`\n\x1b[36m=== Pan Router - Claude Code ===\x1b[0m\n`);
155
+ if (!installClaudeCode()) return process.exit(1);
156
+ writeConfig();
192
157
 
193
158
  if (args.includes("--tray-install") || args.includes("-ti")) {
194
- printBanner();
195
- if (!installClaudeCode()) process.exit(1);
196
- writeConfig();
197
159
  await startTray();
198
- return;
160
+ } else {
161
+ await startServer();
199
162
  }
200
-
201
- printBanner();
202
- if (!installClaudeCode()) process.exit(1);
203
- writeConfig();
204
- await startServer();
205
163
  }
206
164
 
207
165
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panrouter",
3
- "version": "2.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "让 Claude Code 免费使用 DeepSeek 等模型,无需 API Key",
5
5
  "type": "module",
6
6
  "bin": {
@@ -9,8 +9,7 @@
9
9
  "files": [
10
10
  "cli.mjs",
11
11
  "server.mjs",
12
- "tray-daemon.ps1",
13
- "panrouter-tray.vbs"
12
+ "tray-daemon.ps1"
14
13
  ],
15
14
  "license": "MIT"
16
15
  }
package/tray-daemon.ps1 CHANGED
@@ -1,166 +1,107 @@
1
1
  <#
2
2
  .SYNOPSIS
3
- Pan Router 托盘守护脚本 (终极稳固版)
3
+ Pan Router 托盘守护脚本 (极简直连版)
4
4
  #>
5
-
6
5
  $ErrorActionPreference = "SilentlyContinue"
7
6
 
8
- # 增加调试日志功能(记录在系统临时目录,遇到问题能查原因)
9
- $logFile = "$env:TEMP\panrouter_tray_debug.log"
10
- "--- $(Get-Date -Format 'HH:mm:ss') Tray Script Started ---" | Out-File $logFile -Append
11
-
12
- try {
13
- Add-Type -AssemblyName System.Windows.Forms
14
- Add-Type -AssemblyName System.Drawing
15
- } catch {
16
- "Failed to load assemblies: $($_.Exception.Message)" | Out-File $logFile -Append
17
- Exit
18
- }
7
+ Add-Type -AssemblyName System.Windows.Forms
8
+ Add-Type -AssemblyName System.Drawing
9
+ [System.Windows.Forms.Application]::EnableVisualStyles()
19
10
 
20
- $scriptPath = $MyInvocation.MyCommand.Path
21
- $scriptDir = Split-Path $scriptPath -Parent
11
+ $scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
22
12
  $serverPath = Join-Path $scriptDir "server.mjs"
23
13
 
24
- # 接收从 Node CLI 传来的绝对路径,如果没有则降级使用 "node"
25
- $nodePath = $env:PANROUTER_NODE_PATH
26
- if ([string]::IsNullOrWhiteSpace($nodePath)) {
27
- $nodePath = "node"
28
- }
29
- "Node Path identified as: $nodePath" | Out-File $logFile -Append
30
-
31
- # ─── 定义重启服务的逻辑 ────────────────────────────────────
32
- function Restart-Server {
33
- "Executing Restart-Server..." | Out-File $logFile -Append
34
- try {
35
- Get-WmiObject Win32_Process -Filter "Name = 'node.exe'" |
36
- Where-Object { $_.CommandLine -match "server\.mjs" } |
37
- ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
38
- } catch {}
39
-
40
- try {
41
- Start-Process -FilePath $nodePath -ArgumentList "`"$serverPath`"" -WorkingDirectory $scriptDir -WindowStyle Hidden
42
- "Server process spawned successfully." | Out-File $logFile -Append
43
- } catch {
44
- "Server start error: $($_.Exception.Message)" | Out-File $logFile -Append
45
- }
14
+ # 拿到 Node 路径
15
+ $nodePath = $env:PANROUTER_NODE
16
+ if ([string]::IsNullOrWhiteSpace($nodePath)) { $nodePath = "node" }
17
+
18
+ # ─── 管理后台代理 ──────────────────────────────────────────
19
+ function Start-Backend {
20
+ # 杀掉旧代理
21
+ Get-WmiObject Win32_Process -Filter "Name = 'node.exe'" |
22
+ Where-Object CommandLine -match "server\.mjs" |
23
+ ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
24
+
25
+ # 启动新代理
26
+ Start-Process -FilePath $nodePath -ArgumentList "`"$serverPath`"" -WorkingDirectory $scriptDir -WindowStyle Hidden
46
27
  }
47
28
 
48
- # ─── 保证服务在运行(用于应对开机自启动的情况) ───────────
49
- $isRunning = $false
29
+ # 【核心修复】:不要盲目重启!检查端口如果已经通了,直接跳过耗时的杀进程步骤
30
+ $portOpen = $false
50
31
  try {
51
- $procs = Get-WmiObject Win32_Process -Filter "Name = 'node.exe'"
52
- foreach ($p in $procs) {
53
- if ($p.CommandLine -match "server\.mjs") {
54
- $isRunning = $true
55
- break
56
- }
57
- }
32
+ $tcp = New-Object System.Net.Sockets.TcpClient
33
+ $ar = $tcp.BeginConnect("127.0.0.1", 50816, $null, $null)
34
+ $portOpen = $ar.AsyncWaitHandle.WaitOne(500, $false)
35
+ $tcp.Close()
58
36
  } catch {}
59
37
 
60
- if (-not $isRunning) {
61
- "Server not running on load, starting..." | Out-File $logFile -Append
62
- Restart-Server
38
+ if (-not $portOpen) {
39
+ Start-Backend
63
40
  }
64
41
 
65
- # ─── 绘制托盘图标 (增加极强容错) ──────────────────────────
42
+ # ─── 初始化托盘 ────────────────────────────────────────────
43
+ $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
44
+ $notifyIcon.Text = "Pan Router (:50816)"
45
+
46
+ # 绘图报错是导致图标出不来的元凶之一,这里做强兜底
66
47
  try {
67
48
  $bmp = New-Object System.Drawing.Bitmap(16, 16)
68
49
  $g = [System.Drawing.Graphics]::FromImage($bmp)
69
- $g.SmoothingMode = 'HighQuality'
70
- $g.Clear([System.Drawing.Color]::Transparent)
71
- $brush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(0, 120, 215))
72
- $g.FillEllipse($brush, 0, 0, 15, 15)
73
-
74
- # 【修复1】改用通用系统字体,防止系统中缺少 Segoe UI 导致报错闪退
75
- $font = New-Object System.Drawing.Font([System.Drawing.FontFamily]::GenericSansSerif, 8, [System.Drawing.FontStyle]::Bold)
76
- $fg = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::White)
77
- $g.DrawString("P", $font, $fg, 3, 2)
78
-
79
- $hIcon = $bmp.GetHicon()
80
- $icon = [System.Drawing.Icon]::FromHandle($hIcon)
81
- "Custom icon drawn." | Out-File $logFile -Append
50
+ $g.Clear([System.Drawing.Color]::FromArgb(0, 120, 215))
51
+ $font = New-Object System.Drawing.Font("Arial", 8, [System.Drawing.FontStyle]::Bold)
52
+ $g.DrawString("P", $font, [System.Drawing.Brushes]::White, 2, 1)
53
+ $notifyIcon.Icon = [System.Drawing.Icon]::FromHandle($bmp.GetHicon())
82
54
  } catch {
83
- "Icon drawing error: $($_.Exception.Message). Using fallback icon." | Out-File $logFile -Append
84
- # 【修复2】万一画图依然失败绝对不能 Exit,用系统自带程序图标兜底显示
85
- $icon = [System.Drawing.SystemIcons]::Application
55
+ # 终极兜底:如果上面的画图代码因为 GDI 环境被拦,直接用系统自带的安全盾牌图标
56
+ $notifyIcon.Icon = [System.Drawing.SystemIcons]::Shield
86
57
  }
87
58
 
88
- # ─── 创建隐藏主窗口 (防止消息循环异常退出) ─────────────────
89
- # 【修复3】提供一个实质性的隐藏窗体,避免部分系统回收无窗体的托盘进程
90
- $mainForm = New-Object System.Windows.Forms.Form
91
- $mainForm.Text = "PanRouterHidden"
92
- $mainForm.ShowInTaskbar = $false
93
- $mainForm.WindowState = [System.Windows.Forms.FormWindowState]::Minimized
94
- $mainForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedToolWindow
95
- $mainForm.Opacity = 0
96
- $mainForm.Add_Load({ $mainForm.Hide() })
97
-
98
- # ─── 初始化托盘菜单 ────────────────────────────────────────
99
- $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
100
- $notifyIcon.Icon = $icon
101
- $notifyIcon.Text = "Pan Router (端口: 50816)"
102
-
59
+ # ─── 菜单配置 ──────────────────────────────────────────────
103
60
  $menu = New-Object System.Windows.Forms.ContextMenuStrip
104
61
 
105
- $titleItem = New-Object System.Windows.Forms.ToolStripMenuItem("Pan Router | :50816")
62
+ $titleItem = $menu.Items.Add("Pan Router | :50816")
106
63
  $titleItem.Enabled = $false
107
- $titleItem.Font = New-Object System.Drawing.Font([System.Drawing.FontFamily]::GenericSansSerif, 9, [System.Drawing.FontStyle]::Bold)
108
- $menu.Items.Add($titleItem) | Out-Null
109
- $menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator)) | Out-Null
64
+ $menu.Items.Add("-") | Out-Null
110
65
 
111
- $restartItem = New-Object System.Windows.Forms.ToolStripMenuItem("重启后台服务")
66
+ $restartItem = $menu.Items.Add("重启服务")
112
67
  $restartItem.Add_Click({
113
- Restart-Server
114
- $notifyIcon.ShowBalloonTip(2000, "Pan Router", "后台代理服务已重新启动 ✓", [System.Windows.Forms.ToolTipIcon]::Info)
68
+ Start-Backend
69
+ $notifyIcon.ShowBalloonTip(2000, "Pan Router", "服务已重启", [System.Windows.Forms.ToolTipIcon]::Info)
115
70
  })
116
- $menu.Items.Add($restartItem) | Out-Null
117
-
118
- $autoItem = New-Object System.Windows.Forms.ToolStripMenuItem("开机自启动")
119
- try {
120
- $regKey = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name PanRouter
121
- $autoItem.Checked = ($regKey -ne $null)
122
- } catch {}
123
71
 
72
+ $autoItem = $menu.Items.Add("开机自启动")
73
+ try { $autoItem.Checked = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name PanRouter) -ne $null } catch {}
124
74
  $autoItem.Add_Click({
125
75
  if ($autoItem.Checked) {
126
76
  reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v PanRouter /f 2>&1 | Out-Null
127
77
  $autoItem.Checked = $false
128
78
  } else {
129
- $vbsPath = Join-Path $scriptDir "panrouter-tray.vbs"
130
- $cmd = "wscript.exe //B //NoLogo `"$vbsPath`""
79
+ $cmd = "powershell.exe -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`""
131
80
  reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v PanRouter /t REG_SZ /d $cmd /f 2>&1 | Out-Null
132
81
  $autoItem.Checked = $true
133
82
  }
134
83
  })
135
- $menu.Items.Add($autoItem) | Out-Null
136
- $menu.Items.Add((New-Object System.Windows.Forms.ToolStripSeparator)) | Out-Null
137
84
 
138
- $exitItem = New-Object System.Windows.Forms.ToolStripMenuItem("退出")
85
+ $menu.Items.Add("-") | Out-Null
86
+
87
+ $exitItem = $menu.Items.Add("退出")
139
88
  $exitItem.Add_Click({
140
89
  $notifyIcon.Visible = $false
141
- try {
142
- Get-WmiObject Win32_Process -Filter "Name = 'node.exe'" | Where-Object { $_.CommandLine -match "server\.mjs" } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
143
- } catch {}
144
- $mainForm.Close()
90
+ Get-WmiObject Win32_Process -Filter "Name = 'node.exe'" | Where-Object CommandLine -match "server\.mjs" | ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
91
+ [System.Windows.Forms.Application]::Exit()
145
92
  })
146
- $menu.Items.Add($exitItem) | Out-Null
147
93
 
148
94
  $notifyIcon.ContextMenuStrip = $menu
149
95
 
96
+ # 左键点击直接弹出原生菜单(去除了那些花里胡哨的反射代码)
150
97
  $notifyIcon.Add_MouseClick({
151
98
  if ($_.Button -eq [System.Windows.Forms.MouseButtons]::Left) {
152
- $mi = [System.Windows.Forms.NotifyIcon].GetMethod("ShowContextMenu", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)
153
- $mi.Invoke($notifyIcon, $null)
99
+ $notifyIcon.ContextMenuStrip.Show([System.Windows.Forms.Cursor]::Position)
154
100
  }
155
101
  })
156
102
 
157
103
  $notifyIcon.Visible = $true
158
104
 
159
- "UI setup completed, entering Application loop." | Out-File $logFile -Append
160
-
161
- # 运行消息循环,绑定到隐藏窗体以锁死进程不被误杀
162
- [System.Windows.Forms.Application]::Run($mainForm)
163
-
164
- "Exiting..." | Out-File $logFile -Append
165
- $notifyIcon.Visible = $false
166
- $notifyIcon.Dispose()
105
+ # 保持进程存活的最纯粹方式
106
+ $ctx = New-Object System.Windows.Forms.ApplicationContext
107
+ [System.Windows.Forms.Application]::Run($ctx)
@@ -1,13 +0,0 @@
1
- ' Pan Router Tray Launcher
2
- ' 由 cli.mjs --tray 通过 cmd /c start /B 启动
3
- ' 与 daemon 进程树无关, 独立 Window Station
4
-
5
- Dim WshShell, FSO, ScriptDir
6
- Set WshShell = CreateObject("WScript.Shell")
7
- Set FSO = CreateObject("Scripting.FileSystemObject")
8
-
9
- ScriptDir = FSO.GetParentFolderName(WScript.ScriptFullName)
10
-
11
- ' 后台隐藏启动 PS 托盘 (自包含: 启动 server + 图标 + 菜单)
12
- ' 0 = 隐藏窗口, False = 不等待返回
13
- WshShell.Run "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -STA -File """ & ScriptDir & "\tray-daemon.ps1" & """", 0, False