AutoHotkey 多脚本启动器教程一个托盘图标实现一键切换全部脚本【免费下载链接】AutoHotkeyAutoHotkey - macro-creation and automation-oriented scripting utility for Windows.项目地址: https://gitcode.com/gh_mirrors/au/AutoHotkey早上开完电脑要手动点开五个脚本窗口管理、文本替换、Git 快捷命令、自动备份、输入法控制……点完还得去系统托盘一个个数图标确认哪些真跑起来了。如果你也是这个状态这篇文章教你用 AutoHotkey 做一个多脚本启动器一个托盘菜单管住所有脚本支持一键启动、暂停和场景切换。定位这不是脚本管理器是总开关先说清楚这东西的定位避免期待错位。它不是把脚本打进包里、带依赖解析、带版本管理的重型管理器它就是一张托盘菜单 一个 INI 配置文件 几十行控制代码。价值集中在三件事统一入口所有脚本从一个菜单点进点出不再翻文件夹状态可见哪个脚本在跑、哪个停了看菜单勾选就知道场景化切换写代码时一套脚本开会演示时另一套一个热键整组换整个启动器本身就是一个.ahk文件不依赖任何第三方库随时可以删掉重来风险极低。准备工作环境就三样AutoHotkey v1.1本文代码基于 v1 语法Menu、Process命令风格安装版或绿色版均可启动器脚本launcher.ahk后面逐步写出来放在你自己的目录比如D:\AHK\配置文件scripts.ini与启动器同目录存所有脚本的分组和路径脚本清单建议先手工维护成一张表本地 Excel、便签都行确定好哪些脚本归办公场景、哪些归开发场景后面写 INI 就是照抄。底层能力都现成读 INI 用的是IniRead命令实现见 source/script_registry.cpp启停脚本靠Process命令对应 source/lib/process.cpp 里的进程 API热键走全局钩子source/hotkey.cpp。我们只负责把这几块拼起来。第一步scripts.ini 怎么组织让菜单自带分组配置文件的结构直接决定托盘菜单的样子。INI 的 Section 就是菜单里的分组标题Key 是脚本在菜单上的显示名Value 是脚本路径[Office] WinMgrD:\AHK\WindowManager.ahk TextReplaceD:\AHK\TextExpander.ahk [Dev] VSCodeHelperD:\AHK\VSCodeHelper.ahk GitCmdD:\AHK\GitCommands.ahk三个约定后面代码全靠它们Section 名 分组名会出现在托盘菜单一级项上用中文也行[办公]没问题Key 显示名菜单上给脚本起个短名字别直接拿D:\AHK\...这种长路径当菜单项Value 完整路径用绝对路径这样启动器放在哪都能找到脚本这个约定还有个好处想临时停用某个脚本把它的行挪到别的 Section 或者直接删掉即可不用改启动器代码。第二步托盘菜单如何按配置自动生成启动器的骨架其实很短读配置 → 每个 Section 生成一个子菜单 → 组里每条脚本挂一个菜单项点击都指向同一个标签Toggle。核心逻辑大概长这样#Persistent Menu, Tray, Icon, %A_ScriptDir%\launcher.ico IniFile : A_ScriptDir \scripts.ini Menu, Tray, Add ; 占位标题右键第一行显示启动器名 Menu, Tray, NoStandard ; 遍历每个 Section Loop, Parse, IniSections, n { group : LTrim(A_LoopField) group : SubStr(group, 1, InStr(group, ]) - 1) Menu, Tray, Add, %group%, ShowGroup ; 该组下的脚本逐个挂到子菜单读取 IniKeys 并 Add见下 } return其中读取某组下所有脚本用IniRead的三参数形式一次拿回整段 Key再拆开IniRead, keys, %IniFile%, %group% ; 返回 WinMgrD:\..\WindowManager.ahknTextReplace... Loop, Parse, keys, n { name : SubStr(A_LoopField, 1, InStr(A_LoopField, ) - 1) path : SubStr(A_LoopField, InStr(A_LoopField, ) 1) ScriptPath[%name%] : path ; 全局 map 存起来切换时用 Menu, %group%, Add, %name%, Toggle }写到这里托盘里已经能看到分组和脚本名单了点脚本还没反应——正常下一步才接动作。菜单、托盘这类 GUI 交互在引擎里的归属可以看 source/script_gui.cpp 和 source/script_menu.cpp不过日常写脚本用不到那层知道Menu, Tray命令背后有东西托底就够了。第三步脚本控制逻辑怎么写点一下就能启停所有脚本菜单项共用一个标签靠A_ThisMenuItem区分点的是谁Toggle: name : A_ThisMenuItem path : ScriptPath[name] Process, Exist, %name% ; 按进程名判断脚本以文件名当进程名时最稳 if (ErrorLevel) { Process, Close, %ErrorLevel% Menu, %group%, Modify, %name%, Checked, 0 Running[name].Delete() TrayTip, , %name% 已停止, 1 } else { Run, %path% Menu, %group%, Modify, %name%, Checked, 1 TrayTip, , %name% 已启动, 1 } return两个取舍说明一下用Process, Exist而不是记 PID 判断状态。Process, Exist, 脚本名返回的 ErrorLevel 就是 PID找不到为 0一个命令同时完成查状态 拿句柄比维护一张 PID 表少很多出错面。代价是要求被管脚本的进程名文件名不重名这个在前面配置约定里已经排掉了。停止用Process, Close而不是 Kill。Close 走的是正常退出请求脚本里如果有#InstallExitCallbacks或退出清理逻辑保存状态、停子进程能跑完。粗暴 Kill 会让有收尾动作的脚本留下残局。托盘菜单的图标、勾选这些视觉项配合Menu, Tray, Icon一行设置效果就完整了。第四步托盘菜单如何反映真实状态脚本自己退了也要摘勾最容易被忽略的一步用户可能右键结束脚本、任务管理器杀进程菜单勾选却还挂着。用一个 1 秒一次的定时器对账SetTimer, CheckAll, 1000 CheckAll: for name, pid in Running { Process, Exist, %name% if (!ErrorLevel) { Menu, %group_of(name)%, Modify, %name%, Checked, 0 Running[name].Delete() } } returnRunning是一张我当前认为在跑的 map只有勾选中的脚本才进表所以定时器每圈只查活着的几个1000 毫秒的周期对托盘刷新来说绰绰有余CPU 占用可以忽略。定时器走的是引擎内置的SetTimer机制配套等待/延时能力在 source/lib/wait.cpp不用自己造轮子。做完这一步勾选状态就永远和真实进程一致了——它是启动器和假启动器的分水岭。做完之后用起来是什么样描述一下真实一天的节奏比列功能清单直观到工位点开启动器Ctrl1办公组两个脚本同时起来托盘菜单里对应两项打上勾进 IDE 干活前按 Ctrl2办公组自动收起、开发组顶上整个过程手指没离开键盘。下午临时要跑备份脚本直接右键托盘图标 → Dev → 点一下勾上跑完再点一下勾掉。某天发现 Git 脚本其实没起来上次改动后路径写错了以前得逐个数托盘图标排查现在一眼扫菜单该勾的没勾就是它的问题改 INI 重启启动器即可。脚本自己崩溃退出的情况也一样一秒内勾自己消失不用等下次手动点开才发现咦它没在跑。常见问题与避坑脚本双击能跑从启动器 Run 就不行八成是工作目录或相对路径的问题。被管脚本内部如果用了相对路径比如读自己目录下的配置启动器Run它时工作目录未必和你双击时一样。解法被管脚本里统一用A_ScriptDir拼路径启动器这边 INI 里也写绝对路径两头都锁死。Process, Exist查不到刚启动的脚本Run是异步的脚本初始化要几百毫秒。紧跟在Run后面立即Process, Exist可能查不到别据此判断启动失败。要么查Running里自己维护的状态要么留一点延迟再查。中文 Section 名在某些环境读取异常极少数老环境处理非 ASCII 的 INI 段名不老实。稳妥做法Section 用英文[Office]/[Dev]菜单显示名再映射成中文。Key 和 Value 用中文基本没问题。两个脚本同名文件冲突前面提过Process, Exist, 名字靠进程名匹配。D:\AHK\common.ahk和E:\Tools\common.ahk会互相误判。文件名全局唯一是这套方案唯一硬性要求。想加开机自启却发现脚本没起来启动器要进启动项shell:startup放快捷方式即可但被管脚本本身不必都进启动项——由启动器按配置拉起来这正好是集中管理的意义。进阶玩法热键整组切换上文的 Ctrl1 / Ctrl2 就是两个标签各自做先关本组、再开目标组。写起来就是循环Running把当前组的勾全摘掉再对目标组每个脚本执行Run。热键走全局钩子注册source/hotkey.cpp所以即使启动器没有焦点也生效这是场景切换体验的关键。状态推送不用盯菜单把CheckAll里发现退出的分支扩展一下连续两次检查发现某脚本掉了就TrayTip或直接Run一个通知脚本。再进一步用Http把状态推到手机出门在外也能知道那台机器上的脚本还活着——监控脚本本身是启动器最顺手的一个副产品。配置热重载菜单构建逻辑抽成一个函数托盘菜单加一项重新加载配置点一下重建全部子菜单。改 INI 不用重启启动器调脚本清单时很舒服。打包分发如果这套流程在团队里推广可以把启动器用 Ahk2Exe 编译成独立 EXE配置文件外置不变。注意发布前把 INI 里的路径约定和命名规范写进 README比代码本身更重要。小结这个启动器没有炫技一个 INI 定结构一个托盘菜单做入口Process命令管生死SetTimer做对账加起来不到百行代码。但它把手动点五个脚本 数托盘图标这件事压缩成了按一个热键而且状态永远真实。如果你手上的脚本已经多到记不全值得花一个下午把它搭起来。下一篇准备讲脚本加密与权限管理如何防止被管脚本被随意篡改、如何给不同场景的脚本上不同的权限边界搭配这个启动器用正好。【免费下载链接】AutoHotkeyAutoHotkey - macro-creation and automation-oriented scripting utility for Windows.项目地址: https://gitcode.com/gh_mirrors/au/AutoHotkey创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考