個人開発

40MB を諦めた話と、リリース準備の取捨選択 — Windows スクショツール開発記 #4

棚に並んだ立体形を選び取る抽象イラスト
やる / やらないをどう決めたか、リリース準備の取捨選択

先に結論

検索でたどり着いた方向けに、要点だけ。

  • 当初の 実行ファイルサイズ目標 40MB は諦めて、60〜80MB を現実値に置き直した
  • 撮影方式は 新しい仕組みを諦めて、ひとまず古典的な仕組みに寄せるところから始める方針にした
  • 機能としては モザイクをぼかしに寄せる / 暗号化保存は MVP から外す、など、ユーザー価値と実装コストを照らして削る判断もした
  • セキュリティ原則(外部通信しない、キー入力をフックしない)は、そういう書き方をしないことを CI で機械的にチェックする形で守る

連載の他記事

1. 実行ファイルのサイズ目標を 40MB から 60〜80MB に置き直した

このスクショツールは インストーラを使わず、ひとつの実行ファイルだけで配布する想定です。これだと、ユーザーが受け取ってすぐ動かせるので体験が軽い、という狙いです。

最初は「40MB に収めたい」という目標を立てていました。.NET 製の Windows アプリで、ランタイムまで全部含めて単一の実行ファイルに梱包する self-contained 構成に、PublishTrimmed で不要な型を機械的に削るオプションを足せば、40MB あたりまで持っていけるんじゃないか、というふんわりした期待です。

実際に PoC をやってみた感触と、事前に調べた範囲の情報を合わせて見ると、

  • WPF はリフレクションを多用する作りなので、Trim が安全に削れる範囲が小さい
  • 削りすぎると実行時に必要なものまで落ちて、起動しなくなる
  • 確実に動く構成を取ると、自分の手元では 60〜80MB あたりに落ち着きそう

という見え方になってきました。なので、サイズ目標は 60〜80MB に置き直しました。

ここはちょっと悔しいポイントではあるのですが、目標値を現実に合わせる判断をしておかないと、あとあと「サイズに合わせて機能を削る」みたいな本末転倒な話になりかねないので、早めに切り替えることにしました。

2. 撮影方式は「新しい仕組み」を諦めて、古典的な方に寄せる

Windows でスクリーンショットを撮る API は、大きく分けると 2 系統あります。

  • WGC (Windows Graphics Capture): 比較的新しい仕組みで、画面の合成段階に近いところで取得するやり方
  • GDI 系 (BitBlt / PrintWindow): 古典的な仕組みで、Win32 時代から使われているやり方

WGC のほうは、ハードウェアアクセラを使っている画面でも黒く写らない、などの利点があります。GDI 系は、特定の条件で画像が黒くなる(いわゆる BitBlt 黒画像問題)という既知の問題がありますが、その代わり実装はシンプルで、対応範囲も広いです。

最初は「WGC を主軸、GDI を補助」で考えていました。ただ、実際に PoC を進めると、WGC 側の検証コストが MVP のスコープに対して重く、ここでつまずくとリリースが遠のきそうでした。

なので、

  • MVP では GDI 系を主軸にする
  • PrintWindow を PW_RENDERFULLCONTENT フラグ付きで呼ぶと、黒画像問題は大部分を回避できる目処がついている
  • WGC を使うかどうかの判断は、MVP の次のリリース に持ち越す

という整理にしました。実装を「最小限で動くもの」に揃えてから、必要に応じて段階的に置き換える、という考え方です。

3. 機能の取捨選択

MVP のスコープは、大きく言うと「普段使いで困らない撮影体験を、最小構成で揃える」というあたりに置いています。具体的に削った / 寄せた判断をいくつか挙げると、

モザイクはぼかしに寄せる

最初は、画像の一部を隠す手段として「モザイク」と「ぼかし」の両方を実装する想定でした。ただ、ユーザーが実際にやりたいのは「ここを見せたくない」というだけのことなので、ぼかしひとつあれば多くのケースは間に合います。

エディタの機能を 1 つ減らせば、UI もテストもシンプルになるので、MVP ではぼかしだけ残すことにしました。モザイクは将来必要になったら足す形で。

自由線描画は MVP から落とす

矢印・四角・テキスト・ぼかしの 4 つは MVP に入れます。一方で「自由線で書き込む」ような機能は、需要としては「あったら便利」レベルだったのと、実装と UX の両方で深掘りが必要になるので、MVP からは外しました。

ワークスペースの暗号化保存は MVP から外す

過去のスクショを保存しておく場所(ワークスペース)を、Windows 標準の暗号化機能(DPAPI / EFS)で守るかどうか、というのも検討しました。

ただ、考えていくと、

  • そもそも、ローカルディスクに置く時点で、その PC のユーザーは内容を見られる前提になる
  • 攻撃モデルがはっきりしないまま暗号化を入れると、復号フローや権限管理など UX のコストが大きくなる
  • 「ここまではやらない」と最初から決めておいたほうが、自分にとっては気持ちが楽でした

という整理になり、暗号化保存は MVP には入れないことにしました。「やらない」と決めるのも、ひとつの設計判断なんだろうなと思います。

4. セキュリティ原則は CI で機械的に守る

このツールの方針として、

  • 外に通信しない
  • キー入力を覗き見しない
  • テレメトリを送らない
  • 自動更新もしない

というあたりを掲げています。とはいえ、コードを書いていると「うっかり」で原則と矛盾するコードを足してしまうこともあります。

なので、

  • HttpClient などの外部通信系の参照が追加されたら CI で検出する
  • WH_KEYBOARD_LL(Windows の低レベルキーボードフック)を使うコードが入ったら CI で警告する
  • Dependabot を「security 即マージ / minor 週次 / major 個別判断」の 3 段階で運用する

といった機械的な仕組みを CI に仕込んで、原則からそれた書き方が「うっかり」では入らないようにする予定です。原則を口で言うだけでなく、機械的に守れる形に落とす ところまでをひと続きで考えるイメージです。

振り返り

この連載で書いてきた話は、結局のところ、

  • 個人開発でも、Claude Code を並列で動かすことで、密度はかなり上げられる(#1)
  • その上で出てきた機能のひとつひとつには、ちゃんと小さな葛藤がある(#2)
  • それを下支えする設計は、似たバグが再発しない構造を選んでおきたい(#3)
  • そして、リリースに向かっては、目標値の置き直しと「やらない」判断、それを CI で支える整備が必要(#4)

というあたりに整理できる気がします。

このスクショツールはまだ MVP の途中で、リリースまではもう少しかかりそうです。実装が落ち着いて配布できる状態まで漕ぎつけたら、続編としてリリース編を書こうと思います。

ここまでお付き合いいただきありがとうございました。