ここでは、ファイル拡張子をアプリケーションに関連付ける方法を紹介します。関連付けを行うと、エクスプローラでその拡張子のファイルをダブルクリックした時に指定したアプリケーションで開くことができるようになります。また、エクスプローラでその拡張子のファイルを右クリックした時に表示されるコンテキストメニューに「開く」などの項目を追加することもできます。
さらにここでは、関連付けを解除する方法についても説明します。
拡張子に関する情報は、レジストリの「HKEY_CLASSES_ROOT」キー以下に登録されています。例えば、「.000」という拡張子のファイルがダブルクリックされた時に「myapp.exe」というアプリケーションでそのファイルを開くようにするには、「HKEY_CLASSES_ROOT\.000\shell\open\command」というキーに、名前がなく、データが「"myapp.exe" "%1"」の文字列値を作成します。
これが最も簡単な方法ですが、実際にこのように関連付けを行っているアプリケーションは稀です。一般的なやり方は、次のような感じになります。
上記の説明では、「open」(開く)というアクション(動詞)に対する関連付けを行っています。もし「print」(印刷)や「edit」(編集)など別のアクションに関連付けを行うのであれば、「HKEY_CLASSES_ROOT\.000\shell\open\command」の「open」を適当なアクション名に変更してください。
以上は最低限の設定で、さらにアイコン等の設定もレジストリに書き込んで行うことができます。詳しくは、以下のようなページが参考になります。
補足:ファイルの関連付けによりアプリケーションが起動した時、起動したアプリケーションからそのファイルのパスを取得するには、コマンドライン引数を調べます。コマンドライン引数を取得する方法は、「起動時のコマンドライン引数を取得する」をご覧ください。
補足:「"myapp.exe" "%1"」の「%1」には、ダブルクリックされたファイルのパスが入ります。「%1」をダブルコーテーションで囲んでいるのは、ファイルのパスにスペース文字が含まれていても、1つのコマンドライン引数として認識できるようにするためです。もしダブルコーテーションで囲まれておらず、ファイル名にスペース文字が含まれていた場合は、この引数をEnvironment.GetCommandLineArgsメソッドで取得した時、ファイルのパスがスペース文字で分割された複数の引数として取得されてしまいます。ダブルコーテーションで囲んだ時は、Environment.GetCommandLineArgsメソッドでも1つの引数として取得でき、この引数からは前後のダブルコーテーションが取り除かれます。
補足:複数のファイルを選択して関連付けで開いた時、1つのファイルにつき1つのアプリケーションが起動します(つまり、ファイルの数だけアプリケーションのインスタンスが起動します)。アプリケーションを複数起動させないようにする方法については、「二重起動を禁止する」を参考にしてください。
補足:エクスプローラでファイルを右クリックした時に表示されるコンテキストメニューに項目を追加する場合、COMを使用するともっと高度なことができます。COMを使用する方法は、「.NET Shell Extensions - Shell Context Menus - CodeProject」が参考になります。
上記の説明に従い、レジストリを操作して拡張子への関連付けを行うサンプルコードを示します。この例では、「.000」という拡張子を自分自身のアプリケーションに関連付けています。ファイルの種類の説明や、動詞の説明、アイコンの設定なども行っていますが、これらは必須ではありません。
'関連付ける拡張子 Dim extension As String = ".000" '実行するコマンドライン Dim commandline As String = """" + Application.ExecutablePath & """ ""%1""" 'ファイルタイプ名 Dim fileType As String = Application.ProductName + ".0" '説明(「ファイルの種類」として表示される) Dim description As String = "MyApplication File" '動詞 Dim verb As String = "open" '動詞の説明(エクスプローラのコンテキストメニューに表示される。 ' 省略すると、「開く(&O)」となる。) Dim verbDescription As String = "MyApplicationで開く(&O)" 'アイコンのパスとインデックス Dim iconPath As String = Application.ExecutablePath Dim iconIndex As Integer = 0 Dim rootkey As Microsoft.Win32.RegistryKey = _ Microsoft.Win32.Registry.ClassesRoot '拡張子のキーを作成し、そのファイルタイプを登録 Dim regkey As Microsoft.Win32.RegistryKey = _ rootkey.CreateSubKey(extension) regkey.SetValue("", fileType) regkey.Close() 'ファイルタイプのキーを作成し、その説明を登録 Dim typekey As Microsoft.Win32.RegistryKey = _ rootkey.CreateSubKey(fileType) typekey.SetValue("", description) typekey.Close() '動詞のキーを作成し、その説明を登録 Dim verblkey As Microsoft.Win32.RegistryKey = _ rootkey.CreateSubKey(fileType & "\shell\" & verb) verblkey.SetValue("", verbDescription) verblkey.Close() 'コマンドのキーを作成し、実行するコマンドラインを登録 Dim cmdkey As Microsoft.Win32.RegistryKey = _ rootkey.CreateSubKey(fileType & "\shell\" & verb & "\command") cmdkey.SetValue("", commandline) cmdkey.Close() 'アイコンのキーを作成し、アイコンのパスと位置を登録 Dim iconkey As Microsoft.Win32.RegistryKey = _ rootkey.CreateSubKey(fileType & "\DefaultIcon") iconkey.SetValue("", iconPath & "," & iconIndex.ToString()) iconkey.Close()
//関連付ける拡張子 string extension = ".000"; //実行するコマンドライン string commandline = "\"" + Application.ExecutablePath + "\" \"%1\""; //ファイルタイプ名 string fileType = Application.ProductName + ".0"; //説明(「ファイルの種類」として表示される) string description = "MyApplication File"; //動詞 string verb = "open"; //動詞の説明(エクスプローラのコンテキストメニューに表示される。 // 省略すると、「開く(&O)」となる。) string verbDescription = "MyApplicationで開く(&O)"; //アイコンのパスとインデックス string iconPath = Application.ExecutablePath; int iconIndex = 0; Microsoft.Win32.RegistryKey rootkey = Microsoft.Win32.Registry.ClassesRoot; //拡張子のキーを作成し、そのファイルタイプを登録 Microsoft.Win32.RegistryKey regkey = rootkey.CreateSubKey(extension); regkey.SetValue("", fileType); regkey.Close(); //ファイルタイプのキーを作成し、その説明を登録 Microsoft.Win32.RegistryKey typekey = rootkey.CreateSubKey(fileType); typekey.SetValue("", description); typekey.Close(); //動詞のキーを作成し、その説明を登録 Microsoft.Win32.RegistryKey verblkey = rootkey.CreateSubKey(fileType + "\\shell\\" + verb); verblkey.SetValue("", verbDescription); verblkey.Close(); //コマンドのキーを作成し、実行するコマンドラインを登録 Microsoft.Win32.RegistryKey cmdkey = rootkey.CreateSubKey(fileType + "\\shell\\" + verb + "\\command"); cmdkey.SetValue("", commandline); cmdkey.Close(); //アイコンのキーを作成し、アイコンのパスと位置を登録 Microsoft.Win32.RegistryKey iconkey = rootkey.CreateSubKey(fileType + "\\DefaultIcon"); iconkey.SetValue("", iconPath + "," + iconIndex.ToString()); iconkey.Close();
関連付けを削除するには、以下のように対象となるすべてのキーを削除します。
'拡張子 Dim extension As String = ".000" 'ファイルタイプ名 Dim fileType As String = Application.ProductName 'レジストリキーを削除 Microsoft.Win32.Registry.ClassesRoot.DeleteSubKeyTree(extension) Microsoft.Win32.Registry.ClassesRoot.DeleteSubKeyTree(fileType)
//拡張子 string extension = ".000"; //ファイルタイプ名 string fileType = Application.ProductName; //レジストリキーを削除 Microsoft.Win32.Registry.ClassesRoot.DeleteSubKeyTree(extension); Microsoft.Win32.Registry.ClassesRoot.DeleteSubKeyTree(fileType);
「HKEY_CLASSES_ROOT」について補足します。
「HKEY_CLASSES_ROOT」は、「HKEY_LOCAL_MACHINE\Software\Classes」(すべてのユーザー共通の設定)と「HKEY_CURRENT_USER\Software\Classes」(ユーザーごとの設定)が合成されたものです。上記のように「HKEY_CLASSES_ROOT」にキーや値を作成した時、実際に作成される場所が「HKEY_LOCAL_MACHINE」と「HKEY_CURRENT_USER」のどちらになるかは、状況によって変わります。
私が試した限りでは、「HKEY_CLASSES_ROOT」にキーや値を作成する時、「HKEY_LOCAL_MACHINE\Software\Classes」と「HKEY_CURRENT_USER\Software\Classes」のどちらにも存在しないキーに作成すると、「HKEY_LOCAL_MACHINE」に作成されました。しかし「HKEY_CURRENT_USER\Software\Classes」に存在するキーに作成すると、「HKEY_CURRENT_USER」に作成されました。
もし「HKEY_LOCAL_MACHINE\Software\Classes」と「HKEY_CURRENT_USER\Software\Classes」のどちらに書き込むかはっきりさせたい場合は、「HKEY_CLASSES_ROOT」を使わない方が良いでしょう。例えば上記の例で「HKEY_CURRENT_USER\Software\Classes」に書き込みたいのであれば、「ClassesRoot」を「CurrentUser」とし、CreateSubKeyで作成するサブキー名の前に「Software\Classes\」を付けます。
なお「HKEY_LOCAL_MACHINE」と「HKEY_CURRENT_USER」の両方に設定が存在する場合は、「HKEY_CURRENT_USER」の設定が優先されます。
設定を削除する時も注意が必要です。上記の例のように「HKEY_CLASSES_ROOT」のキーを削除すると、「HKEY_LOCAL_MACHINE\Software\Classes」と「HKEY_CURRENT_USER\Software\Classes」の両方にそのキーが存在していた場合は、「HKEY_CURRENT_USER」のキーだけが削除され、「HKEY_LOCAL_MACHINE」のキーは残ります。よってこの場合は、設定が完全に削除されません。
完全に設定を削除するには、「HKEY_LOCAL_MACHINE\Software\Classes」と「HKEY_CURRENT_USER\Software\Classes」の両方の設定を削除するか、「HKEY_CLASSES_ROOT」の設定を2回削除する必要があります。
(この記事は、「.NETプログラミング研究 第41号」で紹介したものです。)