# 创建自动更新程序

## 制作升级包

在 aardio 开发环境创建工程并编写好程序以后，
点击发布按钮（或按 `F7` 快捷键）发布程序并生成 EXE 文件以后，
可以发布完成对话框界面点击「制作升级包」包按钮，打开制作升级包向导。

也可以点击「 aardio 工具 » 编码 » 升级包制作 」 打开升级包向导。

在升级包向导中输入：

- 升级包下载网址根目录。例如 `http://update.aardio.com/api/v1`。
- 升级说明。
- 输出目录。例如 `/.update-files/` 。

然后点击「生成升级包」按钮。
生成升级包以后，弹出对话框『是否打开升级包输出目录』，我们点击「确定」按钮以自动打开升级包输出目录。

在升级包目录（ 例如 `/.update-files/` 目录 ）下面可以看到生成了以下文件：

- `/files/` 目录。此目录下包含了发布程序的全部文件的 `*.lzma` 格式压缩文件，例如 `aardio 程序.exe.lzma`。
- `/checksum.lzma` 校验文件。这个文件解压后的数据是所有发布文件的哈希校验码与文件长度等信息，每行表示一个文件，格式为 `crc32 校验码|文件原始长度|压缩后长度|文件路径`，例如 `1405906598|1160704|411139|aardio 程序.exe`。
- `/version.txt` 这里面包含了 JSON 格式的升级包信息。

    version.txt 示例：

    ```json
    {
        "description":"",
        "format":".lzma",
        "main":"aardio 程序.exe",
        "updater":"aardio 程序.exe",
        "url":"http://update.aardio.com/api/v1",
        "version":"0.0.0.1"
    }
    ```

我们需要将上述文件上传到服务器上，并可通过 version.txt 内指定的 url 根目录可以下载升级包中的所有文件 。例如通过 `http://update.aardio.com/api/v1/version.txt` 可以下载升级包的版本信息, 通过 `http://update.aardio.com/api/v1/checksum.lzma` 可以下载升级包的文件校验码等信息,通过 `http://update.aardio.com/api/v1/files/aardio 程序.exe.lzma` 则可以下载需要升级的应用程序文件。

version.txt 内 `updater` 字段指定的是执行自动更新程序的程序，而 `main` 字段指定的是应用程序的启动 EXE 文件。这两个字段通常指向相同的 EXE 文件，因为我们一般会在应用程序的启动程序中同时检测并执行自动更新（通过启动参数自动区分）。


## 执行自动更新程序

以 aardio 制作的开源软件 ImTip 为例，一个最简单的自动更新程序就是在 aardio 启动代码 main.aardio 内加入以下代码（建议放在所有窗口显示以前）：

```aardio
import fsys.update.simpleMain;

if( fsys.update.simpleMain(
	"ImTip 桌面助手",
	"http://imtip.aardio.com/update/",
	io.appData("/aardio/std/ImTip/app/update"),
	function(version,description,status){
		/*
		version 参数包含最新版本号。
		description 包含最新版本更新说明。
		status 参数值见下面的列表：
			- "ready": 下载已完成并准备更新,
			- "updated": 已更新到新版本并准备启动新版
			- "complete": 当前已更新并已启动新版本主程序，所有操作已完成
			- "latest": 已经是最新版不需要更新
			- "failed": 出错了,description参数为错误信息
		*/
	} )){
	return 0; //必须退出 main.aardio 以启动更新
}
```

fsys.update.simpleMain 专用于在启动主线程（必须是界面线程）内获取 aardio 格式的升级包并执行自动更新程序，调用参数非常简单：

- 参数 1 指定应用程序名称
- 参数 2 指定获取 version.txt 的网址
- 参数 3 指定升级包的下载存储目录，绿色软件建议使用 io.appData 函数获取 `%localappdata%` 下面的目录作为存储目录，建议格式为 `io.appData("/软件厂商名/软件名字/update-files")`。
- 参数 4 则指定回调函数。这个回调函数是可选参数，可以省略。只要调用了 fsys.update.simpleMain 构造函数，则在应用程序中的启动主线程（界面线程）内可以随时调用 fsys.update.simpleMain.onStatusChanged 指定此回调函数（所有回调参数用法都一样）以订阅更新状态变更信息。

只要在主线程（界面线程）调用了 fsys.update.simpleMain 构造函数，那么在同一界面线程的任何窗口中都可以再次调用 `fsys.update.simpleMain.checkUpdate(true)` 再次检测并启动更新程序。

## 定制自动更新程序

fsys.update.simpleMain 实际上是对 `fsys.update.dlMgr` 与 `fsys.update.app` 简化与封装。`fsys.update.dlMgr` 负责检测并下载升级包，而 `fsys.update.app` 负责启动并执行自动更新。

如果需要更进一目自定义检测与下载升级包的界面与交互，以及自动更新的细节，可以参考 fsys.update.simpleMain 库的源代码直接调用 `fsys.update.dlMgr` 与 `fsys.update.app`。

一般情况下直接 fsys.update.simpleMain 就可以了。