コントロールのインストール

Last Updated 2011/09/21


作成したコントロールを適切なディレクトリに格納し、ツールボックスにコントロールを示すビットマップを表示する、などの手続きをコントロールのインストールと呼ぶことにします。

ここでは、以下にリストアップするテーマについて解説します。

ツールボックス用ビットマップの設定

コントロール用アセンブリ(.dll ファイル)を格納する

コントロールをツールボックスに登録する

登録したコントロールを削除する

グローバルアセンブリキャッシュに登録する


ツールボックス用ビットマップの設定

コントロールは特に指定しない限り、ツールボックスにはデフォルトのビットマップ ToolboxIcon が表示されます。しかし、これでは何をさすのかが分からないので、独自のビットマップを設定することにしましょう。

とはいってみたものの、Visual Studio のヘルプの中にその手順が書かれていません。ところが、偶然というか、幸いというか、ToolboxBitmapAttribute クラスの項の中に解説ではありませんが、それらしいことに触れてはいます。そこで、WEB サイトからかき集めた情報と合わせ考えると、以下の手順でよさそうです。

  1. まず、ツールボックスに表示するコントロール用のビットマップ(16 x 16 ピクセル)を用意する(アイコンも可能)
  2. コントロール用プロジェクトにビットマップファイルを追加する
  3. ソリューションウインドウの中にあるビットマップファイル名をマウスで右クリックして、[プロパティ] を表示する
  4. [ビルドアクション] の内容を「埋め込まれたリソース」に変更する
  5. コントロール用クラスの宣言文の前に、ToolboxBitmapAttribute 属性を使ってビットマップを指定する

以下は、.Net Framework のヘルプの ToolboxBitmapAttribute クラスのコンストラクタの中にあるサンプルコードの一部をそのまま抜き出したものです。

  [System.Drawing.ToolboxBitmap(typeof(StopSignControl2), "StopSignControl2.bmp")]
  public class StopSignControl2: System.Windows.Forms.UserControl
  {
    ....
  }

これで準備ができたので、コントロールをビルドするだけです。ビルドが終わったところで、「コントロール用アセンブリを格納する」で説明するディレクトリにアセンブリ(.dll ファイル)をコピーします。次に、ツールボックス内をマウスで右クリックすると表示されるポップアップメニューの [アイテムの選択] でコントロールを選択すると、ツールボックスに目的のコントロールのビットマップが表示されるはずです。

ところがです! 依然としてデフォルトのビットマップになってしまいます。少なくとも、私の環境、私の手順によってではです。

コントロール用アセンブリ(.dll ファイル)を調べると、ビットマップがリソースとして埋め込まれていることは確認しました。したがって、Visual Studio の IDE がアセンブリからビットマップを抜き出すところで問題が発生したものと想像できます。

ビットマップをアセンブリに組み込む方法はうまくいかないことを説明しました。次に、うまくいく手順について説明します。

既存のコントロールのビットマップを借用する

以下は、ToolboxBitmapAttribute クラスのコンストラクのうちのクラス型だけを指定する構文です。ここでは、コンポーネント用ビットマップとして Button クラスのものを借用しています。

  [System.Drawing.ToolboxBitmap(typeof(System.Windows.Forms.Button))]
  public class StopSignControl3 : System.Windows.Forms.UserControl
  {
    ....
  }

このコードはうまくいくきます。Button クラスなどの既存のコントロールと同じビットマップでよければこの方法が一番簡単です。

ビットマップファイルを添付する

以下は、ToolboxBitmapAttribute クラスのコンストラクのうちのビットマップファイル名を指定する構文です。ここではフルパスで指定していますが、アセンブリ(.dll ファイル)と同じディレクトリ内にビットマップファイルを置くのであればファイル名だけでかまいません(例:stop.bmp)。

  [System.Drawing.ToolboxBitmap("c:\\stop.bmp")]
  public class StopSignControl : System.Windows.Forms.UserControl
  {
    ....
  }

この場合はビットマップをリソースとして組み込むわけではなく、ファイルを添付する形になりますが確実にうまくいきます。すでに、説明しましたが、できればアセンブリにリソースとして組み込む方法がスマートではありますが、正常に動作しないのではしかたありません。私はビットマップを添付する方法を取りたいと思います。

【追記】

その後、WEB サイトをあたっていたところ、ヒントになるサイトを見つけました。参考にはなりましたが、結局、自力で解明することになりました。この問題は意外と深刻ですので、詳しい説明が必要です。そこで、「ツールボックスにビットマップを設定する」のページを用意しました。


コントロール用アセンブリ(.dll ファイル)を格納する

完成したコントロールはどこに格納しておくのが最適なのでしょうか。

ツールボックス内をマウスで右クリックすると表示されるポップアップメニューの [アイテムの選択] を選択し、表示されたダイアログボックスの [参照] を選択すると、最初に表示されるディレクトリは私の環境の場合、次のとおりです。

  C:\Program Files\Microsoft Visual Studio 8\Common7\IDE

つまり、Visual Studio はコントロール用アセンブリはこのあたりにあることを期待しているということになります。そこで、IDE ディレクトリの下層に自作したコントロールを格納する専用のディレクトリを作成し、そこに格納するのがベストといえるのかもしれません。私の場合、IDE ディレクトリの下に "MyCompo" ディレクトリを作成し、そこに格納しています。


コントロールをツールボックスに登録する

ツールボックス内にも同様に、自分専用のタブを作ることをすすめます。タブを追加する手順は簡単です。ツールボックス内をマウスで右クリックすると表示されるポップアップメニューの [タブの追加] を選択し、適当なタブ名を入力するだけです。

自分専用のタブを作成したところで、そのタブにフォーカスを与えて、[アイテムの選択] で目的のコントロールを指定すると、コントロールのツールボックスへの登録は完了です。


登録したコントロールを削除する

コントロールをツールボックスに登録する手順については、多くの WEB サイトで取り上げていますが、コントロールを削除する方法について触れているところはありません。もちろん、Visual Studio のヘルプの中にも説明はありませんね。

先に何度も触れましたが、ツールボックス内をマウスで右クリックすると表示されるポップアップメニューの [アイテムの選択] を選択し、表示されたダイアログボックス内にリストアップされるコンポーネントの中の削除するコントロールのチェックをはずして [OK] します。

このとき、ダイアログボックスの [フィルタ] に、削除するコンポーネントを格納するタブ名を入力すると、コンポーネントを絞り込むことができます。たとえば、"MyCompo" を入力すると、そのタブに含まれるコンポーネントだけがリストアップされます。


グローバルアセンブリキャッシュに登録する

グローバルアセンブリキャッシュ(以後、GAC)はそもそも、どこにあるのか。Visual Studio のヘルプを見てもなかなか分かりにくいものです。しかし、「アセンブリ キャッシュ ビューア (Shfusion.dll) 」という項目に中で見つけました。要するに、Windows ディレクトリの中にある assembly ディレクトリがそうです(このディレクトリは Hidden 属性です)。

さて、私はコンポーネントを GAC に登録することをすすめません。というのは、GAC にゴミになるかもしれないコンポーネントを登録することに抵抗感があるからです。ともあれ、コンポーネントを GAC に登録する手順について説明だけはしておきます。ポイントは次の 2 点です。

アセンブリに厳密な名前を付ける

厳密な名前は以下に示す要素で構成されています。

まず、厳密な名前とはどんなものかを確認しておきましょう。以下は、System.dll の厳密名を取得するコードです。

private void button1_Click(object sender, System.EventArgs e)
{
  Assembly assembly = Assembly.Load("mscorlib.dll");
  string dir = System.IO.Path.GetDirectoryName(assembly.Location);

  AssemblyName name = AssemblyName.GetAssemblyName(dir + "\\System.dll");

  Text = name.FullName;
}

実行結果: System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

デジタル署名

Visual Studio のヘルプでは 2 つの意味で「署名」を使っています。現に、署名に関係するツールとして、sn.exe と signtool.exe の 2 つがあります。ちなみに、"sn" は "Strong Name" の略です。

sn.exe に対する .Net Framework SDK の説明は、「厳密名ツールは、厳密な名前を使用してアセンブリに署名する場合に役立ちます。Sn.exe には、キーの管理、署名の生成、署名の検査に関する各オプションが用意されています。」です。一方、signtool.exe に対するそれは「署名ツールはコマンド ライン ツールで、ファイルにデジタル署名を添付し、ファイルの署名を検証し、ファイルにタイム スタンプを付けます。」です。

「アセンブリへの署名」と「ファイルにデジタル署名を添付」と微妙な表現ですが、英語の単語は同じものを使っているとしても両者の意味は違うのではないでしょうか。

ネットワーク用語としての「デジタル署名」はネットワークを通じてファイルをダウンロードすべきかどうかを判断するとき、あるいは受信したファイルが改ざんされているかどうかをチェックする目的で使うものと理解しています。したがって、signtool.exe のほうの「署名」はネットワーク用語としての「デジタル署名」を、また、sn.exe のほうの「署名」は厳密な名前を付けるためのものと考えていいのではないかと思います。

いずれにしろ、「デジタル署名」のほうの解説は省略します。

公開キーの作成

Visual Studio 2005 の場合は、コンポーネントのプロジェクトの [プロパティ] を表示し、[署名] のページを開きます。

[アセンブリの署名]-[厳密な名前のキーファイルを選択してください] のコンボボックスを開くと、次の 2 つのリスト項目があります。

キーファイルがすでにある場合は、[参照] を選択すると、ファイルを選択するダイアログボックスが表示されますので、.pfx ファイルまたは .snk ファイルを選択します。ファイルがまだない場合は、[新規作成] を選択すると、各条件を設定するダイアログボックスが表示されます。

Note PFX は "Personal Information Exchange" の略で、「個人情報の交換」とでも訳せばいいのでしょうか。要するに、パスワードで保護しているという意味のようです。

[キーファイル] にはキーを格納するファイル名(.pfx ファイルまたは .snk ファイル)を入力します。そのとき、拡張子は不要です。

[キーファイルをパスワードで保護する] にチェックを入れる場合は、[パスワードの入力] にパスワードを入力し、[OK] すると、パスワードを含むキーファイル(.pfx ファイル)が作成され、プロジェクトに追加されます。一方、パスワードを使用しない場合は、.snk ファイルが作成されます。

カルチャ情報

プロジェクトの [プロパティ] を開いて、[アプリケーション] のページの [アセンブリ情報] を選択すると表示されるダイアログボックスの [ニュートラル言語] で指定します。

指定のない場合のカルチャは neutral となります。ちなみに、カルチャを指定する文字列は "言語-国" の形式で、アメリカ英語の場合は "en-US"、日本語は "ja-JP" です。

Note Visual Studio に付属するアセンブリのカルチャはすべて neutral となっているので、通常はこれでいいのではないかと思います。

バージョン情報

プロジェクトの [プロパティ] を開いて、[アプリケーション] のページの [アセンブリ情報] を選択すると表示されるダイアログボックスの [アセンブリバージョン] で指定します。デフォルトのバージョン番号は、"1.0.0.0" となっていますので、実情に合わせて設定してください。

GAC 専用のディレクトリ内に格納する

GAC 専用のディレクトリは先に説明したとおり、Windows/assembly ディレクトリです。ところで、assembly ディレクトリはいくつかのディレクトリに別れていますが、自作のコンポーネントはどこに格納すればいいのでしょうか。

結論を先に言うと、どこでもいいようです。というのは、Gacutil.exe を使って登録すると、GAC ディレクトリ内のしかるべき位置にアセンブリをコピーしてくれるからです。

コンポーネントをデザイン時に使う場合は、「コンポーネント用アセンブリを格納する」で説明したとおり、自作コンポーネント専用のディレクトリに格納すればいいでしょう。

GAC に登録する

コンポーネントを GAC に登録する場合の標準的な手順は、Gacutil.exe を使用します。Gacutil.exe は私の環境では以下のディレクトリ内にあります。

    C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin

自作のコンポーネント(ここでは GroupBoxEx.dll と仮定します)を Gacutil.exe を使って GAC に登録するときの構文は以下のとおりです。

    gacutil /i GroupBoxEx.dll

これを実行すると、c:\Windows\assembly\GAC_MSIL の中に、以下に示すディレクトリを作成した上で GroupBoxEx.dll がコピーされます。

    C:\Windows\assembly\GAC_MSIL\GroupBoxEx\1.1.0.0__fec3d6b5812b905a\groupboxex.dll

"1.1.0.0__fec3d6b5812b905a" の "1.1.0.0" はアセンブリのバージョンです。それに続いて 2 つのアンダースコアがあって、"fec3d6b5812b905a" が続きますが、これはアセンブリの公開キートークンです。

また、Regedit.exe でレジストリを調べると、以下のキーの中に登録されています。

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion\GACChangeNotification\Default

このキーの値名と値(8 バイトのバイナリデータ)は以下のとおり。

    GroupBoxEx,1.1.0.0,,fec3d6b5812b905a,MSIL
    34 53 7F 3F A2 5B C9 01

値名は 5 つの要素にカンマ区切りされていて、それぞれの要素は次のようになっています。

  1. アセンブリ名
  2. アセンブリのバージョン情報
  3. カルチャ(neutral の場合は空の文字列)
  4. 公開キートークン
  5. プロセサのアーキテクチャ

「プロセサのアーキテクチャ」については、ProcessorArchitecture enum 型を参照してください。

さて、問題は 8 バイトのバイナリデータです。いろいろと手をつくしましたが依然として不明です。ということは、秘密にしなければならないデータであると考えられます。いすれにしろ、謎のデータではあります。

Windows エクスプローラを使って GAC に登録する

[.Net Framework ツール] の [アセンブリキャッシュビューア (Shfusion.dll)] の記事の中に、Windows エクスプローラを使ってもアセンブリを GAC に登録できると書いてあります。やってみましたが、うまくいきませんでした。何か手順が抜けているのか、私が何かを見落としているのかもしれませんが。

−以上−