# 通知設計書 18-ファイル移動エラー通知

## 概要

本ドキュメントは、StaxRipアプリケーションにおける「ファイル移動エラー通知（Could not move file）」の設計仕様を記述する。

### 本通知の処理概要

この通知は、FrameServerモジュールでツールファイル（エンコーダー等）を別のディレクトリに移動する際に、移動処理が失敗した場合にユーザーにエラー情報を表示する機能を提供する。

**業務上の目的・背景**：StaxRipはAviSynthのポータブル/インストール済み状態に応じて、ffmpegやx264/x265などのエンコーダーファイルを適切なディレクトリに配置する必要がある。この配置処理（ファイル移動）が失敗した場合、エンコード処理に支障をきたす可能性があるため、ユーザーにエラーを通知して問題を認識させる必要がある。

**通知の送信タイミング**：FrameServer.MoveFilesメソッドにおいて、FileHelp.Move()が例外をスローした場合に通知が発生する。具体的にはFrameServer.vbの行528-530でCatch句内で発生する。

**通知の受信者**：StaxRipアプリケーションを操作している現在のユーザー（エンドユーザー）。モーダルダイアログとして表示される。

**通知内容の概要**：エラーメッセージとして「Could not move file from: {ソースパス} to: {宛先パス} {例外メッセージ}」という形式で、移動元・移動先のパスと例外の詳細情報が表示される。

**期待されるアクション**：ユーザーはエラーメッセージを確認し、以下のような対処を行うことが期待される。(1) ファイルが他のプロセスで使用されていないか確認する、(2) 書き込み権限を確認する、(3) ディスク容量を確認する、(4) 手動でファイルを移動する。

## 通知種別

アプリ内通知（モーダルダイアログ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（エラー通知） |
| リトライ | 無 |

### 送信先決定ロジック

現在StaxRipアプリケーションを操作しているユーザーに対して、モーダルダイアログとして直接表示される。

## 通知テンプレート

### ダイアログ通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | Error |
| アイコン | Error |
| ボタン | OK |

### 本文テンプレート

```
Could not move file from:

{SourcePath}

to:

{DestPath}

{ExceptionMessage}
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| SourcePath | 移動元ファイルパス | src変数 | Yes |
| DestPath | 移動先ファイルパス | dest変数 | Yes |
| ExceptionMessage | 例外メッセージ | ex.Message | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | ファイル移動実行 | FileHelp.Move()が例外をスロー | ファイル移動処理が失敗した場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 例外が発生しない | ファイル移動が成功した場合は通知しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[FrameServer.MoveFiles呼び出し] --> B[For Each name In fileNames]
    B --> C[src = Path.Combine#40;srcDir, name#41;]
    C --> D[dest = Path.Combine#40;targetDir, name#41;]
    D --> E[Try FileHelp.Move#40;src, dest#41;]
    E --> F{例外発生?}
    F -->|No| G[次のファイルへ]
    F -->|Yes| H[Catch ex As Exception]
    H --> I[MsgError表示]
    I --> G
    G --> J{全ファイル処理完了?}
    J -->|No| B
    J -->|Yes| K[処理終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

データベースは使用しない。

### 更新テーブル一覧

データベースは使用しない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| IOException | ファイルが使用中 | MsgError表示、次のファイル処理へ |
| UnauthorizedAccessException | アクセス権限不足 | MsgError表示、次のファイル処理へ |
| DirectoryNotFoundException | ディレクトリ不存在 | MsgError表示、次のファイル処理へ |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（処理に応じて随時表示）

## セキュリティ考慮事項

- ファイルパスがメッセージに含まれるため、ディレクトリ構造が露出する
- 例外メッセージにはシステム情報が含まれる可能性がある

## 備考

- MoveFilesメソッドはAviSynthToolPath()から呼び出される
- エラーが発生しても処理は中断されず、次のファイルの移動を試みる
- 主な呼び出し元はffmpeg, x264, x265のファイル移動処理
- ファイル移動は同一ドライブ内で行われることが想定されている

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: MoveFilesメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FrameServer.vb | `Source/Video/FrameServer.vb` | MoveFilesメソッド（行522-533） |

**主要処理フロー**:
1. **行522**: Shared Sub MoveFiles(srcDir, targetDir, fileNames())
2. **行523**: For Each name In fileNames
3. **行524-525**: srcとdestのパスを生成
4. **行526**: Try
5. **行527**: FileHelp.Move(src, dest)
6. **行528-530**: **通知発生箇所** - Catch ex As Exception → MsgError呼び出し
7. **行531**: End Try
8. **行532**: Next

#### Step 2: 呼び出し元を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FrameServer.vb | `Source/Video/FrameServer.vb` | AviSynthToolPath()メソッド（行535以降） |

**読解のコツ**: AviSynthToolPathメソッドが、AviSynthのポータブル/インストール状態に応じてffmpeg, x264, x265のファイルを適切な場所に移動していることを把握する。

### プログラム呼び出し階層図

```
FrameServer.AviSynthToolPath()
    │
    ├─ [IsAviSynth() = False] → Exit Sub
    │
    ├─ [ffmpeg移動が必要な場合]
    │      └─ MoveFiles(Package.ffmpeg.Directory, targetFolder, {Package.ffmpeg.Filename, "ffmpeg Help.txt"})
    │             │
    │             └─ FileHelp.Move()
    │                    │
    │                    ├─ [成功] → 次のファイルへ
    │                    │
    │                    └─ [例外] → MsgError("Could not move file from:...")
    │
    ├─ [x264移動が必要な場合]
    │      └─ MoveFiles(...)
    │
    └─ [x265移動が必要な場合]
           └─ MoveFiles(...)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

srcDir ─────────────────▶ Path.Combine(srcDir, name)
        │                     │
        │                     ▼
        │                  src パス
        │                     │
targetDir ──────────────▶ Path.Combine(targetDir, name)
        │                     │
        │                     ▼
        │                  dest パス
        │                     │
        ▼                     ▼
fileNames[] ────────────▶ FileHelp.Move(src, dest)
                               │
                               ├─ [成功] ───────────────▶ ファイル移動完了
                               │
                               └─ [例外]
                                      │
                                      ▼
                                   MsgError表示
                                   (src, dest, ex.Message含む)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FrameServer.vb | `Source/Video/FrameServer.vb` | ソース | フレームサーバー管理（行529-530が通知発生箇所） |
| FileHelp.vb | `Source/General/FileHelp.vb` | ソース | ファイル操作ヘルパー（Move関数） |
| Package.vb | `Source/General/Package.vb` | ソース | パッケージ情報（ffmpeg, x264, x265等） |
| Msg.vb | `Source/UI/Msg.vb` | ソース | MsgError関数の定義 |
