# WinLaunch **Repository Path**: ssss2020/win-launch ## Basic Information - **Project Name**: WinLaunch - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-25 - **Last Updated**: 2026-05-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WinLaunch Windows 本地应用启动器:用 **CustomTkinter** 管理 `config/apps.json`,支持软件库、分组一键启停、**可自定义全局快捷键唤出主窗口**、**Windows 通知区域(托盘)常驻**、网络小工具与配置热重载。 ## 快速开始 1. 克隆或解压仓库后,双击 **`bin\start.bat`**。 2. 若尚无 **`.venv`**,脚本会自动创建虚拟环境并执行 **`pip install -r requirements.txt`**,随后用 **`pythonw`** 启动主界面(无控制台黑窗)。 3. 工作目录会自动设为仓库根目录;默认配置文件为 **`config\apps.json`**。 4. **Windows**:启动后主窗口会**自动隐藏到托盘**(依赖 **`pystray`**);单击托盘图标或菜单「打开主窗口」可再次显示;点窗口 **关闭** 亦为隐藏到托盘;在托盘菜单中选 **「退出」** 才会结束进程。若未安装 **`pystray`** 则保持传统「始终显示主窗口、关闭即退出」行为。 5. 需要**从外部结束进程**(含仅驻留托盘时):双击 **`bin\stop.bat`**(内部通过主窗口标题 **`MyManager`** 定位进程并终止;实现见 **`bin\stop_winlaunch.py`**,标题须与 `src/gui_ctk.py` 中 **`LAUNCHER_WINDOW_TITLE`** 保持一致)。 ## 启动方式 | 方式 | 说明 | |------|------| | **`bin\start.bat`** | 推荐入口:`pythonw` + `start`,不占用当前 CMD 窗口。 | | **`bin\stop.bat`** | 结束已运行的 WinLaunch:优先用 **`.venv\Scripts\python.exe`** 执行 **`bin\stop_winlaunch.py`**(`FindWindow` + `TerminateProcess`);无 venv 时回退系统 **`python`**。 | | 命令行 | `.\.venv\Scripts\python.exe -m src.gui_ctk --config config\apps.json` | | 指定配置 | 增加参数 **`--config`** 指向其它 `apps.json`(单实例互斥体名称会随配置路径变化,不同配置可同时各开一例)。 | ## 功能概要 ### 我的软件库 - 通过「添加」选择 **exe / bat / cmd / lnk**,写入 **`apps`** 与展示名;**仅对 .exe** 从可执行文件提取界面小图标(**.bat / .cmd** 使用首字母色块,避免部分环境下 Shell 图标导致崩溃)。 - 顶栏:**标题 + 添加**;第二行为 **分组标签**(含「全部」)及 **新分组名 / 添加分组 / 删除分组**。 - 卡片上可对单个应用 **启动 / 停止 / 置前 / 日志** 等操作。 - **外部已运行且进程名匹配**时再次点「启动」:**不会重复拉起进程**,而是尝试将已有窗口 **置前**(依赖 `match_process_names`,见下文配置说明)。 ### 分组启动 - 数据来自 **`quick_groups`**:每个键对应一组别名列表。 - 若配置里 **`quick_groups` 为空**,程序会自动视为存在一个名为 **「默认」** 的空组(便于首次进入页面即可选组、添加成员);写入 `apps.json` 时也会与之一致。 - 顶栏与软件库类似:**「+ 添加组」**(输入对话框)、第二行为 **启动组标签** + **删除组**(删除当前选中标签对应组)。 - 主区域展示 **当前选中组** 的一张卡片:成员以标签展示,**一键启动 / 一键停止**,底部可 **加入 / 移出** 成员。 - 组数量上限见 **`src/apps_json_edit.py`** 中的 **`MAX_QUICK_GROUPS`**(默认 5)。 ### 网络工具箱 - **本地端口占用**:输入端口查询 PID 与进程名;可 **结束进程**(含子进程,有确认框)。优先 **`psutil.net_connections`**,必要时在 Windows 上回退 **`netstat -ano`**。 - **远程 TCP 可达性**:主机 + 端口,短超时内尝试 TCP 连接;**校验与错误信息在页面内展示**,不使用弹窗提示(与端口查询区一致)。 - 部分环境枚举连接需 **管理员权限**;结束系统进程可能失败,属系统限制。 ### 设置中心 - 展示配置文件路径;**编辑 apps.json / 打开配置目录 / 重新加载配置**。 - **全局快捷键(仅 Windows)**:在 **`global_hotkey`** 中配置组合键后,任意时刻按下可将主窗口 **置前** 以便操作。若 JSON **未包含该字段**,默认 **`alt+q`**;在配置中写 **`""`** 则关闭。支持在输入框中 **手动输入**(如 `ctrl+shift+l`),也可点 **「按下录制」** 在弹出窗口内 **直接按键**,校验通过后会 **自动保存并重新加载配置**。规则:**至少一个修饰键**(`ctrl` / `alt` / `shift` / `win`)**加一个触发键**(字母、数字、`space`、或 `f1`–`f12`),多项用 **`+`** 连接。依赖 **`pynput`** 注册系统级热键;与其它软件热键冲突时需更换组合。**Win 键** 可能被系统优先拦截,若录制失败可改用手动输入 `win+...`。 - 本窗口打开时,若磁盘上的 **`apps.json` 被外部修改**,约 **2 秒** 内轮询到后会 **自动重载** 并刷新当前页(解析失败时仅提示,不覆盖内存中的旧配置);重载后也会同步 **全局快捷键** 监听。 ### 单实例(仅 Windows) - 再次运行同一配置的启动器时,若已有实例:**将已有主窗口置前**(标题 **`MyManager`**,与 `src/gui_ctk.py` 中 **`LAUNCHER_WINDOW_TITLE`** 一致),新进程直接退出。主窗口处于**托盘隐藏**状态时同样会**恢复显示**。 - 实现见 **`src/single_instance_win.py`**(命名互斥体 + `FindWindow`)。 ### 托盘(仅 Windows) - 见上文 **快速开始** 第 4 条。图标与菜单由 **`src/win_tray.py`**(位图)与 **`pystray`** 实现;默认菜单项 **「打开主窗口」** 亦响应托盘图标的**主键单击**(`default=True`)。 ## 配置文件:`config/apps.json` 根对象通常包含 **`apps`**、**`groups`**、**`quick_groups`**;**`global_hotkey`** 可省略(省略时默认为 **`alt+q`**),若需关闭热键请写空字符串 **`""`**。若不希望将本机安装路径提交到远程仓库,可另存一份 `apps.json` 并通过 **`--config`** 启动(见「启动方式」表)。 ```json { "apps": { "nginx": "D:\\soft\\nginx\\nginx.exe", "redis": { "command": "D:\\soft\\Redis\\redis-server.exe", "description": "Redis", "match_process_names": ["redis-server.exe"] } }, "groups": { "后端": ["nginx", "redis"] }, "quick_groups": { "一键后端": ["nginx", "redis"] }, "global_hotkey": "alt+q" } ``` | 字段 | 说明 | |------|------| | **`apps`** | 键为 **别名**。值可为 **路径字符串** 或 **对象**(常用键:`command`、`args`、`cwd`、`group`、`description`、`match_process_names`)。未写 **`match_process_names`** 时,默认使用 **`command` 的文件名**(小写)用于检测是否已在运行。 | | **`groups`** | 软件库左侧 **分组标签** 及组内别名顺序;键数量上限见 **`MAX_LIBRARY_GROUPS`**(默认 5,不含「全部」)。 | | **`quick_groups`** | 「分组启动」中的 **一键组**;值为别名数组,且每个别名必须存在于 **`apps`**。 | | **`global_hotkey`** | 字符串。全局快捷键(仅 Windows);**缺省字段**时按 **`alt+q`**;**`""`** 表示不注册。写入格式经程序规范化;可在设置页用「按下录制」生成。 | 日志:由启动器拉起的进程,标准输出/错误写入 **`logs/.log`**(相对当前工作目录,一般为仓库根)。 ## 项目结构(主要文件) ``` WinLaunch/ ├── bin/start.bat # 启动脚本 ├── bin/stop.bat # 结束 WinLaunch 进程(调用 stop_winlaunch.py) ├── bin/stop_winlaunch.py # 按主窗口标题 MyManager 查找并终止进程 ├── config/apps.json # 默认配置 ├── requirements.txt ├── README.md └── src/ ├── gui_ctk.py # 主界面(CustomTkinter) ├── config.py # 配置解析与 AppConfig 等 ├── process_manager.py # 启停、置前、日志、进程树终止 ├── apps_json_edit.py # JSON 安全读写与分组/快速组 API ├── hotkey_pynput.py # 全局快捷键字符串校验与 Tk 按键解析 ├── hotkey_service.py # Windows 下 pynput 监听与置前主窗口 ├── win_tray.py # 托盘图标位图(Pillow) ├── network_tools.py # 端口占用、杀进程、TCP 探测 ├── single_instance_win.py # Windows 单实例 └── win_metadata.py # exe 图标、lnk、FileDescription 等 ``` ## 依赖 见 **`requirements.txt`**: - **customtkinter**:界面。 - **Pillow**:从 exe 生成卡片图标位图。 - **pywin32**:解析 **.lnk**、**FileDescription** 等 Windows 元数据。 - **psutil**:进程与网络连接枚举。 - **pynput**:仅在 Windows 上用于 **全局快捷键** 注册与回调(非 Windows 可不装,但 `requirements.txt` 中仍列出以便环境一致)。 - **pystray**:仅在 Windows 上用于 **通知区域托盘**;未安装时程序不进入托盘模式(主窗口常驻、关闭即退出)。 ## 已知限制 - **托盘**:仅 **Windows** 且成功加载 **`pystray`** 时启用;异常或未安装依赖时回退为普通窗口模式。 - **全局快捷键** 与其它应用或系统保留热键冲突时无法注册;**Win 组合键** 在「按下录制」时可能被系统抢占,可改为手动填写配置。缺省快捷键为 **`alt+q`**(见配置说明),若与系统或其它软件冲突请改为其它组合或写 **`""`** 关闭。 - **置前**(`SetForegroundWindow`)受 Windows 前台规则限制,可能失败;无可见窗口的进程无法置前。 - **`match_process_names`** 若与系统内其它进程同名,可能误判「已在运行」;多开需求需在配置中收窄或留空策略(留空时仍会用 exe 文件名作为默认匹配)。 - **`bat/cmd`** 停止时对进程树做 **terminate/kill**;复杂脚本若子进程与主进程名不一致,可能需在配置中补充 **`match_process_names`** 以便正确识别与停止。 - 网络工具箱的端口列表在 **权限不足** 时可能不完整;可尝试以管理员运行。 ## 开发与排错 - 界面入口模块:`python -m src.gui_ctk --config config\apps.json` - 结束本机 WinLaunch 进程:`bin\stop.bat` 或 `python bin\stop_winlaunch.py`(须在仓库根或提供正确 Python 环境)。 - 修改 **`src/*.py`** 后可用 **`python -m py_compile src/gui_ctk.py`** 做语法检查。