あけましておめでとうございます。おそらく今年はバージョン5の公開によってActiveBasicの大きな節目となる年になることでしょう。そう言いつつ新年最初の話はVisual C++の話です(ぇ。

Visual C++ 2005から、その動的リンク版 (DLL)のランタイムは、Windows XPから搭載されたSide-by-Sideを活用するものとなり、単純にランタイムDLLをEXEと同梱すれば良いというわけにはいかなくなりました。そう思われている節が強いように私は感じていますが、実はそうでもありません。

Side-by-Sideは、複数のバージョンのアセンブリ(DLLなどの集合)を共存・選択する仕組みです。1つのアセンブリは複数のファイルからなっていても構いません。例えば、VC++ 2005のランタイムのアセンブリは「Microsoft.VC80.CRT」という名前ですが、これはmsvcr80.dll, msvcp80.dll, msvcm80.dllの3つからなっています。

Side-by-Sideでは、アセンブリを共有アセンブリプライベートアセンブリの2種類に分類しています。共有アセンブリは%WINDIR%\WinSxS以下に置かれシステム全体で共有されるもの、プライベートアセンブリはアプリケーションの存在するフォルダの下に置かれ、そのアプリケーションだけが使うものとなっています。

共有アセンブリはシステムにインストールするものという雰囲気ですが、プライベートアセンブリはインストーラを必要とせず単にファイルをコピーするだけで実行できるようにできています。つまり、これを使えば、VC++ 2005でもランタイムDLLをEXEに同梱できるのです。

まず、次のような内容のファイルを作成し、EXEと同じフォルダに「Microsoft.VC80.CRT.manifest」(assemblyまたはassemblyIdentityのname属性に拡張子manifestを付けたもの)という名前で保存します。ちなみに、このMicrosoft.VC80.CRTのバージョン8.0.50727.6195は2012年3月3日時点で最新のMS11-025のものです。Visual Studio 2005のSP1ならびにMS11-025の修正を適用していない場合は適宜ご自身が使用なさっている正しいバージョンを記してください。また、x64/IA-64の場合は適宜processorArchitecture属性を書き換えてください(ただし試していません)。

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
  xmlns="urn:schemas-microsoft-com:asm.v1"
  manifestVersion="1.0">
  <assemblyIdentity
    type="win32"
    name="Microsoft.VC80.CRT"
    version="8.0.50727.6195"
    processorArchitecture="x86"/>
  <file name="msvcr80.dll"/>
  <file name="msvcp80.dll"/>
</assembly>

assembly/fileのname属性で、このアセンブリに含まれるファイルを指定します。共有アセンブリのMicrosoft.VC80.CRTは3つのファイルからなっていましたが、こちらは実際EXEが参照している(実行に必要な)ものだけを記述すれば十分です(つまりこの例の場合EXEはmsvcr80.dllとmsvcp80.dllのみを必要とするということです)。

それが済んだら、今作ったマニフェストに記載したファイル(ここではmsvcr80.dllとmsvcp80.dll)を、そのマニフェストがあるフォルダへコピーします。DLLのバージョンとマニフェストのバージョンが合っていることをよく確認してください。これで準備は完了です。

勿論、EXEにもマニフェストが必要です(/MDを付けてコンパイルすれば特に不要と指定しない限り自動的に作られるはずです)。内容は特に書き換える必要はありません。当然EXE側のアセンブリは、リソースとしてEXEに埋め込んで構わないはずです。さあ実行してみてください。心配ならランタイムをインストールしていない(そしてWindows XP以上が稼動してる)他のPCへ持っていって実行してみてください。

結局、マニフェストさえ用意すれば、従来どおりランタイムDLLを同梱して配布できるということです。ここまでで言い忘れましたが、Microsoft.VC80.CRT.manifestをアセンブリマニフェスト、EXE側のほうをアプリケーションマニフェストと呼びます。アセンブリを提供する側と利用する側という立場の違いです。

ところで、プライベートアセンブリは、EXEのあるフォルダのサブフォルダに置くこともできます。EXEのあるフォルダに、アセンブリ名(先の例ではMicrosoft.VC80.CRT)と同名のフォルダを作り、そこへアセンブリマニフェストと本体のファイル(msvcr80.dllら)を移動します。ただし、こうするとWindows XPより以前のバージョンではside-by-sideがなく従来の手順でDLLを探すため、おそらくDLLが見つからないというエラーになるでしょう。そのため個人的にはEXEと同じフォルダにアセンブリマニフェストと本体を置くほうが便利だと思います。

本日の記事は、殆どGoogleで見付けたGotDotNet掲示板の内容の焼き直しです。

私は、その記述を基に自作のDLLをプライベートアセンブリ化できないかと試行錯誤していました。結果としてはできましたが、その話は次回にします。


2012年3月3日追記:例示の中で登場するCRTのバージョンを最新のものへ更新しました。


スポンサード リンク

この記事のカテゴリ

  • ⇒ VC++ 2005のランタイムDLLをEXEに同梱する
  • ⇒ VC++ 2005のランタイムDLLをEXEに同梱する