插件开发教程
一句话概括:一个文件夹 = plugin.json + 一个(或零个)exe,放进插件目录就是一个
GFiles 插件。不需要 SDK、不写注册表、不用重启宿主——界面改完保存,重开窗口即生效。
一句话认识插件
GFiles 插件有三种形态,按需选择:
- 动作插件(type=action):右键菜单触发,可以只有一行输出(如「计算算式」),也可以带完整界面(如「文件夹同步」)。
- 文件系统插件(type=filesystem):让某种「看起来不是目录的东西」像目录一样浏览(如 FTP 服务器、压缩包内部)。
- 编解码插件(type=codec):给系统不认识的格式补缩略图与原图查看(如 iPhone 的 HEIC)。
- 图标主题插件(type=theme):什么都不做、只往文件列表的图标槽位里塞图标(如一套扁平文件夹图标),不改任何行为、不需要 exe。
① 5 分钟写一个插件
目标:选中若干文件 → 右键 → 显示统计结果。无需编译任何 exe,用系统自带 PowerShell 即可体验全流程。
第 1 步:打开插件目录
设置 → 插件 → 外部插件 → 「打开插件目录」(默认 %APPDATA%\GFiles\plugins,不存在就手动创建)。
第 2 步:建一个 hello 文件夹,放两个文件
plugin.json:
run.ps1:
第 3 步:刷新,右键试试
设置 → 插件 → 外部插件 → 「刷新」,列表出现「Hello 统计」即安装成功。选中几个文件 → 右键 → 外部插件 → 「统计选中的文件数」→ 弹出结果窗。
② 安装位置与共享目录
- 内置目录
<程序目录>\plugins\<名称>\:随包发布,设置页标「内置」,只读。 - 用户目录(默认
%APPDATA%\GFiles\plugins):可自由管理;与内置同 id 时用户版覆盖内置。
多个插件共用的第三方工具放共享目录,一个工具一个子目录:
动作插件用相对路径引用:"cmd": "../public/7z/7z.exe"。依赖同目录文件的程序必须走相对路径(exe + 依赖 DLL 一起放),只拷 exe 会起不来。
③ plugin.json 常用字段
| 字段 | 说明 |
|---|---|
| id | 必填,全局唯一,建议 fm.action.* / fm.codec.* 前缀 |
| name / version | 必填。★升级插件必须改 version,否则更新器认为没有新版 |
| type | action(动作/界面)|codec(编解码);文件系统插件为 filesystem |
| cmd | exe 路径,相对插件目录或绝对路径;可 ../ 借共享目录 |
| cmdFallbacks | cmd 找不到时的候选路径(支持 %plugin% 与环境变量),提升换机存活率 |
| input | stdin-json(默认,推荐)|argv |
| target / ext | 右键出现位置与扩展名过滤,见第 ④ 节 |
| label | 必填,右键菜单文案 |
| timeout | 秒,缺省 30,超时强杀 |
| iconType / icon | png/ico 路径,或 svg 代码全文;缺省取 exe 自带图标 |
| ui / uiMode | 自带界面入口;layer=主窗内遮罩卡片(默认)|window=独立窗口 |
| frameless / width / height | window 模式:无边框自绘标题栏与启动尺寸 |
| fileDrop | window 模式:允许从资源管理器拖文件进窗口,宿主把真实路径交给页面(见第 ⑭ 节) |
| alwaysOnTop | window 模式:窗口置顶 |
| toggleHotkey / hotkey | window 模式:同一热键再按一次=收起(否则连按开两个窗);hotkey 为唤出键,可在设置→快捷键改 |
| menus[] | 一个插件占多个右键项(每项可覆盖 label/target/ext/ui 等) |
| dblclick | true=双击文件时按 ext 认领直接打开(右键"打开"不受影响) |
| codecExts | action 插件附带缩略图能力(如视频抽帧) |
完整字段与逐条注释见随包文档《外部插件开发教学》。
④ 出现位置:target
| target | 出现位置 |
|---|---|
| all | 目录 / 文件 / 空白处右键都出现 |
| dir | 目录条目右键 |
| files | 文件条目右键(可配 ext 过滤扩展名,如 "7z,zip,rar") |
| dirblank | 打开某目录后,其内部空白处右键 |
| selecttext | 记事本里选中文字后的右键(text=选中文本) |
| twodir | 拆分窗格后右键:cwd=触发窗格,cwd2=另一窗格 |
可逗号多选:"target": "dir,dirblank"。扩展名统一不带点。
⑤ 宿主 → 插件的输入
stdin-json(默认):exe 从标准输入收到一行 JSON:
argv:数据经命令行占位符传入,写在清单 args 里:%dir%、%dir2%、%files%(单独成元素时逐文件展开)、%text%、%plugin%(插件目录,用于锚定相对脚本)。
⑥ 插件 → 宿主的返回(stdout 契约)
纯文本(最简单):print 一行文字,宿主弹结果窗展示 + 一键复制。
JSON 结构化:最后一行输出 {"fm":...} 开头的 JSON:
JSON 行前后的普通文本会被忽略,可以边打日志边在最后一行输出契约 JSON。
⑦ 自带 UI 与桥接 API
清单声明 "ui": "index.html" 后,触发插件改为加载你的页面,界面与交互全部由你定义。exe 只在你主动调 api/run 时才被拉起。每个插件界面想长什么样完全自定——这正是「插件界面百变」的来源。
桥接 API 常用表
| API | 说明 |
|---|---|
| /extplugin/api/session | GET 触发上下文 {cwd, cwd2, files, cmd, dir, menu…} |
| /extplugin/api/run | POST 同步执行清单 cmd,返回 {code, stdout, stderr} |
| /extplugin/api/runstart | POST 后台运行,返回 {task}(长操作) |
| /extplugin/api/runpoll | GET 轮询累计输出 {done, code, stdout}(进度百分比就在 stdout) |
| /extplugin/api/runcancel | POST 取消后台任务 |
| /extplugin/api/pick(pickfolder) | POST 文件/目录选择对话框 |
| /extplugin/api/stat | POST 查询路径存在性与大小(预检依赖文件用) |
| /extplugin/api/notify | POST 请求宿主刷新目录(新文件立刻现身) |
| /extplugin/api/icon | POST 批量取文件/文件夹的 shell 图标(16–256px,单批 ≤64 项) |
| /extplugin/api/launch | POST 启动 exe/lnk/bat/目录(CreateProcess,失败回退 ShellExecute——唯一能弹 UAC 的路) |
| /extplugin/api/drop | GET 拿拖入文件的真实路径(长轮询,取出即清;需清单 fileDrop:true) |
| /extplugin/api/mediainfo / media | GET 媒体元信息与视频流(播放器类插件) |
| /extplugin/api/close | POST 关闭自带 UI |
页面凭 URL 上的 token 参数鉴权。window 模式最小骨架:
api/drag、最大化调
api/maximize、边缘缩放宿主自动注入——页面只需自绘一条标题栏。范本见 7zip / videopreview。⑧ 编解码插件(type=codec)
给宿主补齐系统不认识的格式:列表缩略图 + 查看器原图。exe 只需实现一个契约:
- 退出码 0 且输出文件存在 = 成功;失败非 0 退出即可(宿主有 5 分钟负缓存)
- 缩略图按最长边 256px JPEG 出,宿主统一缩放
- 系统能出缩略图的格式轮不到插件,只兜系统不认识的,不冲突
⑨ 调试通道
不开主界面直接验证宿主识别与执行:
设置页「新增插件」时的试跑本身就是一次冒烟测试;被拒的插件看返回的 stderr 即可定位。
⑩ 范本对照表
内置插件源码全部公开(外加一份示例主题包),按想学的能力对号入座:
| 插件 | 演示的能力 |
|---|---|
| calc-clipboard | 选中文本触发 + 一行 stdout 契约(最小范本) |
| dircmp | 双窗格 twodir + argv 占位符 + 遮罩层 UI |
| filesync | 独立窗口 + 无边框 + 后台任务进度环 + 取消 |
| 7zip | 多菜单项 menus[] + 一份页面按 menu 字段分流 + 自解压预检 |
| videopreview | 双击认领 + 视频抽帧缩略图 + 视频流播放 |
| heifcodec | --decode 契约 + livp 拆包 |
| quick-launch | 启动器三件套:fileDrop 拖放 + alwaysOnTop + toggleHotkey 热键唤出(无 exe 纯页面) |
| flat-demo(示例主题) | type=theme 图标包:槽位写法 / strong / 三形态图标值(docs/示例-图标主题/) |
⑪ 常见坑
- 退出码非 0 ≠ 失败:命令行工具退出码是分档语义(7-Zip 的 1 = 有警告但包已生成)。只判 code===0 会把「成功但有警告」误报成失败。
- 契约 JSON 独占一行:以 {"fm": 开头,别把 JSON 拆行打印;之前的日志文本无害。
- 中文乱码:先查清单 encoding 字段;PowerShell 输出建议显式设 UTF-8。
- 占位符区分大小写:%files%、%dir1% 等写错不生效。
- 手改清单后要刷新:plugin.json 改动需设置页点「刷新」;只改 HTML 无需刷新(无缓存),重开窗口即生效。
- 插件目录不随自动更新分发:换机器要带整个 bin\plugins\;关键工具用 cmdFallbacks + 页面开窗自检兜底。
- 主题槽位键名错不报错:裸后缀
"7z"≠"ext:7z",写错会静默进「图标冲突」的跳过列表,页面上只是图标没换。 - 拖入没反应先查 data-file-drop-target:拖放链唯一静默失败点,缺了它连控制台日志都没有。
⑫ 引擎选型建议
需要引擎逻辑的插件(对比、同步、计算、转换…),建议用 Go(首选)或 .NET 编译成独立 exe: 单文件、毫秒启动、无运行时依赖,也不会触发杀软对「解释器拉脚本」的拦截。 PowerShell / BAT 脚本只适合一次性本机调试。教学文档 §14 有完整的选型论证与工程约定。
⑬ 图标主题插件(type=theme)
主题插件是什么都不做的插件:不声明 cmd/label/menus,
不进右键菜单、不执行命令、不需要 exe——只往文件列表的图标槽位里塞图标。
示例包见随包文档 docs/示例-图标主题/flat-demo/(4 个文件:清单 + 3 张 SVG)。
三条硬规则
- 槽位只有三种写法:
ext:后缀/folder/file(没有*通配)。 键名写错(裸后缀"7z"、"*"、ext:空后缀)不会报错, 而是进设置页「图标冲突」区的跳过列表——图标没生效先去那里看。 - 图标值三形态自动识别(主题没有 iconType 字段):
data:开头透传;<开头当 SVG 原文;其它按相对主题目录的图片路径(按扩展名定类型)。 - 裁决顺序:具体度 → strong → 启用次序。
ext:7z(具体)永远赢file(兜底);同具体度下strong:true抢占,再平局按启用先后。 想压掉别的主题/插件的后缀图标,就写对应的ext:槽位。
⑭ 启动器型插件:拖放、置顶、热键唤出
「快捷启动」范本演示了独立窗口插件的三件套:把 exe / 桌面快捷方式 / 文件夹拖进窗口收录、 窗口置顶、全局热键随按随现。窗口行为全部由宿主承接,插件页只管界面(本范本甚至没有 exe)。
三个布尔字段都可在 menus[] 单项上覆盖(false 能盖掉顶层的 true)。
热键可在 设置→快捷键 里改,作用域可切「系统级」(任何程序前台都能按)。
页面侧接拖入的三行代码
/extplugin/api/launch——exe/lnk/bat 走
CreateProcess、失败回退 ShellExecute(唯一能弹 UAC 的路);目录→资源管理器;其它文件→默认程序。
自己 cmd /c start 会被 cmd 重新解析引号,带空格/中文/& 的路径会碎。
图标批量取 /extplugin/api/icon(与主窗口同一个 shell 缓存)。