# バッチ設計書 46-New-UnpackagedTerminalDistribution

## 概要

Terminal AppXとXAML AppXから非パッケージ版（ポータブル版）のTerminalディストリビューションを作成するPowerShellスクリプトの設計書である。

### 本バッチの処理概要

本バッチは、Windows Terminal AppXパッケージとMicrosoft.UI.Xaml AppXパッケージをアンパックし、不要なファイルを除去してXAML DLLを統合した上で、リソース（PRI）のマージを行い、最終的にZIPアーカイブとしてポータブル版Terminalディストリビューションを生成する。AppXパラメータセットとLayoutパラメータセットの2つの入力モードをサポートする。

**業務上の目的・背景**：Windows Terminalの非パッケージ版（ポータブル版）は、Microsoft Store経由でインストールできない環境やUSBメモリでの持ち運び用途に対応するために必要である。AppXパッケージから必要なファイルのみを抽出し、スタンドアロンで動作するディストリビューションを構築する。

**バッチの実行タイミング**：リリースビルド時にCI/CDパイプラインから実行される。

**主要な処理内容**：
1. Terminal AppXのアンパック（AppXモード）またはレイアウトディレクトリのコピー（Layoutモード）
2. XAML AppXのアンパック
3. XAMLパッケージのサニティチェック（名前・アーキテクチャ検証）
4. 不要ファイルの除去（*.xml, *.winmd, Appx*, タイル/ロゴ画像等）
5. XAML DLL・ディレクトリのコピー
6. TerminalとXAMLのリソース（PRI）マージ（Merge-TerminalAndXamlResources.ps1呼び出し）
7. ポータブルモードマーカーファイルの作成（オプション）
8. ZIPアーカイブの生成（AppXモード）またはディレクトリの返却（Layoutモード）

**前後の処理との関連**：Merge-TerminalAndXamlResources.ps1（No.50）を内部で呼び出す。前提としてTerminal AppXとXAML AppXのビルドが完了していること。

**影響範囲**：リリース配布用のポータブル版Terminal ZIPファイルが生成される。

## バッチ種別

パッケージング（ポータブル版ディストリビューション作成）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（リリースビルド時） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | CI/CDパイプライン |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Terminal AppX/Layoutの存在 | Terminal AppXファイルまたはLayoutディレクトリが存在すること |
| XAML AppXの存在 | Microsoft.UI.Xaml AppXファイルが存在すること |
| MakeAppx.exeの存在 | Windows SDK内のMakeAppx.exe（x64版）が利用可能であること |
| Merge-TerminalAndXamlResources.ps1の存在 | 同一ディレクトリにPRIマージスクリプトが存在すること |

### 実行可否判定

パラメータセット（AppXまたはLayout）に応じた必須パラメータが指定され、MakeAppx.exeが存在すること。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| TerminalAppX | string | Yes（AppXセット） | なし | Terminal AppXファイルのパス |
| TerminalLayout | string | Yes（Layoutセット） | なし | Terminalレイアウトデプロイメントディレクトリのパス |
| XamlAppX | string | Yes | なし | XAML AppXファイルのパス |
| Destination | string | No | "." | 出力先ディレクトリ |
| MakeAppxPath | string | No | C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\MakeAppx.exe | MakeAppx.exeのパス |
| PortableMode | switch | No | AppXモード:$false / Layoutモード:$true | ポータブルモードマーカーファイルを含めるかどうか |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Terminal AppX | .appx / .msix | Windows Terminalアプリケーションパッケージ |
| XAML AppX | .appx / .msix | Microsoft.UI.Xamlランタイムパッケージ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Destination/{PFN}_{Version}_{Arch}.zip | ZIP | ポータブル版Terminalディストリビューション（AppXモード） |
| 作業ディレクトリ/terminal-{Version} | ディレクトリ | ポータブル版Terminalディレクトリ（Layoutモード） |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | {PackageFamilyName}_{Version}_{Architecture}.zip |
| 出力先 | Destinationパラメータで指定 |
| 文字コード | N/A（バイナリ/ZIP形式） |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. MakeAppx.exeの存在確認
   └─ 存在しない場合はエラー終了（Exit 1）
2. 一時ディレクトリの作成
   └─ システムTEMPディレクトリにランダム名で作成
3. AppxManifest.xmlの読み取り
   └─ AppXモード: tar.exeでAppxManifest.xmlを抽出
   └─ Layoutモード: レイアウトディレクトリから直接読み取り
   └─ PackageFamilyName、Version、ProcessorArchitectureを取得
4. Terminal AppXのアンパック
   └─ AppXモード: MakeAppx.exe unpackで展開
   └─ Layoutモード: Copy-Itemでコピー
5. XAML AppXのアンパック
   └─ MakeAppx.exe unpackで展開
6. XAMLパッケージのサニティチェック
   └─ パッケージ名がMicrosoft.UI.Xaml*であること
   └─ ProcessorArchitectureがTerminalと一致すること
7. 不要ファイルの除去
   └─ *.xml, *.winmd, Appx*, Images/*Tile*, Images/*Logo*を削除
8. XAMLファイルのコピー
   └─ Microsoft.UI.Xaml.dll, Microsoft.UI.Xamlディレクトリをコピー
9. リソース（PRI）のマージ
   └─ Merge-TerminalAndXamlResources.ps1を呼び出し
10. ポータブルモードマーカーの作成（PortableMode指定時）
    └─ .portableファイルを生成
11. パッケージング
    └─ AppXモード: tar -c --format=zipでZIP作成、一時ディレクトリ削除
    └─ Layoutモード: ディレクトリパスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{MakeAppx.exe存在?}
    B -->|なし| C[エラー終了]
    B -->|あり| D[一時ディレクトリ作成]
    D --> E[AppxManifest.xml読み取り]
    E --> F{パラメータセット}
    F -->|AppX| G[MakeAppx unpackでTerminal展開]
    F -->|Layout| H[レイアウトディレクトリをコピー]
    G --> I[MakeAppx unpackでXAML展開]
    H --> I
    I --> J[XAMLサニティチェック]
    J --> K[不要ファイル除去]
    K --> L[XAMLファイルコピー]
    L --> M[PRIマージ]
    M --> N{PortableMode?}
    N -->|Yes| O[.portableファイル作成]
    N -->|No| P{パラメータセット}
    O --> P
    P -->|AppX| Q[ZIP作成・一時ディレクトリ削除]
    P -->|Layout| R[ディレクトリ返却]
    Q --> S[バッチ終了]
    R --> S
```

## データベース操作仕様

### 操作別データベース影響一覧

本バッチではデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Exit 1 | MakeAppx未検出 | MakeAppxPathにMakeAppx.exeが存在しない | Windows SDKをインストール |
| Throw | アンパック失敗 | Terminal/XAML AppXのアンパックに失敗 | AppXファイルの整合性を確認 |
| Throw | XAML検証失敗 | XAMLパッケージ名がMicrosoft.UI.Xaml*でない | 正しいXAML AppXを指定 |
| Throw | アーキテクチャ不一致 | Terminal/XAMLのアーキテクチャが異なる | 同一アーキテクチャのパッケージを使用 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（リトライ機構なし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

入力AppXファイルの存在とアーキテクチャの一致を確認してから再実行する。一時ディレクトリが残っている場合は手動で削除する。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A |
| コミットタイミング | ZIP生成完了時 |
| ロールバック条件 | N/A（失敗時は一時ディレクトリが残る可能性あり） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1セットのAppXファイル |
| 目標処理時間 | 数分以内 |
| メモリ使用量上限 | AppXファイルサイズ依存 |

## 排他制御

同一出力ファイルに対して同時実行しないこと。一時ディレクトリはランダム名で作成されるため衝突は発生しにくい。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| MakeAppx出力 | unpack実行時 | アンパック処理の詳細 |
| Verbose | PRIマージ時 | Verboseパラメータが有効な場合の詳細出力 |
| エラーメッセージ | 各種チェック失敗時 | 具体的なエラー内容 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ビルド失敗 | N/A | CI/CDパイプライン |

## 備考

- $ErrorActionPreference = 'Stop'が設定されており、未処理のエラーは即座にスクリプトを停止させる。
- 除去対象ファイルリスト: `*.xml`, `*.winmd`, `Appx*`, `Images/*Tile*`, `Images/*Logo*`
- XAMLからコピーするファイル: `Microsoft.UI.Xaml.dll`, `Microsoft.UI.Xaml`ディレクトリ（.winmdは不要）
- MakeAppxPathのデフォルトはx64版（No.45のCreate-AppxBundle.ps1はx86版を使用）。
- PortableModeスイッチのデフォルト値はパラメータセットに依存する（Layoutモードではデフォルトで有効）。
- ソースファイルパス: `build/scripts/New-UnpackagedTerminalDistribution.ps1`
