Skip to content

アーキテクチャ

SwiftList のアーキテクチャ

プロセスの分割

SwiftList は、権限レベルとライフタイムに応じて意図的に分離された3つの独立したプロセスとして動作します。

  • SwiftList.ServiceLocalSystem として動作する Windows サービスです。ファイルインデックス作成のすべてを担当します。NTFS/ReFS ドライブの USN Journal と MFT の読み取り、ジャーナルを持たない他のローカルファイルシステムの直接的な走査と監視、ネットワーク共有のスキャンとキャッシュ、そして名前付きパイプ経由での検索クエリへの応答です。SYSTEM レベルで動作させることで、どのユーザーアカウントからも参照可能な生のボリュームメタデータを読み取れるようになり、対話型の App プロセスに不要な昇格権限を与えずに済みます。
  • SwiftList.App — ユーザーごと、セッションレベルで動作する WPF アプリケーションです。検索ウィンドウ、設定ウィンドウ、ホットキー処理、アクションメニュー/QuickLook UI を担います。Service とは名前付きパイプ(Core.ServicesSearchService/UsnServicePipeServer)経由でやり取りし、ディスクインデックスに直接触れることはありません。また、App 自身もユーザーごとの2つ目のパイプ (AppSearchPipeService)をホストしており、これにより slf CLI コンパニオン(コマンドライン検索を参照)は、素の状態から独自にセットアップをやり直すのではなく、App がすでに初期化済みの検索状態 ——読み込み済みのエイリアス/プラグインプロバイダー、設定済みのネットワークドライブインデックス—— を再利用できます。
  • SwiftList.Service --hook — 低レベルのグローバルキーボードフックだけをホストする、独立した小さなプロセスです。フックのクラッシュや不安定なフォアグラウンドアプリが、メインの App プロセスを巻き添えにしないようにするためです。またこのプロセスは、プラグインのウィンドウ統合アダプターも読み込み、その呼び出し自体を自分自身の中で実行します。詳しくは下記のプラグインの位置づけを参照してください。

共有される Core

Core は Service と App の両方から参照されるクラスライブラリです。次のものを保持しています。

  • 検索エンジン(Core/SearchIndex/Fzf/*) — fzf コマンドラインツールのアルゴリズムをモデルにしたあいまい検索の実装で、ドライブレター指定やパスモード検索のためのクエリパーサー(SearchQueryParser) も含みます。
  • ランタイムインデックス(Core/IndexV2/*) — USN/MFT の読み取りから構築される、メモリマップ方式の列指向スナップショット形式で、最後のスナップショット以降の変更を保持するメモリ内デルタオーバーレイを備えています。
  • IPC コントラクト(SearchRequestMessageSearchResponseBinarySerializer など) — App と Service の両方でそのまま共有され、両プロセスが常に同じワイヤーフォーマットに合意していることを保証します。
  • Logger — プロセスごとのログファイル(service.logapp.loghook.log)に書き込みます。これらはすべて App の 設定 → サービスの状態 のログビューアーから読み取り可能です(ただし、すべてが書き込み可能というわけではありません)。

プラグインの位置づけ

プラグインは PluginSdk を参照する .dll アセンブリであり、App プロセスによって読み込まれます (はじめにパッケージングと配布を参照)。SwiftList 自身にも、第一級のサンプルとして2つのプラグインが同梱されています——SwiftList.Plugins.CoreExtensions(組み込みのファイル操作とシェルのコンテキストメニュー統合)と SwiftList.Plugins.PinyinAlias(中国語ファイル名向けのピンインエイリアス)です。両者の詳しい解説はサンプルプラグインを参照してください。

プラグインが Service と直接やり取りすることはありません。プラグインはプラグイン SDK リファレンスに記載されているインターフェースを通じて App とやり取りし、(カスタムのインデックス対象ディレクトリが必要な場合の)ディスクインデックスとのやり取りは、代わりに Service へプロキシする DirectoryIndexerService を通じて行います。

ウィンドウ統合アダプターは、「App だけで完結する」という原則の唯一の例外です。 IActivePathCollectorIFileDialogAdapterIInlineSearchAdapter の実装は Hook プロセスにも二重に読み込まれ、その呼び出しは App ではなく Hook プロセス側で実行されます。これにより、App 自体は常に非昇格で動作しているにもかかわらず、SwiftList は昇格した File Explorer/ファイルダイアログ/サードパーティ製ファイルマネージャーのウィンドウを操作できます——Windows は低権限プロセスから高権限プロセスへの入力送信をブロックするため、呼び出しは対象と同じ権限レベルで動作するプロセスから発行される必要があるからです。