そんなことより、XMLSerializer のアレが再び

日本語環境に設定された Windows の cmd.exe と conime.exe のアレが再び我々を襲うのでした。

using (Process p = Process.Start("...console application..."))
{
  p.WaitForExit();
}

上記の WaitForExit() は、日本語環境では Windows を終了するまで帰ってこないことがあるんです。
XMLSerializer は動的アセンブリを作成する csc.exe の完了の待機に10分間のタイムアウトがある*1ので、10分経過後に存在するファイルに対して FileNotFoundException を投げるという挙動ですんでいるが、上記のコードはタイムアウトの設定がないため、cmd-conime の問題に遭遇すると Windows からログオフしたり再起動するまで二度と帰ってこなくなる。

今回これに至ったわけ

少し前に書いたように、Visual Studio .NET 2002/2003 では、プロジェクトに追加されている「埋め込みリソース」のファイル名(フルパス)の合計が32000文字を超えると、プロジェクトのビルドができなくなる、という不具合がある。*2
この不具合の怖いところは、コマンドラインの32000文字目が偶然ファイル名とファイル名の間にある空白であった場合、プロジェクトのビルドが成功して不完全なアセンブリが生成されることや、フルパスでファイルが受け渡されるため同じソースコードでも開発環境やソースコードのファイルが配置されたフォルダ階層の場所によって再現する場合としない場合があるといったところだ。
英語版 Visual Studio 用の修正モジュールは、KB に従って入手が可能であるようだが、これをお手軽に回避するため、al.exe というコンソールアプリケーションを作成してみることにした。
動作内容は単純で、渡されたコマンドライン引数が3万文字未満なら本物の al.exe を呼び出しなおし、3万文字以上ならプロジェクトファイルを XmlDocument クラスに読み、プロジェクトファイルに指定されている必要なファイルの一覧をテンポラリファイルに書き出して al.exe @tempfile を呼びなおす、というものだ。
この新しい(?) al.exe は思ったように動作してくれて、小さなプロジェクトも大きなプロジェクトも正常なアセンブリを生成することができるようになった……かにみえた。

ところが

問題のアレに遭遇したのである。al.exe の呼び出しに前述のように Process クラスを使用していたのだが、朝1番のビルドに失敗し al.exe がプロセス一覧に延々と残っている状態になってしまった。
Visual Studio は呼び出すツール群にきちんとタイムアウトを設定していたので、ビルドプロセスが終了せずに停止してしまうことはなかったが、やっぱりレジストリを変更して conime.exe を使わないようにしたら治ったので、そういうことなんだろう…。

*1:正確には XMLSerializer が使用しているのは Microsoft.CSharp.CSharpCodeProvider で、その実装が csc.exe を呼び出している

*2:kb840525およびkb829970