連載

Windows業務アプリケーション開発 Q&A #3

グレープシティ株式会社 八巻 雄哉
2006/08/19

本記事は、業務アプリケーション向けコンポーネントのベンダであるグレープシティのテクニカル・サポート担当に対して、実際にプログラマーから問い合わせがあった質問を取り上げて解説しています。

.NETコンポーネントの配置方法は?

 以前はVisual Basic 6.0で開発していましたが、今回.NETでWindowsアプリケーションを構築することになりました。.NETの場合、アプリケーションの配布先においてアプリケーションが利用するコンポーネントをレジストリに登録する必要はないと聞いたのですが、具体的にはどのように配置(インストール)すればよいのでしょうか?

 .NETでは、コンポーネントはすべてアセンブリと呼ばれるファイル(たいていの場合、拡張子が「.dll」のDLLファイル)として提供されます。このアセンブリの配置方法には、大きく分けて「共有配置」と「プライベート配置」の2つがあります。

■共有配置

 共有配置は、その名のとおりアセンブリをマシン全体で共有したい場合の配置方法で、グローバル・アセンブリ・キャッシュ(GAC)と呼ばれる特殊なフォルダ(デフォルトではC:\WINDOWS\assembly)にアセンブリを配置します。

 GACフォルダは特殊なフォルダ構造になっているので、単純にアセンブリ・ファイルをコピーすることはできません。GACへの登録方法には、下記の3つの方法があります。

  1. Windows Installerを使ってインストールする
  2. GACツール(Gacutil.exe)を使う
  3. エクスプローラを使ってGACフォルダにアセンブリ・ファイルをドラッグ&ドロップする

 コンポーネントのアセンブリ・ファイルをGACへ登録しておけば、アプリケーションはそれがどこへ配置されていても動作します。ただし、GACへ登録できるのは「厳密名付きアセンブリ」だけです。

連載:インサイド .NET Framework - 第2回アセンブリのアイデンティティ(前編) - 厳密名がついたアセンブリとそうでないアセンブリ

 Visual Studio .NET 2003までは、厳密名ツール(Sn.exe)というコマンドラインのツールを使用しなければ厳密名による署名は行えませんでしたが、Visual Studio 2005ではIDE上から署名が可能となっています。

【参考】MSDN:方法 : アセンブリに署名する(Visual Studio)

■プライベート配置

 プライベート配置は、基本的に1つのアプリケーションだけがそのアセンブリを利用する場合の配置方法です。コードベースの設定でアセンブリの場所を指定する方法と、アセンブリ名などから推測して自動的にアセンブリを検索させる「プローブ」と呼ばれる機能に頼る方法の2つがあります。

 以下では、これら2つの方法についてWindowsApplication1.exeというWindowsアプリケーションがClassLibrary1.dllというアセンブリ(コンポーネント)を利用している場合の配置を例にして説明します。

<コードベースの設定でアセンブリの場所を指定する場合>

 アプリケーション構成ファイル(.exe.configファイル)を使ってアセンブリの検索フォルダをコードベース(<codeBase>要素)で指定します。

図1 アプリケーションの配置構成1

 ここでは図1のようなアプリケーションの配置構成を行うものとしましょう。この場合のアプリケーション構成ファイルの記述例は以下のようになります。


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="ClassLibrary1"
                          publicKeyToken="xxxxxxxxxxxxxxxxx"
                          culture="Neutral" />
        <codeBase version="1.0.0.0"
                  href=".\MyAssembly\ClassLibrary1.dll "/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
アプリケーション構成ファイルの記述例
(ClassLibrary1.dllが厳密名付きアセンブリの場合)
アプリケーションのEXEファイルがWindowsApplication1.exeの場合にはアプリケーション構成ファイルの名前は「WindowsApplication1.exe.config」となる。厳密名付きアセンブリの場合、任意のフォルダを指定することが可能で、任意のフォルダにコンポーネントを配置できる。

 この例ではアプリケーションのベース・フォルダ(EXEファイルのあるフォルダ)直下にあるMyAssemblyフォルダにコンポーネントを配置していますが、コンポーネントが厳密名付きアセンブリの場合にはアプリケーション構成ファイルにより任意のフォルダを指定することができます。

 コンポーネントが厳密名付きアセンブリでない場合、以下のようにアプリケーションのサブ・フォルダのみ指定可能です。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="ClassLibrary1"/>
        <codeBase href=".\MyAssembly\ClassLibrary1.dll"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
アプリケーション構成ファイルの記述例
(ClassLibrary1.dllが厳密名付きアセンブリでない場合)
厳密名付きアセンブリでない場合、アプリケーションのサブ・フォルダのみが指定できる。

<プローブによるアセンブリ検索を利用する場合>

図2 アプリケーションの配置構成2

 プローブによる検索ではコンポーネントの場所を特に指定する必要はありません。

図3 アプリケーションの配置構成3

 アプリケーションのベース・フォルダと、そのフォルダ配下にある目的のアセンブリの簡易名と同じフォルダ(アセンブリ・ファイルがClassLibrary1.dllの場合にはClassLibrary1フォルダ)が検索対象となります(図2、図3)。

図4 アプリケーションの配置構成4

 また、アプリケーション構成ファイルに下記のように<probing>要素を記述することで、プローブの検索対象を追加することもできます。例えば検索対象にbinフォルダを追加した場合には、図4のような配置が可能となります。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="bin" />
    </assemblyBinding>
  </runtime>
</configuration>
アプリケーションのベース・フォルダ配下のbinフォルダを検索対象に加える場合
アプリケーションのベース・フォルダより上の階層にあるフォルダを指定することはできない。

 ではこれらの配置方法のうち、どの方法を採用するべきでしょうか?

 私の考えでは、可能な限りプライベート配置を採用するのがよいと思います*。プライベート配置の場合、アセンブリをGACに登録する必要はないため厳密名付きアセンブリでなくとも使用することができます。

* ASP.NET 1.0/1.1において厳密名付きアセンブリを使用する場合には、必ず共有配置を採用します。ASP.NET 1.0/1.1のWebアプリケーションでは、厳密名付きアセンブリがドメイン中立のアセンブリとして読み込まれるため、GAC以外に配置することがサポート対象外となっています。

 ただし、プライベート配置の場合でもアセンブリには厳密名による署名を行うべきです。恐らく、プローブに頼ったアセンブリの配置パターンを採用し、アプリケーションと同じフォルダにコンポーネントのアセンブリを配置しているという開発者は多いかと思います。

 厳密名付きアセンブリでない場合、誤って異なるバージョンのアセンブリを上書きされたとしても、アプリケーション実行時に何のチェックも行われないためそのアセンブリが使われてしまいます。しかし厳密名付きアセンブリであれば、実行時にSystem.IO.FileLoadException例外が発生するため、不適切な構成によるアプリケーションの誤動作を防ぐことができます。

 結論としては、厳密名付きのアセンブリを使用したうえでコードベースによる指定を行うのが最も理想的ではありますが、プローブに頼った配置を行う場合でも必ず厳密名付きアセンブリを使用するのがよいでしょう。

VS.NET 2003で[ローカル コピー]をTrueに設定したらエラーに

 Visual Studio .NET 2003でInputMan for .NETを使用してWindowsアプリケーションを作成しています。配布先ではInputManのDLLファイルをEXEファイルと同じフォルダに配置して(プライベート配置のアセンブリとして)使用したいと思い、Visual Studioの参照設定から[ローカル コピー]プロパティをTrueに設定したのですが、ビルド時にエラーとなってしまいます。これは、プライベート配置のアセンブリとしては使用できないということなのでしょうか?

 [ローカル コピー]プロパティは、開発環境、つまりVisual Studioを使用したデバッグ実行時にのみ影響を与えるプロパティで、実行環境における配置にはまったく影響を与えません。つまり、このプロパティの設定にかかわらず、実行環境においては参照するアセンブリをプライベート配置とすることも共有配置とすることも可能です。

 Visual Studioからの実行では、プロジェクトのbinフォルダ(Visual Studio 2005の場合にはbinフォルダ配下のDebugフォルダとReleaseフォルダ)にアプリケーション本体のアセンブリが作成され、それが実行されます。

 アプリケーションがほかのアセンブリを参照している場合、実行にはそのアセンブリが当然必要になります。開発環境において、GACに登録されているアセンブリであれば、GACからアセンブリを参照することができますが、GACにそのアセンブリがない場合、何らかの方法でアセンブリを参照できる状態にする必要があります。

 [ローカル コピー]プロパティはこの問題の解決のために存在しているプロパティで、GACに登録されていないアセンブリを参照している場合、このプロパティは自動的にTrueと設定され、デバッグ実行時に参照しているアセンブリがbinフォルダへ自動的にコピーされるようになっています。

【参考】MSDN:方法 : 参照の [ローカル コピー] プロパティを設定する

 ところで、InputManで[ローカル コピー]プロパティをTrueにするとビルド時にエラーとなってしまう件ですが、これはGACに登録されているアセンブリ全般に共通した問題です。Visual Studio .NET 2002および2003では、GACに登録されているアセンブリの[ローカル コピー]プロパティをTrueにするという設定はサポートされていないようです。少々現象は異なりますが、例えば自動的に参照設定される「System.Windows.Forms.dll」の[ローカル コピー]プロパティをTrueに設定しても、フォーム・デザイナを開く際にエラーが発生します。

 繰り返しとなりますが、[ローカル コピー]プロパティは開発環境にのみ影響を与えるプロパティです。そのため、GACに登録されているアセンブリの[ローカル コピー]プロパティをTrueに設定する必要は基本的にありません。どうしても[ローカル コピー]プロパティをTrueに設定しなければならない場合には、GACへのアセンブリ登録を解除する必要があります。

 なお、Visual Studio 2005ではこの問題が改善されているため、エラーは発生しません。

 ちなみに、Visual Studio 2005の発行ウィザードを使用し、ClickOnceアプリケーションとして実行環境に配置する場合には注意が必要です。

 この発行ウィザードは、参照設定されているアセンブリのうち、[ローカル コピー]プロパティがTrueに設定されているアセンブリを配布すべきファイルと判断します。つまり配布すべきアセンブリがGACにある場合には、デフォルトでは配布されません。

.NET TIPS:GACコンポーネントをClickOnceで配布するには?

 従って、GACにあるアセンブリをClickOnceで配置する場合には、プロジェクトのプロパティにある[発行]タブから[アプリケーション ファイル]をクリックし、手動にて[発行の状況]の設定内容を「追加」に変更する方法にて対応します。End of Article


八巻 雄哉(やまき ゆうや)
グレープシティ株式会社 テクニカルエバンジェリスト

2003年グレープシティ入社。PowerToolsシリーズのテクニカル・サポートを担当する傍ら、製品開発やマーケティングにも従事。現在は.NETとPowerToolsシリーズ普及のため、エバンジェリストとして活動中。仕事柄C#も使うことはあるが、よく使うのはやっぱりVB。http://d.hatena.ne.jp/Yamaki/にてBlogを公開中。


インデックス・ページヘ  「Windows業務アプリケーション開発 Q&A」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH