アプリは VS 2008 SP1 DLL では実行できません。以前のバージョンは RTM バージョンで動作します
-
09-06-2019 - |
質問
Visual Studio 6 から Visual Studio 2008 に切り替えて以来、バージョンを気にしないように、マニフェスト ファイルとともに MFC90.dll と msvc[pr]90.dll をプライベートなサイドバイサイド構成で使用してきました。またはシステムにインストールします。
SP1 以前では、これは正常に動作していました (開発者のマシンでは現在も正常に動作しています)。SP1 後のテストをいくつか行ったので、昨日の朝から髪を引っ張っています。
まず、NSIS インストーラー スクリプトは redist フォルダーから dll とマニフェスト ファイルをプルします。アプリはまだ RTM バージョンにリンクしているため、これらは正しくなくなりました。
そこで私は次の定義を追加しました _BIND_TO_CURRENT_VCLIBS_VERSION=1
すべてのプロジェクトに、redist フォルダー内の SP1 DLL (または、新しいサービス パックがリリースされるとそれ以降の DLL) が使用されるようにします。これを見つけるのに何時間もかかりました。
コンパイルから中間ファイル フォルダーに生成されたマニフェスト ファイルを再確認しました。9.0.30729.1 SP1 バージョンが正しくリストされています。クリーンなマシンに依存するかどうかを二重、三重にチェックしました。すべてエラーなしでローカル DLL にリンクされます。
アプリを実行すると、引き続き次のエラーが発生します。
アプリケーションは適切に初期化できませんでした (0xc0150002)。「OK」をクリックしてアプリケーションを終了します。
Google や Microsoft で検索しても、私が特定の問題に関連するものは見つかりませんでした (ただし、2005 年まで遡ってこのエラー メッセージがヒットしました)。
SP1 で同様の問題が発生した人はいますか?
オプション:
- 問題を見つけて修正し、正常に動作するようにします (推奨)
- 再ディストリビューションをインストールする
- 古い RTM DLL とマニフェスト ファイルを掘り出し、#define を削除して現在のものを使用します。(Microsoft が Redist フォルダーからそれらを削除したため、私は以前のインストーラー ビルドにそれらを入れました。)
編集: 定義をオフにして再ビルドしてみました (RTM DLL へのリンク)。RTM DLL がフォルダーにインストールされている限り、それは機能します。SP1 DLL がドロップインされると、次のエラーが発生します。
c:\Program Files\...\...\X.exe
アプリケーションの構成が正しくないため、このアプリケーションは起動できませんでした。アプリケーションを再インストールすると、この問題が解決される可能性があります。
他にこの問題に対処する必要があった人はいませんか?
編集: ニヤニヤするために、VS2008SP1 用の vcredist_x86.exe をテスト マシンにダウンロードして実行しました。 それ 動作します。SP1 DLL を使用します。そして私のRTMリンクアプリ。しかし ない SP1 以前に動作していたプライベートなサイドバイサイド ディストリビューションで。
解決
私自身も先週この問題と闘い、今では自分をある程度の専門家だと思っています ;)
すべての 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 テーママニフェスト」の下を見てください。右側の「version」属性が「9.0.30729.1」であることを確認します。「9.0.21022」の場合、静的ライブラリが古いバージョンのマニフェストを取り込んでいます。
私が発見したのは、多くの場合、 両方 バージョンはマニフェストに含まれていました。これは、一部のライブラリは sp1 バージョンを使用し、他のライブラリは使用しないことを意味します。
どのライブラリにプリプロセッサ ディレクティブが設定されていないかをデバッグするための優れた方法:プラットフォームのヘッダーを一時的に変更して、古いマニフェストを埋め込もうとしたときにコンパイルが停止するようにします。C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h を開きます。「21022」という文字列を検索します。その定義に、無効なものを入れます (「define」を「blehbleh」などに変更します)。このようにして、プロジェクトをコンパイルするときに、 _BIND_TO_CURRENT_CRT_VERSION
プリプロセッサ フラグが設定されていない場合は、コンパイルが停止し、それらを追加する必要があることがわかり、すべての場所に適用されていることを確認できます。
また、どの DLL がプルされているかを知るために、Dependency Walker を必ず使用してください。更新プログラムなし (SP2 のみ) の新しい Windows XP コピーを仮想マシンにインストールするのが最も簡単です。こうすることで、SxS フォルダー内に、指定した並列 DLL の代わりに使用されているものが何もないことが確実にわかります。
他のヒント
この問題を理解するには、次のような問題があることを認識することが重要だと思います。 4 つのバージョン番号が関係する:
- (A) .exe がコンパイルされる VC ヘッダー ファイルのバージョン。
- (B) その .exe のリソース セクションに埋め込まれているマニフェスト ファイルのバージョン。デフォルトでは、このマニフェスト ファイルは Visual Studio によって自動的に生成されます。
- (C) .exe と同じディレクトリにコピーする VC .DLL (サイドバイサイド アセンブリの一部) のバージョン。
- (D) .exe と同じディレクトリにコピーする VC マニフェスト ファイル (サイドバイサイド アセンブリの一部) のバージョン。
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 氏が指摘するように、これを実装するのはかなり難しい場合があります。
さて、私の状況(と同じだと思います) クラッシュムストラの) は番号 1 です。問題は、Visual Studio が何らかの理由で v2 のクライアント コード (A) を生成するのに、何らかの理由で v1 のマニフェスト ファイル (B) を生成することです。バージョン (A) をどこで設定できるのかわかりません。
注記 この説明全体がまだ文脈の中にあるということ 私的な集会.
アップデート:ようやく何が起こっているのか理解し始めます。どうやら、 Visual Studio はデフォルトで v2 のクライアント コード (A) を生成します, 、私がいくつかの Microsoft ブログで読んだ内容とは反対です。_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 が正常に機能する理由も説明されています。
パブリック サイド バイ サイド アセンブリでは、vcredist が実行され、VC 9.0 DLL が Windows SxS ディレクトリに配置されるため、状況はさらに奇妙です。.exe のマニフェスト ファイルに古いバージョンの DLL を使用する必要があると記載されている場合でも (_BIND_TO_CURRENT_VCLIBS_VERSION フラグが設定されていない場合)、Windows 無視する デフォルトではこのバージョン番号です。代わりに、システム上に存在する場合、Windows は新しいバージョンを使用します。 「アプリケーション構成ファイル」の場合 使用されている。
これは紛らわしいと思うのは私だけでしょうか?
それで 要約すれば:
- プライベート アセンブリの場合は、.exe のプロジェクトで _BIND_TO_CURRENT_VCLIBS_VERSION フラグを使用し、 全て 依存する .lib プロジェクト。
- パブリック アセンブリの場合、Windows が SxS ディレクトリから正しいバージョンの .DLL を自動的に選択するため、これは必要ありません。
どの静的ライブラリが不正に動作しているかを見つけるために使用した別のトリックを思い出しました。文字列「21022」の静的ライブラリを介して「grep」を実行します。ただし、wingrep などの「通常の」 grep ツールは使用しないでください。これらの文字列は表示されないためです (バイナリ ファイルであると考えられ、生の非 Unicode 文字列が検索されます)。リソース キット (現在は Russinovich サイトにあると思います) の「strings」ユーティリティを使用します。これはバイナリを grep します。したがって、この「文字列」をソース ツリー全体に通すと、間違ったマニフェスト (または間違ったバージョンが含まれているマニフェスト) への参照を含むバイナリ ファイル (dll および静的ライブラリ) が表示されます。
exe および dll マニフェストを表示するためのもう 1 つの便利なツールは次のとおりです。 マニフェストビュー, これは、当然のことながら、XP のクリーン インストールでは実行されません。 それ 9.0.21022 に依存します。
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 を実行したくない場合は、この方法を使用してください。