# バッチ設計書 67-Lock-CascadiaFont.ps1

## 概要

本ドキュメントは、Cascadiaフォントファイルのロックを試行するデバッグ用スクリプト `Lock-CascadiaFont.ps1` のバッチ設計書である。フォントキャッシュサービスの問題（GH#9375）を再現するために作成されたが、DirectWriteがロック状態でもフォントを使用可能であることが判明し、未完成のまま参考用に残されている。

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

本スクリプトは、Cascadia Code/MonoフォントファイルをWin32 API（LockFileEx）で排他ロックし、フォントキャッシュサービスを再起動することで、フォントの使用に関する問題（GH#9375）を再現しようとするデバッグ用スクリプトである。

**業務上の目的・背景**：GitHub Issue #9375で報告されたフォントキャッシュサービスの問題を調査するために作成された。この問題では、フォントキャッシュサービスがフォントの存在を報告するにもかかわらず、実際にはフォントを使用できないという現象が発生していた。本スクリプトはフォントファイルをロックすることでこの状態を再現しようとしたが、DirectWriteはファイルロック状態でもフォントを正常に使用可能であることが判明し、問題の再現には至らなかった。スクリプトは参考情報として残されている。

**バッチの実行タイミング**：デバッグ/調査目的で開発者が手動で実行する。管理者権限が必要。

**主要な処理内容**：
1. Win32 APIのLockFileExをP/InvokeでPowerShellから呼び出せるようにする（Add-Type）
2. レジストリからCascadiaフォントのファイルパスを取得する
3. ハードコードされたシステムフォントパス（C:\Windows\Fonts）からも追加でパスを収集する
4. 各フォントファイルをReadWriteShareモードでオープンし、LockFileExで排他ロックをかける
5. フォントキャッシュサービス（FontCache）を再起動する
6. ユーザーのキー入力を待機し、キー入力後にロックを解除する（finallyブロック）

**前後の処理との関連**：単独で実行されるデバッグスクリプトであり、他のバッチとの連携はない。GH#9375の調査用途のみ。

**影響範囲**：Cascadiaフォントファイルへの排他ロック、FontCacheサービスの再起動に影響する。管理者権限を必要とし、システムサービスを操作する。

## バッチ種別

デバッグ / 調査ツール（未完成）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（デバッグ時のみ） |
| 実行時刻 | 手動実行 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 開発者による手動実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| 管理者権限 | `#Requires -RunAsAdministrator` により管理者として実行が必須 |
| Windows環境 | Win32 API（LockFileEx）を使用するためWindows環境が必須 |
| Cascadiaフォントインストール済み | CascadiaCode/Monoフォントがシステムにインストールされていること |

### 実行可否判定

管理者権限で実行されていること。Cascadiaフォントが少なくとも1つインストールされていること。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | 本スクリプトはパラメータを受け取らない |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| レジストリ | WindowsRegistry | `HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Fonts\*` からCascadiaフォントパスを取得 |
| ファイルシステム | ttfファイル | `C:\Windows\Fonts\` 配下のCascadiaフォントファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | テキスト | キー入力待機メッセージ |
| 標準エラー | テキスト | フォントロック失敗時のエラーメッセージ |

### 出力ファイル仕様

ファイル出力はなし。

| 項目 | 内容 |
|-----|------|
| ファイル名 | 該当なし |
| 出力先 | 標準出力/標準エラー |
| 文字コード | UTF-8 |
| 区切り文字 | 該当なし |

## 処理フロー

### 処理シーケンス

```
1. Win32 API型定義
   └─ Add-TypeでLockFileEx, OVERLAPPED構造体を定義
2. Lock-File関数定義
   └─ ファイルをReadWriteShareモードでオープン
   └─ LockFileExで排他ロックを取得
3. レジストリからフォントパス取得
   └─ HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Fonts\* から
   └─ "Cascadia"で始まるプロパティのValueを収集
4. システムフォントパスからフォントパス追加
   └─ CascadiaCode.ttf, CascadiaCodeItalic.ttf, CascadiaMono.ttf, CascadiaMonoItalic.ttf
   └─ Test-Pathで存在確認
5. フォントファイルのロック
   └─ 各フォントファイルに対してLock-File実行
   └─ エラー時はWrite-Errorで通知（処理は続行）
6. FontCacheサービス再起動
   └─ Restart-Service FontCache
7. キー入力待機
   └─ "Press any key to unlock the font files..."
8. クリーンアップ（finally）
   └─ 全ハンドルのClose()を呼び出しロック解除
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[Win32 API型定義（Add-Type）]
    B --> C[Lock-File関数定義]
    C --> D[レジストリからCascadiaフォントパス取得]
    D --> E[システムフォントパスから追加取得]
    E --> F[try: 各フォントファイルをロック]
    F --> G{ロック成功?}
    G -->|Yes| H[次のフォント]
    G -->|No| I[Write-Error]
    I --> H
    H --> J[Restart-Service FontCache]
    J --> K[キー入力待機]
    K --> L[finally: 全ハンドルClose]
    L --> M[バッチ終了]
```

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

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

データベース操作は行わない。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | - | - | - |

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限不足 | 管理者権限なしで実行した場合 | 管理者としてPowerShellを起動する |
| - | LockFileEx失敗 | ファイルロックに失敗した場合 | "Failed to lock file" をthrow |
| - | フォント未検出 | Cascadiaフォントがインストールされていない場合 | Cascadiaフォントをインストールする |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

### 障害時対応

try-finallyブロックにより、エラー発生時でもfinallyブロックで全ファイルハンドルのClose()が確実に実行される。FontCacheサービスが再起動済みの場合、サービスの状態を確認する。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | try-finallyによるリソース管理 |
| コミットタイミング | 該当なし |
| ロールバック条件 | finallyブロックでファイルハンドルを必ず解放 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数件のフォントファイル |
| 目標処理時間 | 数秒（サービス再起動時間を含む） |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

フォントファイルに対してLOCKFILE_EXCLUSIVE_LOCKで排他ロックを取得する。ロックはキー入力まで保持され、finallyブロックで解放される。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| Host出力 | ロック完了後 | `Press any key to unlock the font files...` |
| エラーログ | ロック失敗時 | 各フォントファイルのロック失敗メッセージ |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 該当なし | - | - |

## 備考

- **本スクリプトは未完成（実験失敗）のまま参考用に残されている**
- スクリプト冒頭のコメントに「failed attempt」「doesn't work」と明記されている
- DirectWriteはファイルロック状態でもフォントを使用可能であるため、問題の再現には至らなかった
- GH#9375: フォントキャッシュサービスがフォントの存在を報告するが使用できない問題
- P/Invoke（Add-Type）によりkernel32.dllのLockFileExをPowerShellから呼び出している
- FileShareモードはReadWriteを指定しており、他プロセスからの読み書きアクセスは許可しつつ、LockFileExで排他ロックをかけている
- ソースファイル: `tools/Lock-CascadiaFont.ps1`
