C/C++ 分離アプリケーションおよび side-by-side アセンブリのトラブルシューティング

更新 : 2007 年 11 月

依存する Visual C++ ライブラリが見つからない場合は、C/C++ アプリケーションの読み込みに失敗する場合があります。発生する可能性のあるランタイム エラーの一覧については、「Visual C++ ファイルの再配布」を参照してください。このセクションでは、C/C++ アプリケーションの読み込みに失敗する最も一般的な理由について、問題解決の手順を示しながら説明します。

Visual C++ がインストールされていないコンピュータにアプリケーションを配置し、「Visual C++ ファイルの再配布」に列挙されているようなエラー メッセージでアプリケーションがクラッシュした場合、いくつかのポイントを確認してエラーの原因を突き止める必要があります。

  1. Visual C++ アプリケーションの依存関係の理解」の手順に従ってください。Dependency Walker では、特定のアプリケーションまたは DLL のほとんどの依存関係を表示できます。表示されていない DLL がある場合は、アプリケーションを実行するコンピュータにその DLL をインストールしてください。

  2. オペレーティング システム ローダーは、マニフェストを使用してアプリケーションが依存するアセンブリを読み込みます。マニフェストは、リソースとしてバイナリに埋め込むことも、外部ファイルとしてアプリケーションのローカル フォルダに保存することもできます。マニフェストがバイナリ内に埋め込まれているかどうかを確認するには、Visual Studio でバイナリを開き、このバイナリのリソースを調べます。埋め込まれている場合は RT_MANIFEST というリソースが見つかります。バイナリに埋め込まれたマニフェストが見つからない場合は、<binary_name>.<extension>.manifest のような名前の外部ファイルを探します。

  3. マニフェストが存在しない場合は、リンカにプロジェクトのマニフェストを生成させる必要があります。このプロジェクトの [プロジェクトのプロパティ] ダイアログの [マニフェストの生成] リンカ オプションをオンにしてください。

    ms235342.alert_note(ja-jp,VS.90).gifメモ :

    マニフェストを生成しない Visual C++ プロジェクトのビルドはサポートされていません。Visual C++ 2005 でビルドされる C/C++ プログラムはすべて Visual C++ ライブラリへの依存関係を記述したマニフェストを含んでいる必要があります。

  4. マニフェストがライブラリ内に埋め込まれている場合は、RT_MANIFEST の ID がこのタイプのバイナリに適した ID であることを確認します。アプリケーションの場合は ID を 1 に、また、ほとんどの DLL の場合は ID を 2 にする必要があります。マニフェストが外部ファイルの場合は、XML エディタまたはテキスト エディタで開きます。マニフェストおよび配置のルールの詳細については、「Manifests」を参照してください。

    ms235342.alert_note(ja-jp,VS.90).gifメモ :

    Windows XP では、外部マニフェストがアプリケーションのローカル フォルダに存在する場合、オペレーティング システム ローダーは、バイナリに埋め込まれたマニフェストではなく、この外部マニフェストを使用します。Windows Server 2003 およびそれ以降のバージョンの Windows では、この優先順位が逆になります。つまり、埋め込みマニフェストが存在する場合はそれが使用され、外部マニフェストは無視されます。

  5. すべての DLL がバイナリに埋め込まれたマニフェストを持つようにすることをお勧めします。DLL が LoadLibrary 呼び出しで読み込まれる場合、外部マニフェストは無視されます。詳細については、「アセンブリ マニフェスト」を参照してください。

  6. マニフェストに列挙されているすべてのアセンブリがコンピュータに正しくインストールされていることを確認します。各アセンブリは、名前、バージョン番号、およびプロセッサ アーキテクチャでマニフェストに指定されます。アプリケーションが side-by-side アセンブリに依存している場合は、これらのアセンブリがコンピュータに適切にインストールされ、オペレーティング システム ローダーで検出できることを、「Assembly Searching Sequence」で指定されている手順を使用して確認します。64 ビット アセンブリは、32 ビット プロセスで読み込んだり、32 ビット オペレーティング システムで実行したりできないことに注意してください。

Visual C++ 2005 でビルドされた appl.exe というアプリケーションがあるとします。このアプリケーションにはマニフェストがあり、バイナリ リソース RT_MANIFEST として ID = 1 で appl.exe 内に埋め込まれているか、外部ファイル appl.exe.manifest として格納されています。マニフェストの内容は、次のようになります。

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.xxxxx.y" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

このマニフェストは、オペレーティング システム ローダーに対して、appl.exe が、32 ビットの x86 プロセッサ アーキテクチャ用にビルドされた Microsoft.VC90.CRT という名前のバージョン 9.0.xxxxx.y のアセンブリに依存していることを通知します。

依存 side-by-side アセンブリは、共有アセンブリまたはプライベート アセンブリとしてインストールできます。たとえば、Visual Studio 2005 は、CRT アセンブリを共有 side-by-side アセンブリとしてインストールします。このアセンブリは、Windows XP を実行している場合には %WINDIR%\WinSxS\x86_Microsoft.VC90.CRT_<version> ディレクトリに、Windows Vista を実行している場合には %WINDIR%\winsxs\x86_microsoft.vc90.crt_<version> ディレクトリにあります。

共有 Visual C++ CRT アセンブリのassembly manifestは、Windows XP を実行している場合には %WINDIR%\WinSxS\Manifests\x86_microsoft.vc90.crt_<version>.manifest に、Windows Vista を実行している場合には %WINDIR%\winsxs\Manifests\x86_microsoft.vc90.crt_<version>.manifest にもインストールされます。また、このアセンブリを識別して、その内容 (このアセンブリに含まれる DLL) を一覧表示します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <noInheritable/>
   <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
   <file name="msvcr90.dll" hash="3ca5156e8212449db6c622c3d10f37d9adb12c66" hashalg="SHA1"/>
   <file name="msvcp90.dll" hash="92cf8a9bb066aea821d324ca4695c69e55b27cff" hashalg="SHA1"/>
   <file name="msvcm90.dll" hash="7daa93e1195940502491c987ff372190bf199395" hashalg="SHA1"/>
</assembly>

side-by-side アセンブリは、ポリシー ファイルとも呼ばれる発行者構成ファイルを使用して、あるバージョンの side-by-side アセンブリを使用するアプリケーションおよびアセンブリが別のバージョンの side-by-side アセンブリを使用するようにグローバルにリダイレクトすることもできます。共有 Visual C++ CRT アセンブリのポリシーは、Windows XP を実行している場合には %WINDIR%\WinSxS\Policies\x86_policy.9.0.Microsoft.VC90.CRT_<version>.policy で、Windows Vista を実行している場合には %WINDIR%\winsxs\Manifests\x86_policy.9.0.microsoft.vc90.crt_<version>.manifest で確認できます。ポリシーの内容の例を次に示します。

</assembly>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<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.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
   <dependency>
      <dependentAssembly>
         <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
         <bindingRedirect oldVersion="9.0.aaaaa.bbb-9.0.ccccc.d" newVersion="9.0.xxxxx.yy"/>
      </dependentAssembly>
   </dependency>
</assembly>

このポリシーは、アプリケーションまたはアセンブリが、このアセンブリのバージョン 9.0.aaaaa.bbb を要求する場合は、代わりにシステムに現在インストールされている同じアセンブリのバージョン 9.0.xxxxx.yy を使用するように指定しています。アプリケーションのマニフェストで示されたアセンブリのバージョンがポリシー ファイルに指定されている場合、ローダーは、マニフェストで指定されたバージョンのアセンブリを、WinSxS フォルダで探します。このバージョンがインストールされていない場合、読み込みは失敗します。同様に、バージョン 9.0.xxxxx.yy のアセンブリがインストールされていない場合、バージョン 9.0.aaaaa.bbb のアセンブリを要求するアプリケーションでも読み込みが失敗します。

ただし、CRT アセンブリは、プライベート side-by-side アセンブリとしてアプリケーションのローカル フォルダにインストールされている可能性もあります。オペレーティング システムは、共有アセンブリとしての CRT アセンブリまたはその他のアセンブリの検出に失敗した場合、そのアセンブリをプライベート アセンブリとして検索し始めます。プライベート アセンブリは次の順序で検索されます。

  1. アプリケーションのローカル フォルダで <assemblyName>.manifest という名前のマニフェスト ファイルを検索します。この例では、ローダーは、Microsoft.VC90.CRT.manifest を appl.exe と同じフォルダで検索します。マニフェストが見つからない場合、ローダーはアプリケーション フォルダから CRT DLL を読み込みます。CRT DLL が見つからない場合、読み込みは失敗します。

  2. appl.exe のローカル フォルダにある <assemblyName> フォルダを開こうとします。フォルダが存在する場合は、このフォルダから <assemblyName>.manifest というマニフェスト ファイルを読み込みます。マニフェストが見つからない場合、ローダーは <assemblyName> フォルダから CRT DLL を読み込みます。CRT DLL が見つからない場合、読み込みは失敗します。

ローダーによる依存アセンブリの検索方法の詳細については、「Assembly Searching Sequence」を参照してください。ローダーがプライベート アセンブリとしての依存アセンブリの検出に失敗した場合、読み込みは失敗し、"指定されたプログラムを実行できません。" というメッセージが表示されます。このエラーを解決するには、依存アセンブリとそれを構成する DLL をプライベート アセンブリまたは共有アセンブリとしてコンピュータにインストールする必要があります。

参照

概念

分離アプリケーションおよび side-by-side アセンブリの概念

その他の技術情報

C/C++ 分離アプリケーションおよび side-by-side アセンブリのビルド