税務申告ソフトが起動しない原因を調べたら、消えていたのはプログラム本体だけだった

開発misc-dev

税務申告ソフトが起動しない原因を調べたら、消えていたのはプログラム本体だけだった

朝、法人税の申告ソフトを開こうとしたら起動しなかった。 アプリケーションの一覧を見ても、あるはずのものが見当たらない。

7月29日に、このPCで再帰削除が走って ~/.claude が丸ごと消えた事故があった。 そのときスタートメニューのショートカットも道連れになっている。 だから今回も、消えたのはショートカットだけだろうと考えた。 実体さえ残っていれば、リンクを作り直すだけで済む話になる。

消えたのはショートカットか、実行ファイルか

Claude Code に切り分けを頼んだ。 「本体が残っているか、ショートカットだけ消えたか」を先に確定させたかった。

最初の報告は「本体は残っていて、消えたのはショートカットの側」だった。 そのまま実行ファイルの所在を追わせると、今度は見つからないという。 フォルダはある。中身がない。

更新時刻がそろっていたフォルダ群

決め手はタイムスタンプだった。 全製品のフォルダで、更新時刻が 2026-07-29 の 06:27〜06:28 に揃っている。 削除事故と同じ日、同じ数分間だ。

中を開かせると、構造がはっきりした。 どの製品も Data/ だけが残り、実行ファイル一式が入った Program/ が丸ごと消えている。 実行ファイルだけが消え、データは残っていた。

なぜ Data/ が生き残ったのかは、DBファイルの更新日時で分かった。 その日時が調査当日の 09:48 になっている。 SQL Server がいまもこれらのファイルを開いていて、7月29日の削除時にはロックがかかっていた。 消せなかったから残った。

被害の範囲も詰めた。 同じ 06:27 に電子申告ソフトのフォルダも触られていたが、こちらは 19,550 ファイルが残っていて無傷だった。 正規のアンインストーラが走った線も潰した。 イベントログに MSI のアンインストール記録はゼロ件で、外側からディレクトリごと削られたと見るしかない。

ここで結論が出た。 プログラムは消えている。申告データは全部無事。 26製品分のデータベースが SQL Server 上で ONLINE のまま生きていて、テーブルにもレコードが入っていた。 法人税は5年度分がそろっていた。

再インストールの入口を過去メールから探す

再インストールしようにも、どこから落とせばいいのか覚えていない。 ベンダーからいつか届いたメールに入口が書いてあるはずなので、Gmail を仕事用と個人用の両方から探させた。 個人用にシリーズ関連のメールがあり、仕事用にも10件ヒットした。

ダウンロードサイトのURLは分かったが、開くと 403 で弾かれた。 r.jina.ai を挟んでも 403 だった。 手元に落としてあったインストーラがそのまま最新版なので、そちらで進めることにした。 配布されている実行ファイルの日付が2022年のままなのは、起動後に本体側が自動更新する設計だからだ。 インストーラ自体は据え置きになっている。

プロダクトコードも要る。 仕事用のメールに2022年のライセンス証書のPDFが添付されていた。 1ページ目にはユーザIDしか書かれていない。 FAXヘッダが「0002/0003」になっているのを見て、続きがあると分かった。 2ページ目にプロダクトコードがあった。

「インストール済み」で弾かれる

シリーズ共通のランチャーを入れ直そうとしたら、セットアップが即座に終了した。 実体は消えているのに、レジストリには「1.53.0000 インストール済み」の登録だけが残っている。 セットアップはそれを見て「もう入っています」と判断していた。

修復を試させると、元の MSI パッケージが失われていて不可だった。

Source is invalid due to missing/inaccessible package

アンインストールも同じエラーで落ちた。 Temp に展開フォルダが残っていたので中を漁らせたが、MSI 本体はなかった。 新しいバージョンを取ってきて上書きする道もダウンロードサイトの 403 で消えている。

行き詰まったところで、管理者権限で同じアンインストールを実行させたら ExitCode=0 で通った。 MSI が無いから失敗していたのではなく、単に権限が足りていなかった。 壊れた登録が外れ、残骸のサービスファイルも消えて、クリーンインストールできる状態になった。

ここで「壊れた登録を外してから入れ直す」という型ができた。 以後の製品は全部この流れで戻せた。 データ管理用のツールでは、セットアップが「削除」を出してきて手が止まった。 固有のデータベースを持たない製品だと確認してから削除に進んだ。 入れ直すと、登録済みの事業者がそのまま並んだ。

クラウドに上げる前に手元へ逃がす

まだ削除と再インストールを何回も繰り返す必要がある。 その前にデータを逃がしたかったので、Googleドライブに上げておくのはどうかと聞いた。

返ってきたのは、先に外付けドライブへ取るべきという答えだった。 理由は、さきほどの画面に個人番号を扱うデータベースが見えていたことにある。 顧問先のマイナンバーが含まれる可能性が高く、番号法の安全管理措置の対象になる。 平文のままクラウドに置くのは避けたい種類のデータで、しかも今回必要なのは「これから数十分の削除作業のための保険」だった。 遠隔保管より手元の速さが効く。 その通りだと思ったので、ローカル優先に切り替えた。

バックアップ自体はすぐ終わるはずだった。 SQL Server は Express Edition で圧縮が使えないが、対象は数百MBしかない。 実際には二度つまずいた。 書かせたスクリプトは、日本語がエンコーディングで壊れて落ちた。 ASCII だけで書き直させて通した。 26個すべてのバックアップに成功したのに、今度は外付けドライブへのコピーだけが権限で弾かれた。 出力先が SQL Server のサービスアカウント所有になっていて、通常権限では読めない。 ここも管理者権限で通して、26ファイル(373.9MB)が外付けドライブに乗った。

事故より前のバックアップはどこにもなかった

並行して動かしていたもう一方のセッションでは、事故前の正規バックアップを探させていた。

SQL Server の履歴に残る全記録で確定したのは、正規バックアップが2024年7月の1回分しかないことだった。 OneDrive と Dropbox のローカルツリー、それに外付けドライブまで含めてディスク全体を総当たりさせても、追加は出てこない。 バックグラウンドの find が外付けドライブの全走査で長く粘っていて、終わってみれば新発見ゼロ件だった。

手元に残った弾は2つだけになった。 今日取った26本のバックアップ(内蔵と外付けの2箇所に二重化)と、OneDrive にある2024年の移行セット。 最後の正規バックアップから2年空いていたことになる。

通常出ない画面が出たとき

復旧の途中で、見たことのない画面が出た。 翌年度版のデータベースを新規作成するか聞かれている。

「その年度のデータベースは存在しないので、作っても既存とはぶつからない」と説明された。 理屈は通っている。 ただ、新しい年度版を入れるときにこの画面が出た記憶がない。 通常出ないはずの画面が出ているなら、システムがまだ正常な状態にないというサインだ。 先に前年度版を入れ直してから、もう一度試すことにした。 「壊れない」と「作るべき」は別の話だった、とあとで訂正が入った。

前年度版を入れ直したら、接続先に自動で繋がって顧問先データが読めた。 新規作成は聞かれなかった。 想定どおりの挙動に戻った。

未発見の被害を並列で洗う

7月29日の削除は2波に分かれていた(06:26〜06:28 と 07:22〜07:25)。 この時刻が強い手がかりになるので、10領域に分けて並列でスキャンさせた。

9領域が終わった時点で findings は96件。 最後の1つが AppData 配下の走査で重く、6分間ログが動かなかった。 ハングではなく、単に量が多いだけだった。 待つより先に進めたかったので、その領域は「失敗した領域」として記録に残し、9領域だけで統合に進んだ。

9領域分の結果は158KBあった。 メイン側で全部読むとコンテキストが膨れてセッションが落ちやすくなるので、統合はエージェントに任せてファイルへ直接書かせた。 そのエージェントは7分かけて、96件を鵜呑みにせず自分で裏取りし直していた。

報告の中に、蔵書DBのバックアップが止まっているという指摘が「実害進行中」として上がってきた。 クラウド側にあるものを同期しているだけなら、そこまで急ぐ話ではないはずだ。 そう聞き返したら、中身を確認しないままエージェントの報告をそのまま伝えていたと認めた。 実物を見せてもらうと、蔵書DBの2つのテーブルを CSV に書き出すスクリプトだった。 緊急ではない。

唯一の復旧不能候補として PostgreSQL が残った。 中身の確認は今日はやめた。 帰りたかったので、やらなければいけないことだけメモに残させた。

残したもの

復旧が必要な製品の一覧を、レジストリの登録と実体の有無を突き合わせてマークダウンにさせた。 操作中に渡したスクリーンショットも手順に組み込ませ、HTML化して描画まで確認した。 CDキーが毎回変わることも書き足した(同じ製品でも2回の表示で値が違っていた)。 残りは Codex のコンピュータ操作でまとめてやらせるつもりなので、手順は画像込みで残す必要がある。

このチェックリストは8月9日9:00のタスクとして登録した。 タスクのAPIでは期日に時刻を入れられないと実測で分かった。 画面側から設定し直し、その手順をスキルに追記させた。

もう一方のセッションでは、月次のバックアップを毎朝のコマンドのチェーンに組み込んだ。 前回のバックアップ日をログで見て、30日以上経っていたら自動で取り、外付けへ複製して日付を記録する。 最初の設計には古いバックアップを自動削除する処理が入っていたので、そこは外させた。 容量が膨らんだらリマインドを出す形にしてからコミットした。

残った学び

  • 更新時刻が一点に揃っているフォルダ群は、それだけで削除の痕跡になる
  • 使用中でロックされていたものだけが生き残る。今回は SQL Server が開いていたDBファイルが助かった
  • レジストリの登録だけが残ると、セットアップは「もう入っている」と判断して何もしない。実体の有無までは見ていない
  • 「MSI が無いから失敗した」は誤診で、実際は権限不足だった。失敗の理由を1つ目の仮説で確定させない
  • 通常出ない画面が出たら、その場で安全かどうかより先に、なぜ出たのかを疑う
  • 事故で消えるのは、バックアップを取っていた記憶があるものとは限らない