Windows の関連づけ設定の仕組み

概要

念願の ThinkPad (Windows XP 搭載) 購入を受けまして、Windows XP で新しくなった関連づけシステムについて調べてわかった事を書いていきます。

背景

Windows XP にした途端に関連づけがうまく働かなくなった、 という話をいろいろな日記や掲示板などで見かけます。 具体的には 「画像ファイルの関連づけ設定を変更しても 『Windows 画像とFAXビューア』 が起動してしまって困っている」といったものです。 私も、叔父の PC を設定する時に困った覚えがあります。

改めて関連づけの仕組みについて調べたところ、 MSDN の開発者向け文書に詳しいものを見つけました。 Creating a File Association という文書です。 これを読むと、現在の仕様がかなり複雑になっている事が分かります。 互換性のために残っている過去の仕様が主な原因ではありますが、 それらを理解せずに理解できるような仕様でもないため、 理解するのが少し大変な状態になっています。

関連付け設定方法の概説

まず関連付けに使われる設定方法で一番知られているのは 「ファイルクラス」を定義する方法です。 具体的には HKEY_CLASSES_ROOT 下にある "." 付きの拡張子と同名のキーを使うものです。 HKEY_CLASSES_ROOTHKEY_LOCAL_MACHINE\Software\Classes の別名ですから、 これはシステム全体に対する設定になっています。 システム全体に対する関連付け設定は全ユーザに共通した設定になるのですから、 ユーザ個別の関連付け設定をこの方法で行う事はできません。 恐らくこれはマルチアカウントの意識がなかった Windows 9x 時代からの仕組みなのでしょう。

ユーザ個別の関連付け設定を可能にするために導入されたと思われるのが User Customized Key と呼ばれる設定方法です。 この方法では名前の通り、ユーザごとに関連づけを自由に定義できます。 なお、 これはユーザ個別の設定ですから管理者権限のないユーザでも設定を変更可能である必要があります。 そのため必然的に HKEY_CURRENT_USER 下にあるキーで行うようになっています。

仕様の概要

Windows XP における関連づけ設定に使うキーを優先される順に並べると次のような表になります。 ただしここでは Windows XP 標準状態での .bmp ファイルを例にしています。

MSDN での呼び方 該当キー 用途
User Customized Key HKEY_CURRENT_USER\Software
\Microsoft\Windows
\CurrentVersion\Explorer
\FileExts\.bmp
ユーザーごとの関連づけ設定
ProgID Key HKEY_CLASSES_ROOT
\Paint.Picture
アプリケーションのバージョン管理機能(もどき)付き関連づけ指定
System File Association Key HKEY_CLASSES_ROOT
\SystemFileAssociations\.bmp
全ユーザー共通の関連づけ設定
System File Association
Perceived Type Key
HKEY_CLASSES_ROOT
\SystemFileAssociations\image
同類ファイルタイプに共通の関連づけ設定
Basic Class Key HKEY_CLASSES_ROOT\* 全ファイルタイプに共通の関連づけ設定
All File System Objects Key HKEY_CLASSES_ROOT\file

HKEY_CLASSES_ROOT\folder

HKEY_CLASSES_ROOT\directory
すべてのファイル、フォルダ、ディレクトリの関連づけ設定 (そもそも拡張子を区別せず)

基本的に Windows の関連づけシステムでは拡張子を最重要視します。 これは OS が拡張子以外でファイルタイプを識別できないために当然の事ですね。 上に挙げたどのキーでも、まずは拡張子と同名のキーを使います (下二つをのぞく)。

ProgID Key

まず、一般的に最もよく知られていると思われる関連づけ設定のキーは ProgID Key だと思います。 これは元々の関連づけ設定方法を開発者用の約束事で拡張した方法です。 Windows はこのキーを使った場合、次のように関連づけ情報を取得します (先ほどに引き続き .bmp を例にします)。

  1. HKEY_CLASSES_ROOT\.bmp の標準値を取得("Paint.picture"だったとする)
  2. HKEY_CLASSES_ROOT\Paint.picture のサブキー CurVer の標準値を取得("Paint.picture.1"だったとする)
  3. HKEY_CLASSES_ROOT\Paint.picture.1 キーを取得、そこから関連づけ情報を取得

実はこの通りに設定しているアプリケーションは少なく、Microsoft の Word 97 でもこの通りには設定していませんね。よく使われているのは(あるいは古い方法) 次のように設定する方法です。

  1. HKEY_CLASSES_ROOT\.bmp の標準値を取得("bmpfile"だったとする)
  2. HKEY_CLASSES_ROOT\bmpfile キーを取得、そこから関連づけ情報を取得

さて、どちらの方法でも基本的には最後にたどり着いたキー(前者ではPaint.picture.1、 後者ではbmpfileキー)が関連づけを設定します。 その仕組みを紹介します。

まず、このキーの標準値は、 マイコンピュータやエクスプローラで「ファイルの種類」として表示される文字列になります。 このキーのサブキー「DefaultIcon」の標準値は、そのファイルのアイコンのパス(とインデックス)を指定します。 このキーのサブキー「shell」は、そのファイルタイプの関連づけ(アクション)を設定します。 アクションは、「shell」キーの下にそのアクション用のサブキー(名前は自由)を作り、 そのサブキー「Command」の標準値でそのアクションを定義します。 なおアクションはいくつでも定義できます。 その場合は「shell」キーの下に複数のアクション用のサブキーを作ります。 では最後に例を一覧表にまとめておきます。

キーの例 値の名前 値の例 意味・用途
HKEY_CLASSES_ROOT
\bmpfile
(標準) ビットマップ・イメージ 「ファイルの種類」で表示される文字列
HKEY_CLASSES_ROOT
\bmpfile\DefaultIcon
(標準) C:\WINDOWS\system32\shimgvw.dll,2 「ファイルの種類」で表示される文字列
HKEY_CLASSES_ROOT
\bmpfile\shell
(標準) open 標準(ダブルクリック)のアクションをサブキー名で指定
HKEY_CLASSES_ROOT
\bmpfile\shell
\open
(標準) 開く(&O) 右クリック時に表示されるこのアクションの名前
HKEY_CLASSES_ROOT
\bmpfile\shell
\open
MUIVerb @shimgvw.dll,-550 後述
HKEY_CLASSES_ROOT
\bmpfile\shell
\open\command
(標準) rundll32.exe C:\WINDOWS\System32\shimgvw.dll %1 コマンドラインによるアクションの定義
HKEY_CLASSES_ROOT
\bmpfile\shell
\open\ddeexec
(標準) Open("%1") DDE によるアクションの定義
HKEY_CLASSES_ROOT
\bmpfile\shell
\open\ddeexec
application msdev DDE を行うアプリケーションの指定
HKEY_CLASSES_ROOT
\bmpfile\shell
\open\DropTarget
Clsid {E84FDA7C-1D6A-45F6
-B725-CB260C236066}
指定 CLSID の COM コンポーネントの IDropTarget インターフェイスを使うアクションの定義
HKEY_CLASSES_ROOT
\bmpfile\shell
\xnview
(標準) XnView で開く(&X) 右クリック時に表示されるこのアクションの名前
HKEY_CLASSES_ROOT
\bmpfile\shell
\xnview\command
(標準) "C:\Program Files\XnView\XnView.exe" "%1" アクションの定義
HKEY_CLASSES_ROOT
\bmpfile\shell
\bmp2png
(標準) PNG に変換(&P) 右クリック時に表示されるこのアクションの名前
HKEY_CLASSES_ROOT
\bmpfile\shell
\bmp2png\command
(標準) "C:\Program Files\bin\bmp2png.exe" "%1" アクションの定義

なお、DDE (Dynamic Data Exchange) について私はまったく知りません(興味がない)。 ただ、注意しないといけないのはアクション定義の優先順位です。 アクションを表すキーのサブキーには command、 ddeexec、 DropTarget があり、 これらはそれぞれ違う方法でアクションを定義しています。 この中で最優先されるのは DropTarget です。 従ってこのキーが存在しているファイルタイプの command キーをいくら更新しても関連づけは変わりません。

これについて何を注意しなければならないのかというと、 まず仕様としてファイルタイプのキーで標準のアクションを指定しない場合、 open という名前のキーで定義されたアクションが標準になります。 従って、アプリケーションの「あるファイルタイプに関連づけする」 という処理はだいたいこの open キーを書き換えています。 しかし、この DropTarget は Windows XP で初めて搭載された機能ですので XP 以前に作られたアプリケーションではこのキーを書き換えません。 するとアプリケーション側からすると正常に関連づけ設定ができているのに実際には DropTarget の設定が優先されて関連づけができていない状態になってしまいます。 これがよく聞かれる「関連づけが更新されない」問題の原因です

なお、この場合アイコンの変更は反映されます。 また、右クリックの時に出てくる文字列も変更されると思うのですが、 後述の MUIVerb という仕組みがあるため、 その文字列も更新されません。 つまりアイコンと「ファイルの種類」が変更されるのに起動するアプリケーションが変化しない、 という状況になってしまうわけですね。厄介です。

User Customized Key

前述の通り、ユーザーごとに独立した設定を行う事ができる上に最も優先される設定です。 HKEY_CURRENT_USER \Software \Microsoft \Windows \CurrentVersion \Explorer \FileExts キーのサブキー群で設定が行われます。 このキーのサブキーに拡張子と同名のキーを作成し、 そのキーに "Application" という名前の文字列値を作成します。 この文字列値の値がこのファイルタイプのファイルを開く標準アプリケーションになります。 これにはシステムに登録されているアプリケーション(後述)の実行ファイル名、 あるいは実行ファイルのパスで指定できます。

少々話がそれますが、 システムに登録されているアプリケーションというのはファイルの右クリックメニューの項目 「プログラムから開く」から「プログラムの選択」で出てくる一覧画面で現れるものです。 これは次のレジストリキーに登録されています(登録方法は割愛)。

HKEY_CLASSES_ROOT\Applications

どうもこの仕様が作られた頃は Microsoft の方針が昔のものと違うように感じられます。 従来通りの関連づけではアプリケーションもアイコンもパスで指定するため、 アプリケーションの場所を変更してしまうとそのアプリケーションに関連づけられていた すべてのファイルの関連づけがおかしくなります。 そこで、関連づけという概念を従来の「拡張子とアプリケーション、アイコン」 という関係から「ファイルタイプとそれを開くアプリケーション」 の関係にしようとしているように思われます。 後者のメリットは、 アプリケーション自身が自分自身の場所を申告する事でアプリケーションのパスが変わってもすぐに全ファイルの関連づけが更新できる事でしょう。 デメリットは、アイコンなどの設定が独立していないためアプリケーション側の指定したもの、 ファイルアイコンを自由に変更できません(このあたりは中途半端ですね)。 Macintosh の思想に影響を受けているのだと思いますが、 個人的にはその思想がどんなにすばらしいものだとしても、 複数の思想が入り乱れるぐらいなら導入しない方が無難だったと思いますね(苦笑)。

SystemFileAssociations Key

この種類の関連づけ方法は正直に言って何のためにあるのか私にはわかりません。 ProgID キーと何が違うのかと思ってしまいます(苦笑)。 ただ、違う事があるとすれば拡張子と同名のキーに直接関連づけ情報を書き込む事でしょうか。 あまりこの設定を使う事はないと思います。

SystemFileAssociations PerceivedType Key

PerceivedType を用いて関連付けを設定すると、 個々の具体的なファイルタイプではなくファイルタイプの「分類」に対して関連付けを行う事ができます。 例えば各種の画像ファイルタイプに同じ画像ビュワーに関連づけたいなど、 同じ分類のファイルタイプに一括して関連づけ設定をしたい場合に役立ちます。

PerceivedType とは、先の話で言うところのファイルタイプの「分類」と同じものです。 例として .bmp、 .png を考えましょう。 これらはみな画像ファイルの形式で、 それもベクトル画像ではなくラスタ画像です。 Windows XP ではラスタ画像という分類にあたる PerceivedType として image というタイプが用意されています。

具体例として .bmp などのラスタ画像のファイルタイプに image という PerceivedType を設定する方法を述べます。 まず HKEY_CLASSES_ROOT 下の .bmp と .png というキーに PerceivedType という文字列値を定義し、その値を image にします。 次に HKEY_CLASSES_ROOT\SystemFileAssociations キーの下に image という名前のキーを作ります。 このキーで ProgID キーと同様の関連づけ情報を定義すると、 同じ PerceivedType が指定された全ファイルタイプに対し、一括してアクションおよびアイコンが適用されます。 なお、前述の優先順位によって PerceivedType の設定が上書きされる事がありますので注意してください。

なお、Windows XP があらかじめ定義している PerceivedType は次の 6 つです。

残念ながら Windows XP では独自に PerceivedType を定義する方法は無いようです。 したがって、 この仕組みでは定義済みタイプに入らない種類のファイルに関連付けを行う事はできない、 と考えた方が良いでしょう。

MUIVerb キー

最後に MUIVerb キーについて説明します。 まず MUI は Multi User Interface の略でして、 多言語対応の一環として Windows が複数の言語にローカライズされた複数のユーザーインターフェイスを用意する、 というコンセプト(?)があります。 要するに MUI という思想の影響がありそうな verb (動詞)という感じです (まあ名前はどうでもいいですしね(苦笑))。 実際にこれが何の役割を果たすかというと、 言語環境に応じてアクションの表示名を自動的に切り替える機能を果たします。

まず各ファイルタイプのキー(ProgID\bmpfile、SystemFileAssociations\bmpfile など)のサブキー shell の下にある、 そのファイルに対するアクションを定義するレジストリキー(長い(苦笑))ですが、 一般的にはその標準値に右クリックメニューでの項目名を指定する事になります。 しかしこれではレジストリ上に表示名を直接(プログラミング的に言えば静的に) 打ち込む事になるため、 アプリケーション作者が言語環境に応じて表示名を切り替えるのが難しくなります。 そこで言語環境に応じて表示名を切り替える仕組みが求められてきます。

MUIVerb によるアクションの表示名指定は次のような手順で行います。 アクションの定義キーに "MUIVerb" という文字列値を作り、 そこに「表示させたい項目名の格納されたファイルのパス」と、 「そのファイル内に格納されたその項目名の文字列リソース番号」を指定します。 なお、一般的なファイル参照と違うためかこの項目の値は先頭に "@" をつけます。 具体的な例をあげると次のようになります。

@C:\WINDOWS\System32\shimgvw.dll,-550

これはもう Windows アプリケーション(MFC)の開発者でないと分からない事かもしれませんが、 多くの Windows アプリケーションは内部に「リソース」という形でアイコンや文字列などを持っていますので、 MUIVerb にそれを指定して用います。 この方法には何のメリットがあるのかと言うと、 アプリケーション内のリソースには言語環境に応じて内容を自動的に切り替える機能があります。 つまり日本語環境では日本語の文字列リソースを、 英語環境では英語の文字列リソースを表示させる事ができるようになっているわけです。 MUIVerb を利用する場合、 アプリケーションに文字列の管理を任せる事になるのでこの環境に応じた自動切り替え機能が使えます。 しかし逆を言うとアプリケーションの開発環境と開発技術が必要になるので個人的には 「かなりどうかと」思う機能ではあります。

ただ、一つ気をつけなくてはならない事があります。 この MUIVerb キーの設定がある場合、 アクションを表すキーの標準値に何がセットされていようと MUIVerb の方が優先されます。従って MUIVerb を使って表示名が設定されているアクションは単純に標準値を書き換えるだけでは変更が反映されません。

終わりに

調べている最中に分かってきた事が多く、非常に疲れました(苦笑)。 私がこの記事を書く事で得たものは、 PerceivedType の有用性と DropTarget という騒動の犯人です。 まあ本当は後者のためだったはずですが・・・ この疲れ方は「釣り合ってない」なぁと今更ながら思ってみたりします(苦笑)。

謝辞

やすひささんよりいただいたフィードバックにより、 この記事の内容を改善できました。 ありがとうございます。