Skip to content

Commit 9bfe58f

Browse files
JusterZhuCopilot
andcommitted
Refine Core manifest bootstrap guidance
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 242b504 commit 9bfe58f

3 files changed

Lines changed: 57 additions & 117 deletions

File tree

website/docs/doc/GeneralUpdate.Core.md

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public GeneralUpdateBootstrap SetSource(
177177
string? token = null)
178178
```
179179

180-
`SetSource` 是轻配置入口,适合把应用身份信息放到 `generalupdate.manifest.json` 或运行时发现机制里,只在代码中指定服务端入口和密钥。若需要精确控制清单中的每个身份字段,建议使用后文的 `ManifestInfo.Load().ToUpdateRequest()` 再调用 `SetConfig(request)`
180+
`SetSource` 是轻配置入口,适合把应用身份信息放到 `generalupdate.manifest.json`,只在代码中指定服务端入口和密钥。
181181

182182
```csharp
183183
await new GeneralUpdateBootstrap()
@@ -338,65 +338,45 @@ Tools 生成的 JSON 使用小驼峰字段名,Core 中对应类型是 `Manifes
338338

339339
配置界面的发布样例流程还会调用 `SamplePublisherService.PublishAsync(...)`,把主程序输出、升级程序输出和清单一起组织到可运行样例目录中。因此新手不需要从零手写完整 `UpdateRequest`,可以先用 Tools 生成清单,再在应用代码中补充服务端入口和密钥。
340340

341-
### Core 如何读取清单
341+
### 配合引导类使用
342342

343-
Core 侧提供 `ManifestInfo`
343+
使用清单后,业务代码不需要关心 `MainAppName``ClientVersion``UpdateAppName``UpgradeClientVersion``ProductId``UpdatePath` 这些身份字段,也不需要手动读取 `generalupdate.manifest.json`。引导类启动更新流程时会在内部读取 `InstallPath/generalupdate.manifest.json`,并把清单中的应用身份信息带入后续的版本检查、下载、启动升级程序和版本回写流程。
344344

345-
```csharp
346-
using GeneralUpdate.Core.Configuration;
347-
348-
var manifest = ManifestInfo.Load();
349-
if (manifest == null)
350-
throw new FileNotFoundException("generalupdate.manifest.json was not found.");
351-
352-
var request = manifest.ToUpdateRequest();
353-
request.UpdateUrl = "https://update.example.com/api/upgrade/verification";
354-
request.ReportUrl = "https://update.example.com/api/upgrade/report";
355-
request.AppSecretKey = "your-app-secret";
356-
request.InstallPath = AppDomain.CurrentDomain.BaseDirectory;
345+
默认安装目录就是当前应用目录时,只需要把服务端入口和密钥传给 `SetSource`
357346

347+
```csharp
358348
await new GeneralUpdateBootstrap()
359-
.SetConfig(request)
349+
.SetSource(
350+
updateUrl: "https://update.example.com/api/upgrade/verification",
351+
appSecretKey: "your-app-secret",
352+
reportUrl: "https://update.example.com/api/upgrade/report")
360353
.SetOption(Option.AppType, AppType.Client)
361354
.LaunchAsync();
362355
```
363356

364-
`ManifestInfo.Load()` 默认从 `AppDomain.CurrentDomain.BaseDirectory` 读取清单;`ManifestInfo.Load(path)` 可以从指定文件读取。`ToUpdateRequest()` 会把清单转换成一个最小 `UpdateRequest`,但不会填充服务端地址和密钥。
365-
366-
`ClientStrategy` 在标准工作流开始时也会调用 `AppMetadataDiscoverer.Discover(context)`,从 `InstallPath/generalupdate.manifest.json` 补齐空的身份字段。优先级规则很重要:**代码中已经提供的值优先,清单只补齐空字段**。这意味着你可以用清单作为默认身份来源,同时在特殊环境中用代码覆盖某个字段。
367-
368-
### 推荐配置方式
369-
370-
对业务应用来说,最清晰的方式是“清单提供身份,代码提供服务端和密钥”。
357+
如果应用的实际安装目录不是当前进程基目录,只需要在 `UpdateRequest` 中补充 `InstallPath`,仍然不需要把清单中的身份字段重复写进代码:
371358

372359
```csharp
373360
using GeneralUpdate.Core;
374361
using GeneralUpdate.Core.Configuration;
375362

376-
static UpdateRequest CreateRequestFromManifest()
363+
var request = new UpdateRequest
377364
{
378-
var manifest = ManifestInfo.Load()
379-
?? throw new InvalidOperationException("Missing generalupdate.manifest.json.");
380-
381-
var request = manifest.ToUpdateRequest();
382-
request.UpdateUrl = "https://update.example.com/api/upgrade/verification";
383-
request.ReportUrl = "https://update.example.com/api/upgrade/report";
384-
request.AppSecretKey = Environment.GetEnvironmentVariable("GENERALUPDATE_APP_SECRET")
385-
?? throw new InvalidOperationException("Missing update secret.");
386-
request.InstallPath = AppDomain.CurrentDomain.BaseDirectory;
387-
388-
return request;
389-
}
365+
UpdateUrl = "https://update.example.com/api/upgrade/verification",
366+
ReportUrl = "https://update.example.com/api/upgrade/report",
367+
AppSecretKey = "your-app-secret",
368+
InstallPath = @"C:\Program Files\MyProduct"
369+
};
390370

391371
await new GeneralUpdateBootstrap()
392-
.SetConfig(CreateRequestFromManifest())
372+
.SetConfig(request)
393373
.SetOption(Option.AppType, AppType.Client)
394374
.LaunchAsync();
395375
```
396376

397-
这种写法的好处是
377+
推荐的职责拆分是
398378

399-
| 不再硬编码 | 仍由代码或环境提供 |
379+
| 由 manifest 提供 | 由代码或环境提供 |
400380
| --- | --- |
401381
| `MainAppName``ClientVersion``UpdateAppName``UpgradeClientVersion``ProductId``UpdatePath` | `UpdateUrl``ReportUrl``AppSecretKey``Scheme``Token`、事件、扩展点、运行选项 |
402382

website/i18n/en/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Core.md

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public GeneralUpdateBootstrap SetSource(
175175
string? token = null)
176176
```
177177

178-
`SetSource` is a lightweight entry point when identity metadata is discovered elsewhere, such as from `generalupdate.manifest.json`. When you need precise control over every manifest identity field, prefer `ManifestInfo.Load().ToUpdateRequest()` followed by `SetConfig(request)`.
178+
`SetSource` is a lightweight entry point when identity metadata is provided by `generalupdate.manifest.json`, leaving only the server endpoint and secret in application code.
179179

180180
```csharp
181181
await new GeneralUpdateBootstrap()
@@ -336,65 +336,45 @@ The `GeneralUpdate.Tools` configuration flow parses the main-app and updater `.c
336336

337337
The sample publishing flow in the configuration UI also calls `SamplePublisherService.PublishAsync(...)` to place the main-app output, updater output, and manifest into one runnable sample directory. New users therefore do not need to hand-write a complete `UpdateRequest`: they can generate the manifest with Tools and only add server endpoints and secrets in application code.
338338

339-
### How Core reads the manifest
339+
### Using the manifest with the bootstrap
340340

341-
Core provides `ManifestInfo`:
341+
With the manifest in place, application code does not need to care about identity fields such as `MainAppName`, `ClientVersion`, `UpdateAppName`, `UpgradeClientVersion`, `ProductId`, or `UpdatePath`, and it does not need to load `generalupdate.manifest.json` manually. The bootstrap reads `InstallPath/generalupdate.manifest.json` internally during the update workflow and carries that identity metadata into version checking, downloading, updater launch, and version write-back.
342342

343-
```csharp
344-
using GeneralUpdate.Core.Configuration;
345-
346-
var manifest = ManifestInfo.Load();
347-
if (manifest == null)
348-
throw new FileNotFoundException("generalupdate.manifest.json was not found.");
349-
350-
var request = manifest.ToUpdateRequest();
351-
request.UpdateUrl = "https://update.example.com/api/upgrade/verification";
352-
request.ReportUrl = "https://update.example.com/api/upgrade/report";
353-
request.AppSecretKey = "your-app-secret";
354-
request.InstallPath = AppDomain.CurrentDomain.BaseDirectory;
343+
When the install directory is the current application directory, pass only the server endpoint and secret to `SetSource`:
355344

345+
```csharp
356346
await new GeneralUpdateBootstrap()
357-
.SetConfig(request)
347+
.SetSource(
348+
updateUrl: "https://update.example.com/api/upgrade/verification",
349+
appSecretKey: "your-app-secret",
350+
reportUrl: "https://update.example.com/api/upgrade/report")
358351
.SetOption(Option.AppType, AppType.Client)
359352
.LaunchAsync();
360353
```
361354

362-
`ManifestInfo.Load()` reads from `AppDomain.CurrentDomain.BaseDirectory` by default. `ManifestInfo.Load(path)` reads a specific file. `ToUpdateRequest()` converts the manifest into a minimal `UpdateRequest`, but it does not populate server URLs or secrets.
363-
364-
At the beginning of the standard workflow, `ClientStrategy` also calls `AppMetadataDiscoverer.Discover(context)` and fills empty identity fields from `InstallPath/generalupdate.manifest.json`. The precedence rule matters: **values already provided in code win; the manifest only fills empty fields**. This lets you use the manifest as the default identity source while still overriding individual fields in special environments.
365-
366-
### Recommended configuration pattern
367-
368-
For application code, the clearest pattern is "manifest for identity, code/environment for server and secrets".
355+
If the actual install directory is not the current process base directory, provide `InstallPath` through `UpdateRequest` while still keeping manifest identity fields out of code:
369356

370357
```csharp
371358
using GeneralUpdate.Core;
372359
using GeneralUpdate.Core.Configuration;
373360

374-
static UpdateRequest CreateRequestFromManifest()
361+
var request = new UpdateRequest
375362
{
376-
var manifest = ManifestInfo.Load()
377-
?? throw new InvalidOperationException("Missing generalupdate.manifest.json.");
378-
379-
var request = manifest.ToUpdateRequest();
380-
request.UpdateUrl = "https://update.example.com/api/upgrade/verification";
381-
request.ReportUrl = "https://update.example.com/api/upgrade/report";
382-
request.AppSecretKey = Environment.GetEnvironmentVariable("GENERALUPDATE_APP_SECRET")
383-
?? throw new InvalidOperationException("Missing update secret.");
384-
request.InstallPath = AppDomain.CurrentDomain.BaseDirectory;
385-
386-
return request;
387-
}
363+
UpdateUrl = "https://update.example.com/api/upgrade/verification",
364+
ReportUrl = "https://update.example.com/api/upgrade/report",
365+
AppSecretKey = "your-app-secret",
366+
InstallPath = @"C:\Program Files\MyProduct"
367+
};
388368

389369
await new GeneralUpdateBootstrap()
390-
.SetConfig(CreateRequestFromManifest())
370+
.SetConfig(request)
391371
.SetOption(Option.AppType, AppType.Client)
392372
.LaunchAsync();
393373
```
394374

395-
This keeps the split explicit:
375+
The recommended responsibility split is:
396376

397-
| No longer hard-coded | Still provided by code or environment |
377+
| Provided by manifest | Provided by code or environment |
398378
| --- | --- |
399379
| `MainAppName`, `ClientVersion`, `UpdateAppName`, `UpgradeClientVersion`, `ProductId`, `UpdatePath` | `UpdateUrl`, `ReportUrl`, `AppSecretKey`, `Scheme`, `Token`, events, extension points, runtime options |
400380

website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/doc/GeneralUpdate.Core.md

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public GeneralUpdateBootstrap SetSource(
177177
string? token = null)
178178
```
179179

180-
`SetSource` 是轻配置入口,适合把应用身份信息放到 `generalupdate.manifest.json` 或运行时发现机制里,只在代码中指定服务端入口和密钥。若需要精确控制清单中的每个身份字段,建议使用后文的 `ManifestInfo.Load().ToUpdateRequest()` 再调用 `SetConfig(request)`
180+
`SetSource` 是轻配置入口,适合把应用身份信息放到 `generalupdate.manifest.json`,只在代码中指定服务端入口和密钥。
181181

182182
```csharp
183183
await new GeneralUpdateBootstrap()
@@ -338,65 +338,45 @@ Tools 生成的 JSON 使用小驼峰字段名,Core 中对应类型是 `Manifes
338338

339339
配置界面的发布样例流程还会调用 `SamplePublisherService.PublishAsync(...)`,把主程序输出、升级程序输出和清单一起组织到可运行样例目录中。因此新手不需要从零手写完整 `UpdateRequest`,可以先用 Tools 生成清单,再在应用代码中补充服务端入口和密钥。
340340

341-
### Core 如何读取清单
341+
### 配合引导类使用
342342

343-
Core 侧提供 `ManifestInfo`
343+
使用清单后,业务代码不需要关心 `MainAppName``ClientVersion``UpdateAppName``UpgradeClientVersion``ProductId``UpdatePath` 这些身份字段,也不需要手动读取 `generalupdate.manifest.json`。引导类启动更新流程时会在内部读取 `InstallPath/generalupdate.manifest.json`,并把清单中的应用身份信息带入后续的版本检查、下载、启动升级程序和版本回写流程。
344344

345-
```csharp
346-
using GeneralUpdate.Core.Configuration;
347-
348-
var manifest = ManifestInfo.Load();
349-
if (manifest == null)
350-
throw new FileNotFoundException("generalupdate.manifest.json was not found.");
351-
352-
var request = manifest.ToUpdateRequest();
353-
request.UpdateUrl = "https://update.example.com/api/upgrade/verification";
354-
request.ReportUrl = "https://update.example.com/api/upgrade/report";
355-
request.AppSecretKey = "your-app-secret";
356-
request.InstallPath = AppDomain.CurrentDomain.BaseDirectory;
345+
默认安装目录就是当前应用目录时,只需要把服务端入口和密钥传给 `SetSource`
357346

347+
```csharp
358348
await new GeneralUpdateBootstrap()
359-
.SetConfig(request)
349+
.SetSource(
350+
updateUrl: "https://update.example.com/api/upgrade/verification",
351+
appSecretKey: "your-app-secret",
352+
reportUrl: "https://update.example.com/api/upgrade/report")
360353
.SetOption(Option.AppType, AppType.Client)
361354
.LaunchAsync();
362355
```
363356

364-
`ManifestInfo.Load()` 默认从 `AppDomain.CurrentDomain.BaseDirectory` 读取清单;`ManifestInfo.Load(path)` 可以从指定文件读取。`ToUpdateRequest()` 会把清单转换成一个最小 `UpdateRequest`,但不会填充服务端地址和密钥。
365-
366-
`ClientStrategy` 在标准工作流开始时也会调用 `AppMetadataDiscoverer.Discover(context)`,从 `InstallPath/generalupdate.manifest.json` 补齐空的身份字段。优先级规则很重要:**代码中已经提供的值优先,清单只补齐空字段**。这意味着你可以用清单作为默认身份来源,同时在特殊环境中用代码覆盖某个字段。
367-
368-
### 推荐配置方式
369-
370-
对业务应用来说,最清晰的方式是“清单提供身份,代码提供服务端和密钥”。
357+
如果应用的实际安装目录不是当前进程基目录,只需要在 `UpdateRequest` 中补充 `InstallPath`,仍然不需要把清单中的身份字段重复写进代码:
371358

372359
```csharp
373360
using GeneralUpdate.Core;
374361
using GeneralUpdate.Core.Configuration;
375362

376-
static UpdateRequest CreateRequestFromManifest()
363+
var request = new UpdateRequest
377364
{
378-
var manifest = ManifestInfo.Load()
379-
?? throw new InvalidOperationException("Missing generalupdate.manifest.json.");
380-
381-
var request = manifest.ToUpdateRequest();
382-
request.UpdateUrl = "https://update.example.com/api/upgrade/verification";
383-
request.ReportUrl = "https://update.example.com/api/upgrade/report";
384-
request.AppSecretKey = Environment.GetEnvironmentVariable("GENERALUPDATE_APP_SECRET")
385-
?? throw new InvalidOperationException("Missing update secret.");
386-
request.InstallPath = AppDomain.CurrentDomain.BaseDirectory;
387-
388-
return request;
389-
}
365+
UpdateUrl = "https://update.example.com/api/upgrade/verification",
366+
ReportUrl = "https://update.example.com/api/upgrade/report",
367+
AppSecretKey = "your-app-secret",
368+
InstallPath = @"C:\Program Files\MyProduct"
369+
};
390370

391371
await new GeneralUpdateBootstrap()
392-
.SetConfig(CreateRequestFromManifest())
372+
.SetConfig(request)
393373
.SetOption(Option.AppType, AppType.Client)
394374
.LaunchAsync();
395375
```
396376

397-
这种写法的好处是
377+
推荐的职责拆分是
398378

399-
| 不再硬编码 | 仍由代码或环境提供 |
379+
| 由 manifest 提供 | 由代码或环境提供 |
400380
| --- | --- |
401381
| `MainAppName``ClientVersion``UpdateAppName``UpgradeClientVersion``ProductId``UpdatePath` | `UpdateUrl``ReportUrl``AppSecretKey``Scheme``Token`、事件、扩展点、运行选项 |
402382

0 commit comments

Comments
 (0)