32bit版Windows 7をWindows 10に更新

あるPCがPCIボードの事情でWin 7 32bitにしがみついていたが最近それが不要になった。すでに10月で無料更新期限後だが、まだ普通に更新できるという話なので更新してみた。
まず公式ダウンロードページから作成ツールをダウンロードする。後々のことも考えてインストールメディアの作成を選んだ。
最初はUSBメモリに保存しようとしたのだが、接続しているUSBメモリドライブが表示されない。仕方がないのでISOファイルを作成することにした。

メディアが作成できない

OSのダウンロードは開始するのだが、完了後検証しようとするとエラー 0x80070008 0x9002で中断してしまう。やり直して先に進んでも、検証途中に0x80070008 0xA0003で中断してしまうこともあった。
0x80070008はいわゆるシステムリソース不足のエラー。メモリがいくら空いていてもシステム領域に限界のある32bit Windowsカーネルではある意味どうしようもないのだが、インストーラなので使い勝手を考えなければ空ける余地はある*1
常駐ソフトをMSSEを含め可能な限り切って、画面解像度を落として再起動、再起動後にも可能な限りプロセスを終了して行ったところ、何とかISOファイルを作成できた。
ちなみに3回失敗した。ISOの保存場所に関係なくC:\ESD\Downloadにinstallx**.esdがダウンロードされるが、プログラムの作りこみが甘くダウンロード自体が完了しても検証時やISO作成時に上記エラーで中断してしまうとダウンロードからやり直しになる。x86とx64で計5GBあるので都合15GBも帯域を無駄にしてしまった。
このダウンロードしたESDからISOを作るツールもあるようだが、isolatedな形式ということでISOの作成ができないばかりか、RSA鍵も不明でデコードもできないようだったので上記のように頑張るしかなかった。
ともあれ最終的にはISOが用意できたのでアップデートにやっと移れる。

後で知ったのだが、Windows以外(のUser-Agent)ではISOファイルを直接ダウンロードできたらしい。なぜかWindowsではオプションを表示してくれない。*2

インストール

ISOをWinCDEmuでマウントして、内容をNTFSフォーマットのUSBメモリのルートにすべてコピーした。DVDに焼いてもいいが、アクセス速度的にも高速なUSBメモリの方が便利だろう。仮想イメージからSetupを起動してもエラーになる。
USBメモリ上のSetupを起動して、アップグレードを開始する。
途中2回くらい再起動した。Setupを7から起動したからかUEFI BIOSのブート順序を入れ替えないでも特に問題なかった。

巷の期限後の移行記事を見ると、ライセンスはインストール時に7のプロダクトキーを入れるとOKという話だった。しかし今回インストールと初期設定を済ませてもキーを尋ねられることはなく、Win-Breakを押してみるとすでにライセンス認証済みとなっていて、何も入力作業は必要なかった。たまたまなのか、何かしら最近のWindows 7側の更新で状況が変わったのかは分からない。

環境設定

Windows Vistaや7にしたとき同様、キーの置き換えがリセットされているのでremapkeyを管理者権限で起動し再設定する。
AppDataのTEMPのジャンクションも再設定した。
おせっかいにもアプリの関連付け設定もブラウザやメディアファイルでMS謹製のものに勝手に変更されていたので修正した。*3

7と比べて

高速スタートアップなしで起動は10秒弱遅くなった。
メモリ使用量は起動時点では130MBくらい増えている。初期状態で余計なものを削っていないせいもあるかもしれない。
Windowsの上書きインストールならばこんなものだろう。後日64bit化したい。

*1:それにしても巨大ファイルのverifyができないというのはお粗末な作りだ。全体をmmapでもしようとしているのだろうか。

*2:去年にそんな記事を読んだ記憶もあるのだが、すっかり忘れていた。

*3:せっかく設定してもたまに勝手にMSのアプリにリセットしてくれる。opt-outできない余計な機能を増やす伝統はいつまで経っても変わらないようだ。

startコマンドがファイルデスクリプタを引き継いでしまう

3つのスクリプトがあるとする。

  • a.bat は b.bat を実行し、そのエラー出力をログに保存する
  • b.bat はいろいろな処理をする過程で c.pl というデーモンを起動する
  • c.pl はデーモンなので終了しない
# a.bat
call b.bat 2>>error.log

# b.bat
start wperl c.pl

# c.pl
use AnyEvent;
my $cv = AE::cv;
...
$cv->recv; # 基本的に終了しない

この時、startで起動した c.pl の出力はリダイレクトされていないのにも関わらず、ログファイルが c.pl によって使用中になっていまう。a.bat としてはログを処理して処分したいが、Windowsにおいて開いているファイルは処分できないので困る。
startでも&2をリダイレクトしてみたが、古いデスクリプタを閉じてはくれないようだ。
a.bat であらかじめ c.pl を起動しておく以外に解決する方法はないのだろうか? まあ、トラブルメーカーなbatを止めるのがいいのだろう。

起動ディスクをSSDにした

SSDに換装したのではなくHDDはそのままに起動ドライブをSSDにコピーする形。OSはWindows 7
HDDはC, D, E, Fの4パーティションでC:が起動ドライブ。このC:のみをSSD化したわけだ。
CFD販売のSSDなのでクローンはOEM版のEasyDiskCopyをサイトからダウンロードして使った。余談だが付属のネジ8本中4本はSSDにはうまくハマらず使えなかった。HDDには使えるようなのでSSD側のネジ穴がシビアなのだろう。

まずSSDを内臓SATA接続し起動、EasyDiskCopyでSSDにCドライブをコピー。ジャンクションは維持する設定にした。コピー速度はファイル単位でパス名順に行なうので割と遅く、30GBが40分程度かかった。
画面に従い電源を落とし、内蔵HDDの電源ケーブルをはずして(SATAケーブルはそのまま)起動すると、普通に立ち上がった。一点、ページファイルを置いていたFドライブ(HDD)が無いためそのエラーが表示され、一時的にSSDのC:にページファイルが置かれた状態になった。
次にWindowsを起動したままHDDの電源ケーブルを繋ぎ、HDDを認識させる。ドライブのシグネチャがクローンしたSSDと衝突するため繋いだだけではマウントされない。ちなみにAHCIモードのSATAはホットプラグしてOKのはずだが、古いPCなのでマザーボードくらいなら仮に故障しても構わないと考えての乱暴な行動。*1
コンピュータの管理>ディスクの管理で接続したHDDを右クリックし、オンラインを選択。HDDの旧C〜Fパーティションがばらばらの順序でD〜Gとしてマウントされる。EasyDiskCopyの説明によると、オンラインにした段階でSSDをはずしてHDDのみに戻しても旧Cドライブは起動ドライブにはならなくなる可能性がある。
パーティションを右クリックし、ドライブ文字とパスの変更でドライブレターを変える。旧C:は適当な未使用文字に変更し、旧D:〜F:を改めてD:〜F:に割り当てなおした。
再起動し、BIOSのHard Disk Boot PriorityでSSDを優先設定したところ、C:のみSSDになった形で他のHDDパーティションも元通り認識された。
念のためC:のジャンクションを確認して、移行完了。

失敗パターン

と書くと順調にできた様に見えるが、その前に2回失敗している。

1度目はEasyDiskCopyでコピーした後、HDDを外さずにSSDを優先設定して起動した時。

windows failed to start. A recent hardware or software change might be the cause...
File: \windows\system32\kdcom.dll
Status: 0xc000000f
Info: □□□...□□□DLL□□□...□□□windows□□□...(おそらく日本語が文字化けしている)

というメッセージが黒画面に表示され、起動しなかった。Windowsのシステム回復オプションで修復しようとしても前出のファイルが壊れているが修復不能というメッセージがでる。
もしやコピーが失敗していたのかと、もう一度コピーから試そうと思いEasyDiskCopyを起動すると
「dvshadowの実行に失敗しました」と出てコピーできなくなっている。ドキュメントにあるようにサービスの状態を確認したが変わらず。ログを見ても解決できそうにない。

ERROR: Selected writer 'Registry Writer' is in failed state!
   - Status: 9 (VSS_WS_FAILED_AT_FREEZE)
   - Writer Failure code: 0x800423f4 (VSS_E_WRITERERROR_NONRETRYABLE)

そこで次善の策としてネットで評判のよさそうなEaseUS ToDo Backupの無料版*2を使ってクローンすることにした。パーティションのクローン自体は15分程度と速く完了したのだが、起動してみるとX:(SSD)のWindowsから起動してProgramDataもSSDだがProgram FilesやUsersはC:(HDD)を参照するという変な結果に。
そこでドライブレターの変更でC:(HDD)を適当なものにして再起動したところ、今度はログインすると「デスクトップの準備をしています...」というメッセージが出るように。数分表示された後で画面は切り替わったが、今度は青っぽい背景に「このWindowsのコピーは正規品ではありません」というメッセージが右下に出るだけで何も起こらない。マウスポインタはあるのだがアイコンもなくキーにも反応しないのでどうしようもない。

そこからもう一度手順を検討しなおして前述の通りにしたら、移行できたわけだ。
dvshadowが一度失敗していた理由は不明。添付ドキュメントの通り1 NTFSパーティションのHDDを換装する場合は十分スムーズにできる気がする。
注意点としてファイルの作成日とアクセス日が保持されない。ディレクトリの場合は修正日も移行時間になってしまう。

シャドウコピーの削除

失敗パターンでEasyDiskCopy (dvshadow)が途中で終了したせいだろうか。シャドウコピーがHDDにいくつも残っていた。
vssadmin list shadows で確認できる。そのままにしておくとフォーマットでもしない限りデータが残ってディスクを圧迫する。
削除方法はvssadmin delete shadows /?にある。今回は復元ポイントなどもなくすべて移行時にできたものだったので vssadmin delete shadows /all で一括して削除した。

*1:BIOSによってはホットプラグを無効化する設定がある。

*2:下部にある通り丁寧なコメントが付いていたのでリンクを設定した。本記事は2016年当時のバージョンについてであり、最新版で同様の結果になるかは確認していない。

Java (JRE 1.8.0 update 91)が動作しない (Windows 7, 32bit)

実行・アンインストールできない

Javaを使ったプログラムを実行しようとしても何も起きない。タスクマネージャを見るとjavaw.exeが暴走している。Javaのコントロールパネルを開こうとしても同様。
再インストールするためにアンインストールしようとしても同じ。javaw.exeを強制終了したところ正常にアンインストールが始まった。

インストールできない

しかし改めてJREをインストールしようとすると、最後の段階でやはりjavaw.exeが暴走して途中で止まってしまう。
javaw.exeを強制終了すると今度はjavaws.exeが暴走して、それを終了するとエラー1603でインストールが失敗した。
ファイル自体は展開されているのだが、そこからjava.exeを使おうとしてもやはりフリーズする。

アーカイブファイルを使う

今回必要なのはjarファイルの実行環境だけでコンパイラはもちろんブラウザプラグインも不要なので、他の手段を探してみた。
OracleのダウンロードページからJava SE > JRE とたどると、インストーラの他に単なるアーカイブも用意されている。そこからWindows用の.tar.gzをダウンロード、展開してみた。java.exeを実行したところ、今度は問題なくヘルプが表示された。
これで解決かと思ったのだが、展開したディレクトリを別の場所に動かすと同じようにフリーズするようになった。

原因

そうなると元々考えにくかったインストーラの破損というのは完全になくなった。いろいろな場所に動かして試行錯誤の末、JREのパス中にJavaというディレクトリがあるとフリーズすることがわかった。
デフォルトのインストール先はC:\Program Files\Javaなので、このせいでフリーズしていたのだろう。これまではこのパスでも問題なく動作していたので根本的な原因は不明だ。

符号化方式"UTF8"文字0xHEX<は"EUC_JP"と同じではありません

PostgreSQL 8.4 のメッセージでこんなのが出た。
意味が理解不能なので元のメッセージを見ると、"character 0xHEX of encoding "UTF8" has no equivalent in "EUC_JP"となっていた。
つまり正しくは「エンコーディング UTF8 の文字 0xHEX は対応する文字が EUC_JP にない」ということ。*1
今回の場合はクライアント側はすべてEUCjp-winなので理論上はそれ以外の文字が入る余地はない。該当するデータを見てみたところ単にpsqlで直接データを挿入した時に表外の文字を入れてしまっていたと判明したのでデータを修正して対応した。

古いシステムのメンテで出くわしたメッセージなので今はどうかと見てみたところ、9.5では "符号化方式"UTF8"におけるHEXバイトシーケンスを持つ文字は"EUC_JP"符号化方式では等しくありません" と、やはりおかしい。
ただ誤訳の報告はどこに投げればいいのかがわからなかった。GitHubは単なるミラーのようなので公式のアカウントを作ってチケットを作成するのだろうか。ドキュメントの翻訳は別プロジェクトがある雰囲気なので、メッセージの翻訳も別なのかもしれない。割といろいろなプロジェクトで細々と翻訳やその訂正を投げているが、検索しても窓口や手順がわからなかったため断念した。

*1:Windowsによくある機械翻訳的な意味や品詞の間違いは元の単語を想像して英文を推測できるのだが、原文の動詞を落っことしていると難しい。