37

VisualStudio6からVisualStudio2008に切り替えてから、バージョンを気にしないように、マニフェストファイルとともにMFC90.dllとmsvc[pr]90.dllをプライベートサイドバイサイド構成で使用しています。またはそれらをシステムにインストールします。

SP1より前では、これは正常に機能していました(そして、開発者のマシンでも正常に機能します)。SP1後のテストを行ったので、昨日の朝から髪を抜いてきました。

まず、NSISインストーラースクリプトが、redistフォルダーからdllとマニフェストファイルをプルします。アプリはまだRTMバージョンにリンクしているため、これらは正しくありませんでした。

そこで、すべてのプロジェクトにdefine forを追加して_BIND_TO_CURRENT_VCLIBS_VERSION=1、それらがredistフォルダー内のSP1 DLL(または新しいサービスパックがリリースされたときの後続のDLL)を使用するようにしました。これを見つけるのに何時間もかかりました。

コンパイルから中間ファイルフォルダーに生成されたマニフェストファイルを再確認したところ、9.0.30729.1SP1のバージョンが正しくリストされています。私はダブルチェックとトリプルチェックをクリーンなマシンに依存しています:それはすべてエラーなしでローカルdllにリンクしています。

アプリを実行しても、次のエラーが発生します。

アプリケーションを正しく初期化できませんでした(0xc0150002)。[OK]をクリックして、アプリケーションを終了します。

私がグーグルやマイクロソフトで行った検索のどれも私の特定の問題に関連するものを思い付きませんでした(しかし、このエラーメッセージで2005年に戻ったヒットがあります)。

SP1で同様の問題が発生した人はいますか?

オプション:

  • 問題を見つけて修正し、正常に機能するようにします(推奨)
  • redistをインストールします
  • 古いRTMdllとマニフェストファイルを掘り起こし、#defineを削除して現在のものを使用します。(Microsoftがあなたのredistフォルダーからそれらを爆破するので、私は以前のインストーラービルドでそれらを持っています!)

編集:定義をオフにして(RTM dllへのリンク)再構築を試みましたが、RTMdllがフォルダーにインストールされている限り機能します。SP1 dllがドロップインされると、次のエラーが発生します。

c:\ Program Files \ ... \ ... \ X.exe

アプリケーションの構成が正しくないため、このアプリケーションを起動できませんでした。アプリケーションを再インストールすると、この問題が解決する場合があります。

他の誰もこの問題に対処する必要はありませんでしたか?

編集:ニヤリと笑うために、テストマシンにVS2008SP1用のvcredist_x86.exeをダウンロードして実行しました。それは動作します。SP1DLLを使用します。そして私のRTMリンクアプリ。ただし、SP1より前に機能していたプライベートサイドバイサイドディストリビューションではありません。

4

5 に答える 5

40

私は先週この問題と戦いましたが、今ではある程度の専門家だと思っています ;)

すべての dll とスタティック ライブラリが SP1 バージョンで再コンパイルされたわけではないことは 99% 確信しています。あなたが置く必要があります

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

使用しているすべてのプロジェクトに。実際のサイズのすべてのプロジェクトでは、再コンパイルされていない小さなライブラリを簡単に忘れてしまいます。

どのバージョンにバインドするかを定義するフラグは他にもあります。http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspxに記載されています。上記の行の代わりに、次のように置くこともできます

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

これは、すべての VC ライブラリ (CRT、MFC、ATL、OpenMP) の最新バージョンにバインドされます。

次に、埋め込まれたマニフェストの内容を確認します。XM リソース エディターをダウンロード: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm。ソリューション内のすべての dll と exe を開きます。「XP テーマ マニフェスト」の下を見てください。右側の「バージョン」属性が「9.0.30729.1」であることを確認します。「9.0.21022」の場合、一部の静的ライブラリが古いバージョンのマニフェストを取得しています。

私が見つけたのは、多くの場合、両方のバージョンがマニフェストに含まれていたことです。これは、一部のライブラリが sp1 バージョンを使用し、他のライブラリが使用しないことを意味します。

プリプロセッサ ディレクティブが設定されていないライブラリをデバッグする優れた方法: プラットフォーム ヘッダーを一時的に変更して、古いマニフェストを埋め込もうとするとコンパイルが停止するようにします。C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h を開きます。「21022」文字列を検索します。その定義では、無効なものを入れます (「定義」を「blehbleh」などに変更します)。このようにして、プリプロセッサ フラグが設定されていないプロジェクトをコンパイルする_BIND_TO_CURRENT_CRT_VERSIONと、コンパイルが停止し、それらを追加する必要があるか、すべてに適用されることを確認する必要があることがわかります。

また、Dependency Walker を使用して、どの dll が取り込まれているかを確認してください。仮想マシンに更新なし (SP2 のみ) の新しい Windows XP コピーをインストールするのが最も簡単です。このようにして、SxS フォルダーには、指定したサイド バイ サイド dll の代わりに使用されているものがないことが確実にわかります。

于 2008-09-16T09:47:15.053 に答える
14

この問題を理解するには、次の4 つのバージョン番号が関係していることを理解することが重要だと思います。

  • (A) .exe がコンパイルされる VC ヘッダー ファイルのバージョン。
  • (B) その .exe のリソース セクションに埋め込まれているマニフェスト ファイルのバージョン。既定では、このマニフェスト ファイルは Visual Studio によって自動的に生成されます。
  • (C) .exe と同じディレクトリにコピーする VC .DLL (side-by-side アセンブリの一部) のバージョン。
  • (D) .exe と同じディレクトリにコピーする VC マニフェスト ファイル (side-by-side アセンブリの一部) のバージョン。

実行中の VC 2008 DLL には 2 つのバージョンがあります。

  • v1: 9.0.21022.8
  • v2: 9.0.30729.4148

わかりやすくするために、v1/v2 表記を使用します。次の表は、考えられるいくつかの状況を示しています。

Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1         | v2       | v1                    | v1          | v1         
2         | v2       | v1                    | v2          | v2          
3         | v2       | v1                    | v2          | v1
4         | v2       | v2                    | v2          | v2

Vista SP1 のクリーン インストールで .exe を実行すると、次のような状況が発生します。

  • 状況 1: 「プロシージャ エントリ ポイント XYZXYZ がダイナミック リンク ライブラリに見つかりませんでした」というポップアップが表示されます。

  • 状況 2: .exe を実行しても何も起こらないように見えますが、次のイベントが Windows の「イベント ビューアー / アプリケーション ログ」に記録されます。

    「C:\Path\file.exe」のアクティベーション コンテキストの生成に失敗しました。マニフェストまたはポリシー ファイル「C:\Path\Microsoft.VC90.CRT.MANIFEST」の 4 行目のエラーです。マニフェストで見つかったコンポーネント ID が ID と一致しません要求されたコンポーネントの。参照は Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8" です。定義はマイクロソフト

  • 状況 3: すべて正常に動作しているようです。これがremicles2 のソリューションです。

  • 状況 4: こうあるべきです。残念ながら、Roel 氏が指摘するように、実装はかなり難しい場合があります。

さて、私の状況 ( crashmstrと同じだと思います) は nr 1 です。問題は、Visual Studio が何らかの理由で v2 のクライアント コード (A) を生成するが、何らかの理由で v1 マニフェストを生成することです。ファイル (B)。バージョン (A) をどこで設定できるかわかりません。

この全体の説明はまだプライベート アセンブリのコンテキスト内にあることに注意してください。

更新:ついに何が起こっているのか理解し始めました。どうやら、Visual Studio はデフォルトで v2 のクライアント コード (A) を生成します。_BIND_TO_CURRENT_VCLIBS_VERSION フラグは、生成されたマニフェスト ファイル (B) のバージョンのみを選択しますが、このバージョンはアプリケーションの実行時に無視されます。

結論

Visual Studio 2008 でコンパイルされた .exe は、デフォルトで VC90 DLL の最新バージョンにリンクします。_BIND_TO_CURRENT_VCLIBS_VERSION フラグを使用して、マニフェスト ファイルで生成される VC90 ライブラリのバージョンを制御できます。これにより、「マニフェストが要求されたコンポーネントの ID と一致しません」というエラー メッセージが表示される状況 2 が実際に回避されます。また、_BIND_TO_CURRENT_VCLIBS_VERSION フラグがなくてもアプリケーションが VC DLL の最新バージョンにリンクされているため、状況 3 が正常に機能する理由も説明しています。

VC 9.0 DLL を Windows SxS ディレクトリに置き、vcredist が実行された public side-by-side アセンブリの場合、状況はさらに奇妙です。.exe のマニフェスト ファイルで古いバージョンの DLL を使用するように指定されていても (_BIND_TO_CURRENT_VCLIBS_VERSION フラグが設定されていない場合)、Windowsは既定でこのバージョン番号を無視します。代わりに、「アプリケーション構成ファイル」が使用されている場合を除き、システムに存在する場合、Windows は新しいバージョンを使用します。

ややこしいと思うのは私だけでしょうか?

要約すると

  • プライベート アセンブリの場合、.exe のプロジェクトとすべての依存する .lib プロジェクトで _BIND_TO_CURRENT_VCLIBS_VERSION フラグを使用します。
  • パブリック アセンブリの場合、Windows が SxS ディレクトリから正しいバージョンの .DLL を自動的に選択するため、これは必要ありません。
于 2010-01-28T08:06:02.030 に答える
4

exe および dll マニフェストを表示するためのもう 1 つの優れたツールはManifest Viewです。これは、9.0.21022依存しているため、XP のクリーン インストールでは適切に実行されません。

于 2009-10-14T17:17:14.450 に答える
4

どの静的ライブラリが動作不良であるかを見つけるために使用した別のトリックを思い出しました。文字列「21022」の静的ライブラリを「grep」します。ただし、これらの文字列が表示されないため、wingrep などの「通常の」grep ツールは使用しないでください (バイナリ ファイルと見なされ、生の非 Unicode 文字列を探します)。リソース キットの 'strings' ユーティリティを使用します (現在、Russinovich のサイトにあると思います)。それはバイナリをgrepします。したがって、この「文字列」をソース ツリー全体に渡すと、間違ったマニフェスト (または間違ったバージョンのマニフェスト) への参照を含むバイナリ ファイル (dll および静的ライブラリ) が表示されます。

于 2008-09-16T14:04:12.660 に答える
2

3 番目のオプションでは、開発マシンの C:\WINDOWS\WinSxS ディレクトリに 9.0.21022 バージョンの DLL とマニフェストが見つかる可能性があります。可能であれば、独自の redist ディレクトリをセットアップし、それらのファイルをアプリにインストールできます。

または、Visual Studio で提供される 9.0.30729.1 のものを使用し、アプリと共にインストールするマニフェストを偽造して、9.0.30729.1 ではなく 9.0.21022 DLL を提供することを報告することもできます。実行時リンカーは気にしないようです。詳細については、これらの問題の解決に非常に役立つこのブログを参照してください。

どちらの回避策も、VS2008 Express で DLL をプライベート アセンブリとして展開する際に発生した問題を解決しました。

Roelの答えは最初のオプション(「正しく修正する」)に進む方法ですが、9.0.21022に依存するライブラリに依存している場合(したがってマニフェストに両方のバージョンがリストされている場合)、3番目のオプションが唯一の可能性がありますvcredist_x86.exe を実行したくない場合は、これで問題ありません。

于 2009-10-14T17:13:33.317 に答える