自動アップデート¶
この節の要旨 GitHub Releases をソースにした無停止アップデート機構。チェック → ダウンロード → 展開 → ユーザー同意 → 終了時適用 → 再起動という段階制御で、ユーザーが明示的に承認するまで実ファイルは書き換えられません。
構成¶
| 構成要素 | 役割 |
|---|---|
UpdateService |
チェック・ダウンロード・展開と、適用するファイルの準備を担当 |
| 更新の通知 | 更新の準備ができると、ステータスバー直上・中央寄せのバナーを出す。再起動ボタンと閉じるボタン付き |
設定(settings.json) |
AutoUpdateEnabled, LastUpdateCheck, SkippedVersions — チェック間隔・最終チェック時刻・スキップ済みバージョン一覧 |
チェックと取得フロー¶
- 自動チェック:
UpdateService.Initialize()がAutoUpdateEnabled==trueのときTimerを生成し、起動 30 秒後に初回、以後 4 時間間隔でバックグラウンドチェックを実行。rate limit 対策として前回チェックから 30 分以内はスキップ(_lastCheckUtcでガード)。 - 手動チェック: Control Deck → このアプリについて → 「アップデートを確認」で
CheckForUpdatesAsync()を即時呼び出し。結果はトーストとUpdateStatusプロパティで表示。 - バージョン照会の二段構え:
- 第一優先は Cloudflare Worker(
VersionCheckUrl)。GitHub API rate limit を回避するためのキャッシュ層。 - Worker が
errorプロパティを返した/HTTP 失敗した場合、GitHub API (releases/latest) へ自動フォールバック(CheckGitHubDirectAsync)。 - ダウンロードタイプの優先順位(
Auto指定時): - 差分版 (delta) —
DeltaFromVersion == AppVersionが一致するときのみ使用 - 完全版 (full) — 上記が使えない場合のフォールバック
バージョンを飛ばして更新した場合は delta が一致しないため、自動的に完全版になります。また、プログラム本体の置き場所が変わる前のバージョンから更新する場合も、必要なファイルが揃わないため常に完全版が選ばれます(
ResolveDownloadType)。 - ダウンロード進捗:
_downloadClient(API ヘッダーなし、タイムアウト 5 分)でストリーム受信し、GlowBar(10〜74%)で可視化。受信後はZipFile.ExtractToDirectoryで一時ディレクトリ(TempUpdateDir)に展開。展開完了時にIsReadyToRestart = trueとRaiseStateChanged()。
ユーザー同意ゲート(v0.45.1 以降)¶
再起動ポップアップがユーザー操作で閉じられる前にアプリが終了しても、黙って更新が適用されることはありません。
UpdateService.UserConsentedToApplyフラグはApplyAndRestart()(=ポップアップ「再起動」ボタン押下時)でのみtrueになる。- アプリ終了時の
App_Exit → UpdateService.ApplyOnExit()はif (!IsReadyToRestart || !UserConsentedToApply) return;のガードで動作。 - ユーザーが同意せずに閉じた場合、次回起動時の 30 秒タイマーで再度チェックが走り、同じポップアップが再出現する(ダウンロード済みの展開物は
TempUpdateDirに残置)。
適用バッチと再起動通知¶
LaunchUpdateBatch()が生成した.batがxcopy /s /y /qでextracted/内をappDirに上書きコピーし、新バイナリで再起動。- 再起動後のプロセスは
--updatedコマンドライン引数付きで起動し、アプリがこれを検出して「アップデートが完了しました(vX.Y.Z)」トーストを表示。同時にCleanupTempFiles()で旧キャッシュを削除。
スキップ機能¶
バージョン通知ダイアログで「このバージョンをスキップ」を選択すると、対象バージョンが WindowSettings.SkippedVersions に追加され、以後の自動チェックでは通知されません(手動チェックには表示される)。
トラブルシュート¶
| 症状 | 原因と対処 |
|---|---|
| ポップアップが出ない | ログ(data/logs/*.log)で [Update] StateChanged raised と [Update] ShowRestartPopup called が出ているか確認。出ていない場合は _updateServiceSubscribed 未初期化の疑い |
| 「rate limit」ログが出る | Worker 経由ではなく GitHub API 直接呼出でレート上限超過。次回チェックが 6 時間後に自動延長される。rate limit 中のダウンロードはブラウザで Releases ページを開くフォールバックに切り替わる |
| 再起動しても更新が反映されない | 適用バッチがアンチウイルスにブロックされた可能性。data/logs/ の [Update] ApplyAndRestart と [Update] ApplyOnExit ログで IsReadyToRestart / UserConsentedToApply の値を確認 |
| 自動アップデートを完全に止めたい | Control Deck → このアプリについて → 「自動アップデートを有効にする」を OFF。WindowSettings.AutoUpdateEnabled = false が保存され、タイマーは SetEnabled(false) で停止 |
ログ仕様¶
アップデート関連の主要ログプレフィックスは [Update]。v0.45.1 以降で以下のポイントに明示ログが追加されました。
[Update] 定期チェック開始 / 結果: hasUpdate=...[Update] {typeLabel} (v... → v...)— ダウンロード開始[Update] ダウンロード&展開完了 IsReadyToRestart=true[Update] StateChanged raised: IsDownloading=..., IsReadyToRestart=..., AvailableVersion=...[Update] ShowRestartPopup called from {source}, version=...[Update] ApplyAndRestart: ユーザー承認済み、バッチ起動[Update] ApplyOnExit: IsReadyToRestart=..., UserConsentedToApply=...