SxSに対応していない (VC7以前でビルドされた) アプリケーションからSxSに対応したDLLを読み込むには

追記:タイトルを少し変えました。
追記2:VC9とx64環境について。

ここ数ヶ月の疑問が氷解。とてもすがすがしい。

事の発端はここで、当時はVisual Studio 2005 (VC8) を使う事をあきらめてVisual Studio .NETでしのいだのでした。で、最近、Pythonの拡張モジュールをPythonでimportしようとしたときにも同様に「MSVCR80.dllが見つからなかったため、このアプリケーションを開始できませんでした」という次のようなエラーが発生して泣きそうになっていたわけです。
f:id:moriyoshi:20070525184143p:image

Z:\>python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import _tableio
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: DLL load failed: 指定されたモジュールが見つかりません。
>>>

いろいろ調べているうちにJunfeng Zhang's Windows Programming Notes - SXS Activation Context --- Activate and Deactivateに遭遇、ここで始めてアクティベーション・コンテキストというものが存在して、SxSによるDLL読み込みをコントロールしていることに気づいたというわけです。

Activation Context is the runtime data structure to maintain the data in Sxs manifests. It is the boundary for Sxs data isolation. When components (for example, nt library loader, COM, User32) look up their registration data, the search is performed in the following order:

  1. The most recent activated Activation Context
  2. The process default Activation Context
  3. The system default Activation Context

CreateProcess automatically creates a process default Activation Context if the application has a Sxs manifest, either as an external file as app.exe.manifest, or as internal Win32 resource of type RT_MANIFEST, ID 1.

Activation Context can also be created by calling API CreateActCtx.

Junfeng Zhang's Windows Programming Notes - SXS Activation Context --- Activate and Deactivate

これを読むとCreateProcess() の実行時にマニフェストが存在すると作られると書かれています。

ということは、

マニフェストが存在しない→SxSコンテキストが作られない→SxS対応DLLをLoadLibarry()できない

ということなのではないかと思い、だめもとで次のファイルを python.exe のあるディレクトリに python.exe.manifest というファイル名で置いてみたところ、ちゃんとモジュールを読み込めるじゃないですか。

x86 VC80 / VC90:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
  <!-- VC90環境が入っている場合は以下 <dependency> 以下を囲むコメントを削除 -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

x64 VC80 / VC90:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture='amd64' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
  <!-- VC90環境が入っている場合は以下 <dependency> 以下を囲むコメントを削除 -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='amd64' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

多分これってPythonに限らずRubyPHPの拡張モジュール、PerlのXSでも同じ問題が起こりますね。そして同じ方法で解決できそうだということです。

.NET Framework でも同じ問題が発生していたのは、.NET Framework 2.0 のランタイムが SxS 対応のアプリケーションではなかったということなんでしょうね (Windows 2000 でも動くし)。