Initial commit

This commit is contained in:
2026-06-30 15:14:37 +08:00
commit 15dab96872
311 changed files with 95639 additions and 0 deletions
+503
View File
@@ -0,0 +1,503 @@
# MeshRay 隐藏控制台窗口解决方案
**完成时间**: 2026-03-24
**状态**: ✅ **已修复**
**问题**: 程序运行后前端一直显示命令行窗口
---
## 🎯 **问题描述**
### **现象**
运行 meshray.exe 后:
- ❌ 在任务栏显示一个命令行窗口
- ❌ 窗口持续存在,即使托盘已在运行
- ❌ 影响用户体验,不够专业
---
### **原因分析**
**Go程序默认行为**:
- Go 编译的 Windows 程序默认是**控制台子系统**Console Subsystem
- 会自动分配并显示控制台窗口
- 用于输出 `fmt.Println``log` 等调试信息
**MeshRay 的情况**:
```go
// cmd/meshray/main.go
func main() {
fmt.Println("MeshRay v2.0.0 - Starting...") // ← 这些会输出到控制台
log.Fatalf("❌ 加载配置失败:%v", err) // ← 包括错误信息
// ... 系统托盘运行 ...
trayMgr.Run() // ← 托盘在后台运行
}
```
**问题**:
- 程序有系统托盘(图形界面)
- 但仍然显示控制台窗口(不需要)
- 应该像其他 Windows 应用一样,只显示托盘图标
---
## ✅ **解决方案**
### **方法:使用 `-H windowsgui` 链接器参数**
**修改 build.bat**:
```batch
REM 修改前:
go build -ldflags="-s -w" -o meshray.exe ./cmd/meshray
REM 修改后:
go build -ldflags="-s -w -H windowsgui" -o meshray.exe ./cmd/meshray
# ↑ 添加这个参数
```
**修改build.sh**:
```bash
# Windows 平台:隐藏控制台窗口
go build -ldflags="-s -w -H windowsgui" -o meshray ./cmd/meshray
# macOS/Linux: 保持控制台(不需要隐藏)
go build -ldflags="-s -w" -o meshray ./cmd/meshray
```
---
### **参数说明**
**`-H windowsgui`**:
- `-H`: Go 链接器参数,指定程序的子系统类型
- `windowsgui`: Windows GUI 子系统(不显示控制台)
**对比**:
| 参数 | 子系统 | 控制台窗口 | 适用场景 |
|------|--------|------------|----------|
| **无或 `-H console`** | Console | ✅ 显示 | 命令行工具、需要调试输出 |
| **`-H windowsgui`** | Windows GUI | ❌ 隐藏 | 托盘应用、纯图形界面 |
---
## 📊 **效果对比**
### **修改前**
```
运行 meshray.exe
├── 显示命令行窗口 ❌
│ └── "MeshRay v2.0.0 - Starting..."
│ └── "✅ 配置加载成功"
│ └── "正在连接数据库..."
│ └── ...
└── 系统托盘 ✅
└── MeshRay 图标
```
**问题**:
- ❌ 控制台窗口挥之不去
- ❌ 用户可能误关闭控制台导致程序退出
- ❌ 看起来像命令行工具,不够专业
---
### **修改后**
```
运行 meshray.exe
└── 系统托盘 ✅
└── MeshRay 图标
```
**优势**:
- ✅ 只显示托盘图标
- ✅ 干净清爽的用户界面
- ✅ 专业的 Windows 应用体验
- ✅ 所有日志通过文件输出(如果有配置)
---
## 🔧 **完整的构建脚本更新**
### **build.batWindows**
```batch
@echo off
REM MeshRay Windows 完整构建脚本(go-winres
REM [1/7] 检查 go-winres 工具
where go-winres >nul 2>&1
if %ERRORLEVEL% NEQ 0 (
go install github.com/tc-hib/go-winres@latest
)
REM [2/7] 检查配置文件
if not exist build\winres.json (
echo [错误] 配置文件不存在
exit /b 1
)
REM [3/7] 生成资源文件
go-winres make --in build\winres.json --arch amd64
REM [4/7] 复制 syso
copy rsrc_windows_amd64.syso cmd\meshray\meshray.syso
REM [5/7] 编译程序 ← 关键修改点
echo [5/7] 编译 MeshRay...
go build -ldflags="-s -w -H windowsgui" -o meshray.exe ./cmd/meshray
if %ERRORLEVEL% NEQ 0 (
echo [错误] 编译失败!
del cmd\meshray\meshray.syso
del rsrc_*.syso
pause
exit /b 1
)
echo [✓] 编译成功
REM [6/7] 清理临时文件
del rsrc_*.syso
del cmd\meshray\meshray.syso
REM [7/7] 验证
if exist meshray.exe (
echo [✓] 验证通过
) else (
echo [错误] 可执行文件未生成!
exit /b 1
)
echo.
echo ========================================
echo 构建完成!
echo 输出文件:meshray.exe
echo 版本信息:2.0.0.0
echo 包含:图标 + Manifest + 版本信息
echo 特性:隐藏控制台窗口
echo ========================================
```
---
### **build.sh(跨平台)**
```bash
#!/bin/bash
# MeshRay 跨平台构建脚本(go-winres
# 检测操作系统
OS=$(uname -s)
case "$OS" in
MINGW*|MSYS*|CYGWIN*)
RSRC_NEEDED=true
;;
Darwin|Linux)
RSRC_NEEDED=false
;;
*)
echo "[错误] 不支持的操作系统:$OS"
exit 1
;;
esac
# Windows 平台特殊处理
if [ "$RSRC_NEEDED" = true ]; then
# 1. 检查 go-winres
if ! command -v go-winres &> /dev/null; then
go install github.com/tc-hib/go-winres@latest
fi
# 2. 检查配置文件
if [ ! -f "build/winres.json" ]; then
echo "[错误] 配置文件不存在"
exit 1
fi
# 3. 生成资源文件
go-winres make --in build/winres.json --arch amd64
# 4. 复制 syso
cp rsrc_windows_amd64.syso cmd/meshray/meshray.syso
# 5. 编译(隐藏控制台)← 关键修改
echo "[5/7] 编译 MeshRay..."
go build -ldflags="-s -w -H windowsgui" -o meshray ./cmd/meshray
if [ $? -ne 0 ]; then
echo "[错误] 编译失败!"
rm -f rsrc_*.syso
rm -f cmd/meshray/meshray.syso
exit 1
fi
echo "[✓] 编译成功"
# 6. 清理
rm -f rsrc_*.syso
rm -f cmd/meshray/meshray.syso
# 7. 验证
if [ -f "meshray.exe" ]; then
echo "[✓] 验证通过"
else
echo "[错误] 可执行文件未生成!"
exit 1
fi
else
# macOS/Linux: 简单构建
go build -ldflags="-s -w" -o meshray ./cmd/meshray
fi
echo "========================================"
echo " 构建完成!"
echo " 输出文件:meshray$([ "$RSRC_NEEDED" = true ] && echo '.exe')"
echo "========================================"
```
---
## 🛠️ **技术细节**
### **为什么 `-H windowsgui` 有效?**
**Windows 可执行文件格式**:
```
PE (Portable Executable) 头部
├── DOS Header
├── NT Headers
│ ├── File Header
│ └── Optional Header
│ └── Subsystem ← 这里决定程序类型
└── Sections (.text, .data, .rsrc 等)
```
**Subsystem 字段值**:
- `2` = IMAGE_SUBSYSTEM_WINDOWS_GUI → GUI 程序(无控制台)
- `3` = IMAGE_SUBSYSTEM_WINDOWS_CUI → 控制台程序(有控制台)
**Go 编译器**:
- 默认:`-H console` → Subsystem = 3
- 添加 `-H windowsgui` → Subsystem = 2
---
### **注意事项**
#### **1. 调试输出**
**问题**: 隐藏控制台后,`fmt.Println` 输出看不到
**解决**: 使用日志文件
```go
// internal/logging/config.go
config := logging.Config{
Level: "info",
Format: "json",
Output: "file", // ← 输出到文件而不是控制台
MaxSize: 10, // MB
MaxBackups: 3,
MaxAge: 7, // days
}
```
**或者**: 开发时使用控制台,发布时隐藏
```bash
# 开发版本(显示控制台,便于调试)
go build -o meshray-debug.exe ./cmd/meshray
# 发布版本(隐藏控制台)
go build -ldflags="-s -w -H windowsgui" -o meshray.exe ./cmd/meshray
```
---
#### **2. 标准输入输出**
**影响**: 隐藏控制台后:
-`os.Stdin` 不可用(无法读取用户输入)
- ⚠️ `os.Stdout` 被重定向(写入但无处显示)
- ⚠️ `os.Stderr` 被重定向(错误输出不可见)
**MeshRay 的情况**:
```go
func main() {
fmt.Println("启动中...") // ← 输出到 nowhere
log.Fatal("错误") // ← 错误看不到
// 但有系统托盘,所以没问题 ✅
trayMgr.Run()
}
```
**建议**:
- ✅ 使用日志文件记录所有信息
- ✅ 通过托盘菜单查看状态
- ✅ 通过 Web UI 查看日志
---
#### **3. 跨平台兼容性**
**Windows**: 需要 `-H windowsgui`
```bash
go build -ldflags="-s -w -H windowsgui" -o meshray.exe
```
**macOS/Linux**: 不需要(也不支持)
```bash
go build -ldflags="-s -w" -o meshray
# macOS/Linux 没有"隐藏控制台"的概念
# 终端应用就应该显示在终端
```
---
## 📋 **验证方法**
### **方法 1: 直接运行**
```bash
.\meshray.exe
```
**期望结果**:
- ✅ 任务栏右下角出现托盘图标
- ✅ 没有命令行窗口弹出
- ✅ 程序正常运行
---
### **方法 2: 查看 PE 头信息**
使用工具如 `dumpbin`Visual Studio)或 `objdump`:
```bash
dumpbin /headers meshray.exe | findstr subsystem
```
**期望输出**:
```
subsystem (2) Windows GUI
```
如果是 `(3)` 则表示还是控制台程序。
---
### **方法 3: 使用 PowerShell 检查**
```powershell
# 读取 PE 文件的 subsystem 字段
$bytes = [System.IO.File]::ReadAllBytes("meshray.exe")
$subsystem = [BitConverter]::ToUInt16($bytes, 0x5C)
Write-Host "Subsystem: $subsystem"
if ($subsystem -eq 2) {
Write-Host "✅ Windows GUI 程序(无控制台)"
} elseif ($subsystem -eq 3) {
Write-Host "❌ Console 程序(有控制台)"
}
```
---
## 🎯 **最佳实践**
### **开发阶段**
```bash
# 保留控制台,便于调试
go build -o meshray-debug.exe ./cmd/meshray
# 运行时会看到所有输出
.\meshray-debug.exe
```
**优势**:
- ✅ 可以看到启动日志
- ✅ 可以实时调试
- ✅ 错误信息立即可见
---
### **发布阶段**
```bash
# 隐藏控制台,专业交付
go build -ldflags="-s -w -H windowsgui" -o meshray.exe ./cmd/meshray
```
**优势**:
- ✅ 专业的用户界面
- ✅ 只通过托盘交互
- ✅ 符合 Windows 应用规范
---
### **自动化构建**
在 CI/CD 中自动区分:
```yaml
# GitHub Actions 示例
jobs:
build-windows:
runs-on: windows-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: '1.21'
- name: Build with hidden console
run: |
go build -ldflags="-s -w -H windowsgui" -o meshray.exe ./cmd/meshray
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: meshray-windows
path: meshray.exe
```
---
## ✅ **总结**
### **核心修改**
| 文件 | 修改位置 | 修改内容 |
|------|----------|----------|
| **build.bat** | 第 5 步编译命令 | 添加 `-H windowsgui` |
| **build.sh** | Windows 平台分支 | 添加 `-H windowsgui` |
---
### **效果对比**
| 项目 | 修改前 | 修改后 |
|------|--------|--------|
| **控制台窗口** | ❌ 显示 | ✅ 隐藏 |
| **托盘图标** | ✅ 显示 | ✅ 显示 |
| **专业性** | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| **用户体验** | 一般 | 优秀 |
---
### **适用场景**
**需要使用 `-H windowsgui`**:
- ✅ 系统托盘应用
- ✅ 纯图形界面应用(Win32、WPF、WinForms
- ✅ 后台服务(虽然最好用 Windows Service
**不需要使用**:
- ❌ 命令行工具
- ❌ 需要控制台输入的程序
- ❌ 调试阶段的开发版本
---
**修复状态**: ✅ **已完成,控制台窗口已隐藏**
**推荐方案**: ✅ **使用 `-H windowsgui` 参数**
**用户体验**: ✅ **从 2 星提升到 5 星**
*MeshRay - 注重细节,追求卓越用户体验!*