Skip to content

内嵌资源(把文件打进 EXE) ​

[🕒 预计 15 分钟] | 难度:进阶

内嵌资源让你把任意格式的项目文件(图片、文本、JSON、zip、字体、DLL 字节…)在构建期直接打进 EXE, 运行期用「资源_*」命令按逻辑名读取。程序分发时只需要一个 exe,不再需要把素材文件散落在旁边。

功能由内置模块 lingbuilder.resource.embed(「内嵌资源模块」)提供,清单保存在项目模型里, 跨窗口共享:同一个项目的所有窗口读到的都是同一份资源。

NOTE

内嵌资源只在构建期打包:改了源文件必须重新构建,运行期读到的始终是构建时的内容。 构建产物不会把资源解压到磁盘(除非你显式声明 extract 或调用释放命令)。

1. 什么时候用它 ​

场景做法
单文件分发把图标、说明文件、配置 JSON 内嵌进 exe
交给只吃字节集的接口内存DLL_加载(资源_取字节集("dll/mylib.dll"), "mylib.dll")
交给只吃磁盘路径的老库声明 extract: true,或运行期 资源_释放到临时目录(...)
内嵌网页资源用「内嵌站点」机制配 EdgeView/FBro 浏览器控件(两者怎么选见内嵌站点 vs 内嵌资源)

2. 在设计器里维护清单 ​

  1. 打开窗口设计器,选中窗口本身(在画布空白处点一下,让右侧显示「窗口属性」)。
  2. 在属性面板找到 项目 / 内嵌资源(跨窗口共享) 分组。
  3. 用两个按钮添加条目:
    • 选择文件…:本机多选,选完自动复制进项目(默认 <项目源码根>/resources/<原文件名>,重名自动加 -2 后缀),逻辑名自动回填。
    • 选择文件夹…:本机选目录,递归展开成多条,逻辑名保留文件夹内的相对路径(文件夹名作为顶层目录)。
  4. 想引用工作区内已有文件、不想再复制一份时,在「扫描目录」输入框填工作区相对目录(如 assets),点 扫描目录,逻辑名直接取工作区相对路径。
  5. 表格里可以直接改逻辑名、源文件,勾选/取消启动释放,点右侧垃圾桶删除条目。

TIP

面板会实时做与构建期同一套校验:逻辑名重复、源文件缺扩展名、路径越界等都会在面板底部用中文提示。 没启用「内嵌资源模块」时面板顶部会给出一键启用入口。

3. 清单写法(手改项目 JSON 时) ​

清单存在项目设计器模型的顶层 embeddedResources(window-designer.json):

json
"embeddedResources": [
  { "name": "assets/说明.txt", "file": "src/resources/说明.txt" },
  { "name": "assets/包.zip",   "file": "src/resources/包.zip", "extract": true },
  { "name": "dll/mylib.dll",   "file": "dll/x64/mylib.dll" }
]
字段含义
name逻辑名:运行期用它读取。大小写与斜杠方向不敏感,可以用中文与子目录
file工作区内相对源文件路径(必须带扩展名、位于工作区内)
extract为真时程序启动就释放到 %TEMP%\lingbuilder-embedded\<工程ID>\<逻辑名>,供只接受磁盘路径的 API

4. 八条命令 ​

命令签名说明
资源_取字节集资源_取字节集(逻辑名) → 字节集读成字节集(失败返回空字节集)
资源_取文本资源_取文本(逻辑名) → 文本型按 UTF-8 解码(源文件须是 UTF-8)
资源_是否存在资源_是否存在(逻辑名) → 逻辑型清单里有且 EXE 里能取到
资源_取大小资源_取大小(逻辑名) → 整数型原始字节数
资源_列表资源_列表() → 文本型每行一个逻辑名,便于自检
资源_保存到文件资源_保存到文件(逻辑名, 路径) → 文本型覆盖写成真实文件,返回路径
资源_释放到临时目录资源_释放到临时目录(逻辑名) → 文本型释放到 %TEMP%\lingbuilder-embedded\<工程ID>\ 并返回路径
资源_取错误信息资源_取错误信息() → 文本型最近一次失败的中文原因

5. 完整示例 ​

假设清单里已声明 assets/说明.txt、assets/包.zip、dll/mylib.dll:

text
包 我的程序
使用 Win32窗口基础模块
使用 内嵌资源模块

类 主窗口 : 窗口
公开
  事件 _主窗口_创建完毕()
    局部 文本型 说明 = ""
    局部 整数型 包大小 = 0
    局部 字节集 包数据 = 字节集_从文本("")
    说明 = 资源_取文本("assets/说明.txt")
    包大小 = 资源_取大小("assets/包.zip")
    包数据 = 资源_取字节集("assets/包.zip")
    调试输出(格式化文本("说明={},压缩包={} 字节", 说明, 包大小))
    如果 (包大小 = 0)
      调试输出(资源_取错误信息())
    如果结束
    // 交给只接受磁盘路径的库
    局部 文本型 路径 = 资源_释放到临时目录("assets/包.zip")
    调试输出(路径)
    // 内嵌 DLL 直接内存加载,不落盘
    局部 长整数型 模块地址 = 内存DLL_加载(资源_取字节集("dll/mylib.dll"), "mylib.dll")
    结束
  结束
结束类

要点:

  • 调用的模块命令,项目必须先在 配置项目所使用模块 中启用「内嵌资源模块」和「内存加载DLL模块」。
  • 逻辑名写错时不会崩溃:命令返回空值,用 资源_取错误信息() 看中文原因。
  • 列表自检:资源_列表() 会打印全部逻辑名,构建后不确定打包了什么就先打它。

6. 构建与放置规则 ​

  • 资源号从 2301 起按清单顺序分配(图标 101、内嵌站点 2101+、项目 DLL 2201+ 各自独立)。
  • 构建时源文件会被复制成 ASCII 归档名(resources/res-0001.bin)再交给资源编译器, 因此中文路径与中文文件名都能安全内嵌。
  • 上限:条目 ≤ 4096 条、单文件 ≤ 256MB;总量超过 256MB 会在构建日志里给出体积告警(不阻断)。
  • 路径必须是工作区内相对路径,且不能包含 ..、引号或控制字符。

7. 限制与注意事项 ​

  • 仅支持 Windows 目标(PE 资源机制);EXE 体积会随资源总量线性增长。
  • 内嵌 ≠ 解压:资源_取字节集 读 zip 拿到的是原始字节。要解压请先 资源_保存到文件,再用 ZIP 相关模块处理。
  • 不要内嵌 .exe / .com 等可执行文件;要内嵌可执行代码请用「内存加载 DLL」链路。
  • extract: true 的释放是覆盖写,每次启动都会重写一遍,路径固定为 %TEMP%\lingbuilder-embedded\<工程ID>\。
  • 旧项目的「窗口内嵌文件」(释放到 %TEMP% 的 embeddedFiles,最多 8 个、没有设计器入口)会在打开/构建时 自动迁移成等价的 extract: true 内嵌资源,构建日志会给出弃用提示,保存项目即写回新格式。

下一步 ​