8. Side-by-Side 実行

更新日: 2009 年 10 月 23 日


.NET Framework では、バージョン管理の仕組みによって、アプリケーションの実行時に適切なバージョンのアセンブリが読み込まれ、開発者の想定通りにアプリケーションを動作させることが可能になっています。それでは例えば、実行中の 2 つのアプリケーションが、あるアセンブリの異なるバージョンをそれぞれ要求している場合にはどうなるのでしょうか。このような場合に、それぞれのアプリケーションが要求しているアセンブリを適切に読み込み、実行可能にする仕組みが Side-by-Side 実行です。

.NET 以前の技術では、コンポーネントはバージョンが上がるたびに上書きされていました。そのため、コンポーネントの開発者には互換性の維持が求められていました。しかし、コンポーネントを使用しているアプリケーションをすべてテストすることが現実的に困難であるため、コンポーネントのバージョンが上がると、いくつかのアプリケーションが正しく動作しないという問題が多く発生していました。

.NET では、複数バージョンのコンポーネントを管理する仕組みがあらかじめ用意されているため、常に開発時に使用したバージョンのコンポーネントを使用してアプリケーションを実行できるようになっています。これにより、開発者は互換性を強く意識しなくても、新しいバージョンのコンポーネントを開発可能になりました。

ランタイム バージョン

「Side-by-Size」は「並行して」という意味ですが、最も基本的な .NET Framework ランタイム (.NET アプリケーションの実行に必要な一連のコンポーネントを含む実行環境) でも、同じように Side-by-Side が実現されています。つまり、コンピューター上に複数バージョンの .NET Framework がインストールでき、その場合でもアプリケーションに必要なバージョンのランタイムが使用されるように設計されています。

従って、例えば .NET Framework 1.1 と .NET Framework 2.0 がコンピューターに同時にインストールされていれば、.NET Framework 1.1 で開発されたアプリケーションと .NET Framework 2.0 で開発されたアプリケーションは、それぞれのランタイムが読み込まれて実行されます。

従って、例えば .NET Framework 1.1 と .NET Framework 2.0 がコンピュータに同時にインストールされていれば、.NET Framework 1.1 で開発されたアプリケーションと .NET Framework 2.0 で開発されたアプリケーションは、それぞれのランタイムが読み込まれて実行されます。

アプリケーションの実行までの流れ」でも解説したように、アプリケーションが起動されると、mscoree.dll が読み込まれます。mscoree.dll は、アセンブリのメタデータから必要な CLR のバージョンを読み出して、%Systemroot%\Microsoft.NET\Framework 以下のバージョン フォルダーから、適切なバージョンの mscorwks.dll を読み込みます。

mscoree.dll は、アセンブリのメタデータから必要な CLR のバージョンを読み出して、%Systemroot%\Microsoft.NET\Framework 以下のバージョン フォルダから、適切なバージョンの mscorwks.dll を読み込みます。

このようにアセンブリのメタデータによって適切な.NET Framework ランタイムが選択されるため、複数のバージョンがインストールされている場合でも、正しく適切なアセンブリが選択されて実行されるようになっています。

アプリケーションが異なるバージョンの .NET Framework 上でも実行できることが分かっている場合には、構成ファイル (拡張子が .exe.config のファイル) により、そのアプリケーションが実行可能な.NET Framework ランタイムのバージョンを指定することで、適切なバージョンのランタイムがコンピューター上に存在していない場合でも、アプリケーションを実行できます。

Framework ランタイムのバージョンを指定することで、適切なバージョンのランタイムがコンピュータ上に存在していない場合でも、アプリケーションを実行できます。

異なるバージョンのランタイムで実行するためには、構成ファイルを次のように記述します。この記述では、アプリケーションは .NET Framework 1.0 と 1.1 の両方で実行可能ということを示しています。

<configuration>
  <startup>
    <supportedRuntime version="v1.1.4322"/>
    <supportedRuntime version="v1.0.3705"/>
  </startup>
</configuration>

それでは、もし適切なバージョンのランタイムがインストールされておらず、構成ファイルも存在しない場合はどうなるのでしょうか。そのような場合、新しいバージョンの .NET Framework は古いバージョンのアセンブリを実行できるという想定でアプリケーションを起動します。そのため、.NET Framework 1.1 で開発されたアプリケーションを起動したときに、実行環境に .NET Framework 1.1 ランタイムが存在せずに、.NET Framework 2.0 のみがインストールされている場合、アプリケーションは .NET Framework 2.0 上で起動されます。

NET Framework 2.0 のみがインストールされている場合、アプリケーションは .NET Framework 2.0 上で起動されます

逆に .NET Framework 2.0 で開発されていて、実行環境に .NET Framework 1.1 のみがインストールされている場合には、アプリケーションの起動は失敗します。

逆に .NET Framework 2.0 で開発されていて、実行環境に .NET Framework 1.1 のみがインストールされている場合には、アプリケーションの起動は失敗します。

そして、以下のエラー メッセージが表示されます。

そして、以下のエラー メッセージが表示されます。

このように新しいバージョンのランタイムを使用することで、古いバージョンで開発されたアプリケーションでも実行することができますが、バージョン アップに伴って仕様が変更されたり、機能が変更されたりしている機能もあるため、可能な限り同じバージョンのランタイムで実行できるようにクライアント環境を整備しておいた方がよいでしょう。

ページのトップへ


アセンブリのバージョン管理

Side-by-Side は、.NET Framework ランタイム のみではなく、アプリケーションやコンポーネントなどのアセンブリでもサポートされています。.NET 以前の技術では、参照しているコンポーネントのバージョン管理の仕組みが存在しなかったため、複数のアプリケーションから参照される共通のコンポーネントが変更されてしまった場合、それらのアプリケーションは正しく動作する保証がなくなってしまうという問題がありました。.NET Framework では、複数のバージョンのアセンブリが存在していても適切なバージョンのアセンブリが選択されるように設計されています。

アプリケーションが参照しているアセンブリのバージョンは「アセンブリの仕組み」で解説したようにマニフェストに記述されています。アプリケーションがクラスの呼び出しでアセンブリが必要になったとき、CLR は、マニフェスト情報に記述されているアセンブリを読み込みます。アプリケーションが適切なアセンブリを読み込むようにするためには、アセンブリに適切なバージョンを指定します。

複数のアプリケーションから共通的に使われるアセンブリは、GAC に登録しておくと自動的にバージョン管理が実施されて、アプリケーションは適切なバージョンのアセンブリを読み込むことができます。通常のライブラリであれば、アプリケーションと同じフォルダーにアセンブリを配置しておくだけで、適切なアセンブリが読み込まれるため、配置も容易です。

ページのトップへ


構成ファイルによるバージョン指定

アプリケーションが参照しているアセンブリに問題があった場合、実行時に参照するアセンブリのバージョンを変更することができます。参照するアセンブリの情報は、「アプリケーションの実行までの流れ」で解説したように構成ファイルで指定します。構成ファイルには、次の 3 種類のファイルが指定可能です。上から順に優先順位が高くなっています。

  • アプリケーション構成ファイル
  • 発行者ポリシー ファイル
  • マシン構成ファイル

これらのどれを指定しても、アセンブリのバージョンを指定できるようになっています。意図的にアセンブリのバージョンを切り替えて読み込ませる操作を、アセンブリのリダイレクトと呼びます。上記の 2 つの構成ファイルは、コンピューターに配置された .config ファイルのことで、アプリケーションの実行設定が記述された XML ファイルです。一方、発行者ポリシー ファイルというのは、アプリケーションの開発元が記述するファイルで、アプリケーションの実行ポリシーが記述された DLL ファイルになります。

アプリケーション構成ファイルとマシン構成ファイルの違いは、前者がアプリケーションに対してアセンブリのリダイレクトを指示するのに対して、後者はコンピューターにインストールされているアプリケーションすべてに対して、アセンブリのリダイレクトを指示するということです。

アプリケーションの問題を回避するためにアセンブリを異なるバージョンにリダイレクトする場合は、アプリケーション構成ファイルを変更します。アプリケーション構成ファイルは、アプリケーションと同じフォルダー上で、実行可能ファイル名に .config という拡張子を付けたファイルを指します。実行可能ファイルが app1.exe という名前だった場合、app1.exe.config というファイル名になります。

コンピューターにインストールされているアセンブリに明らかに問題があって、複数のアプリケーションで問題が起こる場合は、マシン構成ファイルを変更します。ただし、マシン構成ファイルはコンピューター全体に影響を与えるため、可能な限り変更しない方が安全です。マシン構成ファイルは通常、%Systemroot%\Microsoft.NET\Framework\v<バージョン番号>\CONFIG\machine.config に配置されています。

発行者ポリシー ファイルも構成ファイルも、アセンブリのリダイレクトは、以下のような書式で記述した XML ファイルを作成します。

 

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="lib"
                          publicKeyToken="25520ce5d712a2c6"
                          culture="neutral"  />
        <bindingRedirect oldVersion="1.0.0.0"
                         newVersion="1.1.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

構成ファイルの場合は、このファイルを .config ファイルとして配置するだけで機能します。発行者ポリシーは、ここからさらにアセンブリ リンカ (al.exe) と呼ばれるツールを使用してポリシー ファイルを作成します。ポリシー ファイルを作成するためには、次のようなコマンドを実行します。

al /link:policy.config /out:policy.1.0.lib.dll /keyfile:key.snk

ポリシー ファイルは、

policy.<メジャー番号>.<マイナ番号>.アセンブリ名.dll

というファイル名で指定します。ポリシー ファイルには厳密名が必要なため、/keyfile オプションを指定して、公開キーと秘密キーのキーペアを設定しています。このようなコマンドを実行して生成された policy.1.0.lib.dll を GAC に登録すると、バージョン 1.0.0.0 のlib.dll を参照したときに、バージョン 1.1.0.0 の lib.dll が参照されるようになります。

以上のように、構成ファイルやポリシー ファイルでリダイレクトするバージョンを指定することによって、開発時に参照していたアセンブリ以外のアセンブリを参照してアプリケーションを実行できるようになります。

ページのトップへ