Skip to content

アーキテクチャ

モジュール構成

text
src/Launcher/
├── Core/           ドメインモデル・ビジネスロジック
├── Infrastructure/ 基盤ユーティリティ
├── UI/             WinFormsフォーム群
├── Win32/          Win32 API連携
└── Updater/        自動更新機能

モジュール分割の設計意図

  • Core — UIフレームワーク(WinForms)に依存しない純粋なドメインモデルとロジックを置く。 テスト容易性と関心の分離が目的である
  • Infrastructure — アプリケーション基盤。シリアライズ・パス操作・ファイル操作など、 ドメインやUIに属さない横断的関心事を集約する。PathHelperはパス文字列操作のみ、 FileHelperはファイル・ディレクトリ操作と役割を分離している
  • UI — WinFormsに依存するフォーム群。ロジックはPresenterに委譲し、フォーム自体は表示と入力の橋渡しに徹する
  • Win32 — P/Invoke呼び出しを隔離するモジュール。 Win32 APIの複雑さ(マーシャリング、リソース管理)をアプリケーション本体から遮断する。 Shell API呼び出し(プロセス起動・アイコン取得・ショートカット操作・Shellコンテキストメニュー表示等)をここへ集約する
  • Updater — 自動更新機能。GitHub Releases APIとの通信、ZIPの展開、バッチスクリプトによる自己置換など、 更新特有の処理を分離する

主要な設計パターン

Presenterパターン

CommandLauncherPresenter / ButtonLauncherPresenter / SchedulerPresenter / MemoPresenterがUIロジックを担当する。 WinFormsのフォームクラスはイベントハンドラとコントロール操作のみを持ち、判断ロジックはPresenterに委譲する。 UIロジックをWinFormsから分離してテスト可能にする設計である。

ConfigStore継承による永続化

ConfigStoreを継承するクラスはXMLシリアライズで永続化される。 対象はConfig・CommandList・ButtonLauncherData・SchedulerData・Data・MemoDataである。 ConfigStoreは原子的なファイル保存(一時ファイルに書き込み後File.Moveで置換)を提供し、 保存中のクラッシュによるデータ破損を防止する。

ApplicationHostFormによるIPCハブ

ApplicationHostFormは不可視の常駐フォームで、アプリケーション全体のハブとして機能する。 WM_APPMSGによるプロセス間通信(/close、/restart等のコマンドライン引数の処理)を受け付ける。 加えて、子フォーム(CommandLauncherForm、ButtonLauncherForm、MemoForm)のライフサイクルを管理する。 WinFormsのメッセージループを維持するために常駐フォームが必要であり、 CommandLauncherFormは表示/非表示を繰り返すため、この役割を分離している。 また、スケジューラーのタイマー(30秒間隔)を管理し、スケジュール条件に合致したタスクの自動実行も制御する。

スケジューラータスクの種類

スケジューラーはファイル実行に加え、メッセージ表示タスクをサポートする。

種類説明
ExecuteShellExecuteExでプログラムを起動する
BalloonTipタスクトレイのバルーン通知でメッセージを表示する (自動消去)
MessageBoxNotificationFormをモーダル表示する (OKボタンで手動消去)

Core層 (SchedulerPresenter) はUI依存を持たない。 BalloonTip/MessageBoxの表示はデリゲート経由でUI層 (ApplicationHostForm) に委譲する。 MessageBoxはInvoke(同期呼び出し)でダイアログが閉じるまで後続タスクをブロックする。 BalloonTipはBeginInvoke(非同期)で実行する。

通知ダイアログの追跡とowner選定

実装上の不変条件は.claude/skills/notification-dialog/に記載している。

フック管理

HookManagerがグローバルキーボード/マウスフックの状態管理を一元的に担当する。 マウスフックはボタン押下状態(lbuttonDown/rbuttonDown)を追跡し、 設定されたトリガー(左右同時押し等)を検知する。

コールバック内で守るべき実装上の不変条件(即時return・UP抑制フラグ更新など)は .claude/rules/win32-interop.mdに記載している。

環境変数の自動リロード

EnvironmentRefresherWin32/)がレジストリから環境変数を再読込し、現プロセスの環境ブロックを差分更新する。 ApplicationHostForm.WndProcWM_SETTINGCHANGElParam == "Environment")を受信する。 500msのデバウンスを経てEnvironmentRefresher.Refresh()を呼び、 その後ReplaceEnvListCommandListSchedulerDataに背景スレッドで再適用する。 ReplaceEnvListに関する挙動上の注意は.claude/skills/persistence/に記載している。

マージ規則はExplorer互換(HKLM+HKCU統合、Path系のみ;連結、それ以外はユーザー変数優先)とする。

子プロセスへの伝搬は追加実装不要である。 ShellExecuteExは呼び出し元プロセスの環境ブロックを継承するため、 Environment.SetEnvironmentVariableで更新すれば以降の起動プロセスへ新値が反映される。