C#で拡張子をレジストリに登録する

C#
06 /15 2017
こんにちは、Takymです。
以前に、C#のMicrosoft.Win32.RegistryKeyクラスを使用して拡張子登録 という記事を書いた事があります。
今回はそのリメイク版みたいな物です。

登録の仕方

まず、拡張子をレジストリに登録する方法を簡単に説明します。
HKEY_CLASSES_ROOTに、「.xxx」というキーを作成します。
xxxは拡張子の名前です。必ずドット(.)から始めます。
次に、作成したキーの限定の所に任意の文字列を入れます。
そしたら、その文字列と同じ名前で、HKEY_CLASSES_ROOT内にキーを作成します。
作成したキーの限定の値を変更すると、エクスプローラの種類の所に表示される文字列を変更する事ができます。
次に、そのキーにshellキーを作成してその中にopenキーを作成します。
さらにopenキーの中にcommandキーを作成します。
commandキーの限定を特定のコマンドラインに変更すれば拡張子の登録は完了です。

サンプルソース

C#でレジストリを変更するには、Microsoft.Win32.RegistryKeyクラスを使用します。
using System;
using System.Collections.Generic;
using Microsoft.Win32;

namespace Test
{
	/// <summary>
	///  ファイル拡張子を管理する為のクラスです。
	/// </summary>
	public class FileExtension : IDisposable
	{
		/// <summary>
		///  変更する拡張子です。先頭に<c>"."</c>を付けません。
		/// </summary>
		public string Extension { get; }

		/// <summary>
		///  拡張子の説明です。エクスプローラの種類に表示される文字列です。
		/// </summary>
		public string Description { get; set; }

		/// <summary>
		///  ファイルアイコンのファイルパスです。
		/// </summary>
		public string IconPath { get; set; }

		/// <summary>
		///  アイコンインデックスです。
		/// </summary>
		public int IconIndex = -1;

		/// <summary>
		///  拡張子の動詞の一覧です。
		/// </summary>
		public Dictionary<string, (string Command, string Description)> Verbs { get; }

		/// <summary>
		///  オブジェクトが破棄されているかどうかを取得します。
		/// </summary>
		protected bool IsDisposed { get; private set; }

		private RegistryKey _key_b, _key_ico, _key_shell;

		/// <summary>
		///  操作する拡張子を指定して、新しいインスタンスを生成します。
		/// </summary>
		/// <param name="ext">変更する拡張子です。先頭に<c>"."</c>を付けません。</param>
		public FileExtension(string ext)
		{
			this.IsDisposed = false;
			this.Extension = ext;
			this.Verbs = new Dictionary<string, (string Command, string Description)>();

			using (var _key_a = Registry.ClassesRoot.CreateSubKey("." + ext, true)) {
				string _key_name = (string)(_key_a.GetValue(null, ext + "_auto_file"));
				_key_a.SetValue(null, _key_name);
				_key_b = Registry.ClassesRoot.CreateSubKey(_key_name, true);
				_key_ico = _key_b.CreateSubKey("DefaultIcon", true);
				_key_shell = _key_b.CreateSubKey("shell", true);
			}
		}

		/// <summary>
		///  現在のオブジェクトの内容をレジストリに保存します。
		/// </summary>
		public void Save()
		{
			if (IsDisposed) throw new ObjectDisposedException(nameof(FileExtension));

			_key_b.SetValue(null, this.Description);
			_key_ico.SetValue(null, $"\"{this.IconPath}\"" + (IconIndex >= 0 ? ", " + IconIndex : string.Empty));

			foreach (var item in this.Verbs) {
				using (var _key_c = _key_shell.CreateSubKey(item.Key, true))
				using (var _key_d = _key_c.CreateSubKey("command", true)) {
					_key_c.SetValue(null, item.Value.Description);
					_key_d.SetValue(null, item.Value.Command);
				}
			}
		}

		/// <summary>
		///  このオブジェクトのファイナライザーです。
		/// </summary>
		~FileExtension()
		{
			this.Dispose(false);
		}

		/// <summary>
		///  このオブジェクトで使用している全てのリソースを開放します。
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		///  このオブジェクトのインスタンスを破棄させます。
		/// </summary>
		/// <param name="disposing">
		///  このクラス内に存在する、他の<see cref="System.IDisposable"/>も破棄するかどうかです。
		/// </param>
		protected virtual void Dispose(bool disposing)
		{
			if (!IsDisposed) {
				if (disposing) {
					_key_b.Close();
					_key_ico.Close();
					_key_shell.Close();
				}

				this.Description = null;
				this.IconPath = null;
				IconIndex = 0;
				this.Verbs.Clear();

				IsDisposed = true;
			}
		}
	}
}
このプログラムを以下の様に呼び出します。
using (FileExtension fe = new FileExtension("ext")) {
	fe.Description = "拡張子登録の実験 (電卓を開くだけのファイル)";
	fe.IconPath = @"C:\Windows\System32\calc.exe";
	fe.IconIndex = 0;
	fe.Verbs.Add("open", (@"C:\Windows\System32\calc.exe", "電卓を開く"));
	fe.Save();
}
このプログラムを実行すると、extファイルを開くと電卓が開かれるようになります。

感想

昔書いたプログラムをもう一度書き直してみると、昔書いたプログラムより見やすく書ける事が分かりました。
(※この記事はリメイク版)
間違いの指摘、誤字・脱字、分からない事等はこの記事のコメント欄にお願いします。
最後まで読んでくださってありがとうございました。また次回も読んでくれると嬉しいです。
関連記事
スポンサーサイト

コメント

非公開コメント