2011年9月6日火曜日

コマンドプロンプトとフォントの怪

コマンドプロンプトの文字化けにしばらく悩まされたのでその奮戦記。

◎ 起こったこと
  • ある日、Visual Studioをインストールするとスタートメニューに入る「Visual Studio 20xx コマンドプロンプト」(VS用の環境変数が設定済みのコマンドプロンプト)を初めて起動したら、日本語が文字化けして表示された。
  • その少し前にmsysgitをインストールしていて、インストール時にコマンドプロンプトのフォント設定に関する確認を求められていたから、それ絡みかもしれないと思いつき、コマンドプロンプトの設定画面からフォントの設定値を見てみるとちゃんと「MSゴシック」になっている。
  • そもそも、msysgitインストール後に普通のコマンドプロンプトを使ったことは既にあって、文字化けは発生していなかった。
はじめはVisual StudioもExpress Editionだし、昔は日本語のサポートが遅れていたし、とVisual Studioのせいかと思って、そちらを想定したキーワードでググってしまい、直ぐに解決しなかった。濡れ衣を着せてごめんなさい。


◎ mysisgitを疑い直してググッてみた

すぐにレジストリ「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont」のキー「0」を「Lucida Console」→「*MS ゴシック」に変更すれば良いという情報を発見したのだが… ここが長い道のりの始まりだった。
その通りにしようと思いレジストリエディタで「HKEY_LOCAL_MACHINE\~\TrueTypeFont」を開いたら、違和感があって変更できなかったのだ。


違和感の内容は文字化けしているコマンドプロンプトの文字コードはShift-JIS、つまりCP932なのだが、キー「932」の設定値はMSゴシックと、正しそうな設定だということだ。そんな訳でもう少し調べてみることにした。


◎ 調査と実機確認の結果

検索で引っかかった「コンソール(cmd.exe)の文字コードを UTF-8 に」や「MSのナレッジベース」を読んで分かったのは、「HKEY_LOCAL_MACHINE\~\TrueTypeFont」の設定により、コマンドプロンプトのフォント設定画面の一覧に表示されるフォントが決まるということだ。確かにフォント一覧には限られたフォントしか表示されない。

ここから書くことはWebで見つかった断片的な情報と、自分のPC(Windows7 64bit)で色々試した結果から推測したもののため、間違った部分があるかもしれない。

表示するフォントは以下のアルゴリズムで決まる。
  1. コマンドプロンプトの現在のコードページを取得
  2. 各レジストリキーの名前について、以下のチェックを行う。
    1. 名前を先頭からスキャンして数字になる部分を切り出す。
    2. 切り出した文字を数値に変換する。
    3. 現在のコードページが特定のものでなければ、数値に変換した値が0になるキーのフォントが表示される。
    4. ただし、フォントの属性チェックが走り、条件(等幅であるなど)を満たさないフォントは表示されない。うちの環境で表示できたのは「Lucida Console」, 「Consolas」, 「Courier New」だけだった。
    5. 現在のコードページが特定のものである場合は、数値に変換した値がコードページと同じキーのフォントが表示される。特定のコードページというのはおそらくレジストリに初めからエントリされている932, 936, 949, 950でおそらく漢字圏のコードページだけの特別処理なのだろう。
    6. これも、フォントの属性チェックが走るが、0の場合と少し条件が異なる。表示ができたのは「MS ゴシック」, 「Osaka-等幅」, 「VL ゴシック」などの日本語フォントのみだった。(試してないがWebの情報だとMeiryoKe_Consoleもいけるらしい)
  3. 例外としてラスタフォント(Terminal)は必ず表示する。
複雑で例がないと分かり難い。レジストリが
00          フォントA
000 フォントB
932    フォントC (Shift-JIS)
932.    フォントD
932a フォントE
936    フォントF
65001 フォントG (UTF-8)
だったとすると、コードページが932であればフォントC, D, Eが表示される。コードページ936ならフォントF。ここまでは直感的なのだが、コードページ65001はフォントA, Bが表示されるわけでWeb上にも困惑している人がちらほら。


◎ ややこしいことに…

上で決まるのはあくまでコマンドプロンプトの設定画面から設定できるフォントであって、直接設定の保存先を書き換えれば、設定画面に表示できないフォントも設定できる。では、設定の保存先がどこなのかというとこれがまたややこしい。

まず、大元の設定は「HKEY_CURRENT_USER\Console」にある。素の状態でコマンドプロンプトを使うと、ここの設定が読み込まれる。ただ、ここの設定は読み込み専用で、コマンドプロンプトの設定画面から設定を変更しても書き込まれない。
変更のあった設定値だけ、別の場所に書き込まれてそちらが優先して読まれる。

その書き込み先というのはコマンドプロンプトをショートカットから起動した場合はショートカットファイル、exeを直接起動した場合は「HKEY_CURRENT_USER\Console」の下にディレクトリが掘られ、その中に保管される。exeが変わると作られるディレクトリ名が変わる。例えば64bit版Windowsだと、32bitと64bitの2つのcmd.exeがあるが、ディレクトリ名はそれぞれ「%SystemRoot%_System32_cmd.exe」, 「%SystemRoot%_SysWOW64_cmd.exe」となる。

UTF-8で設定画面からは選べない日本語フォントを設定したい場合、ここの設定値を変えれば良い。ショートカットの書き換えは難しいのでレジストリを書き換える。実はexeを直接起動した場合に作られるディレクトリはexeのパスで決まるわけではなく、起動時のウィンドウタイトルで決まり、これはstartコマンド指定できる。手順は以下。
  1. cmd.exeのショートカットを作成する。
  2. リンク先を「cmd.exe /c start "utf8" cmd」に変更する。
  3. そのリンクからコマンドプロンプを起動して、フォントの設定変更を行う。この時ボールドフォントにチェックを入れておくと良い。(後述)
  4. utf8以下に新しい設定値が作られるので、それを書き換える。注意点としてフォントの設定はFaceName, FontSize, FontWeightの3つが揃っていないと不正と判断され、親ディレクトリの設定が読み込まれてしまう。項番3でフォントをボールドフォントにしないとFontWeightというキーが作られないため、このディレクトリのフォント設定は読まれない。別に自分でキーを追加しても可。
  5. ついでにCodePageというキーを65001にしておけば起動毎のchcpが不要になる。

注意点としては、やはり任意のフォントが設定できるわけではなくコードページ932で一覧に表示できないフォントは指定しても表示がおかしくなるということと、以降コマンドプロンプトの設定画面を使おうとしても日本語フォントは選べないため、regeditを使用するなくなってしまうということだ。


◎ あの日、私に何が起こっていたか?

私はmsysgitをインストールする前の時点でコマンドプロンプトを使ってフォントの設定を書き換えたことがあり、ショートカットにその時設定されたフォントが残っていた。でも、Visual Studioの管理コンソールは使ったことがなかったのでショートカットにフォントの設定は残っておらず、レジストリキーのデフォルトの設定「HKEY_CURRENT_USER\Console\FaceName」が読まれた。ここの設定がmsysgitで書き換えられたので文字化けが発生していたというわけである。

コマンドプロンプトのフォントの設定画面ではフォントの表示はMSゴシックになっていたが、それはフォント選択リストの仕様によりコードページ932では「Lucida Console」は表示できなかったためであり、実際の設定値は「Lucida Console」になっていたのだ。だから改めてフォントを設定しなおせば文字化けは治っていたはずである。


◎ 最後に残った謎

色々試して納得しかかったけれど、よくよく考えると1つだけ説明のつかないことがある。それは何故ググったらmsysgitで文字化けしたら「HKEY_LOCAL_MACHINE\~\TrueTypeFont」を直せという情報が引っかかるのかだ。実際自分の環境ではここを直さなくても文字化けは治ったし、調査結果からは治るとも思えない。OSバージョンのせいかとも思ったけれど情報元の人もWindow7(64bit)だし、複数いるようだし、勘違いということもなさそうだ。

自分的には正しい対策は「HKEY_CURRENT_USER\Console\FaceName」を書き換えることのはずなので納得が行かない。でももう調べる気力は起きない。もう既に困らなくなる程度に情報が得られてからも突っ込んで調べ過ぎた感がある。
教えてエロイ人。


0 件のコメント:

コメントを投稿