VC90ランタイム問題まとめ

何度もこの問題について書き続けながら、まとめてなかった。

Visual C++ 9.0のランタイム問題
Visual Studio 2008 SP1
Visual C++ 9.0 SP1のランタイム問題
再考:Visual C++ 9.0 SP1のランタイム問題
_BIND_TO_CURRENT_VCLIBS_VERSIONについてまじめに調べてみる

結論から言うと、ランタイムのインストールは、vcredist_x86.exeの最新版を利用するか、あるいは、MSMを使ってインストールするのいずれかを選択するのが賢明であると言うこと。

vcredist_x86.exeを利用する

Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)
Microsoft Visual C++ 2008 SP1 Redistributable Package (x64)

vcredist_x86.exeは、最新版だったら、ファイルをぶちまけることはないし、ユーザーにランタイムをインストールしてもらう方法としては、悪くはないと思われる。

MSM(マージモジュール)を利用する

Microsoft_VC90_CRT_x86.msm
policy_9_0_Microsoft_VC90_CRT_x86.msm

の「両方」をインストールしないといけない。ポリシー(policy)って何?っていう疑問が出てくるんだけど、実はこのファイルがかなり重要。このファイルは何をしているのか知るために、インストールされたファイルを開いてみると、

x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_8550c6b5d18a9128.manifest

の場合、

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) Microsoft Corporation.  All rights reserved. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32-policy" name="policy.9.0.Microsoft.VC90.CRT" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
      <bindingRedirect  oldVersion="9.0.20718.0-9.0.21022.8" newVersion="9.0.30729.1"/>
      <bindingRedirect  oldVersion="9.0.30201.0-9.0.30729.1" newVersion="9.0.30729.1"/>
    </dependentAssembly>
  </dependency>
</assembly>

と書かれている。

細かい部分は置いておいて、結局、bindingRedirectという部分で、古いバージョンを新しいバージョンにリダイレクトしていることが分かる。
つまり、逆に言えば、このファイルがなければ、別バージョンのファイルは別バージョンとして扱われると言うこと。なるほど、こういう仕組みで動いていたんだねという感じ。

従来のDLL簡単入れ替えには微妙な躊躇があるけど、自分で完全互換であることが保証できるなら、こうやって明示的に代替することができるということみたい。

プライベートDLLとしてインストール

で、プライベートアセンブリとして配置する、つまり、アプリケーションのフォルダにMicrosoft.VC90.CRTなどのディレクトリをそのまま配置する場合に、どうやって、リダイレクトのポリシーを適用するのかについてはググってみたり、いろいろ実験してみたりしたけど、結局、分からず。

結論から言うと、当たり前すぎる方法で対処するしかないらしい。たとえば、下記は、VS2009SP1のMicrosoft.VC90.DebugCRT.manifestを9.0.21022.8を必要としているアプリケーション(つまり、_BIND_TO_CURRENT_VCLIBS_VERSIONをdefineしていないVC++9.0SP1でビルドしたアプリ)用に無理に修正したもの。
元々、9.0.30729.1と書かれていたのを、9.0.21022.8と書き換えただけ。
これで動く。本当は良くない感じもするが、MSが公式にリダイレクトしているのだから、特に問題でもないんでしょう。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable></noInheritable>
    <assemblyIdentity type="win32" name="Microsoft.VC90.DebugCRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    <file name="msvcr90d.dll" hashalg="SHA1" hash="77c2dcb12982a6855302844f8803e68ce360fcc9"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>WA59/AbhIDaZgmB1cN9MFlDi2g4=</dsig:DigestValue></asmv2:hash></file> <file name="msvcp90d.dll" hashalg="SHA1" hash="b2fa2a05ee7e6a2595c16547246753a62e9bf398"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>Rxofhw9S95owIW2MDmCg2zStQgs=</dsig:DigestValue></asmv2:hash></file> <file name="msvcm90d.dll" hashalg="SHA1" hash="6cfc0c6330724d86db3e2ef295d4e1d75a43514a"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>iOxEMZK3fufMDQFuKGZ4VdAYzWY=</dsig:DigestValue></asmv2:hash></file>
</assembly>

ただねぇ、デバッグ目的ならばいいけど、配布するアプリケーションでこの手の芸当を利用するのはお勧めできないと思います。