トップ回答者
VC++2005のクラスライブラリが実行環境で動きません。

質問
-
お世話になります。VC++初心者です。
ソースコードのないVC++6で製作されたDLLを、呼び出すアプリケーションをVB2005で作製中です。
そこで、VC++2005のクラスライブラリでラップのDLLを作製し、VB2005から呼び出しています。
VB2005→VC++2005クラスライブラリ→VC++6 という具合です。
開発環境では問題なく動くのですが、他のPCでは動きませんでした。
セットアップを作製し、必須コンポーネントでFramework2.0とVC++ランタイムライブラリx86を指定してテスト環境にインストールしましたが、Framework2.0とVC++ランタイムライブラリはちゃんとインストールされましたが、
実行時に「アプリケーションのコンポーネントで、ハンドルされていない例外が・・・」「ファイルまたはアセンブリ’クライス名’・・・またはその依存関係の1つが読み込みませんでした。このアプリケーションの構成が正しくないため、アプリケーションを開始できませんでした。」とエラーになります。
続行するとVBのプログラム自体は動きますが、DLLの機能を使うと上記のエラーになります。
ためしにテストとして、VBからの引数をそのまま返すだけの簡単なVC++クラスライブラリを作製してみましたが同じく、テスト環境では動きませんでした。
原因は何が考えられるでしょうか?
開発環境はWinXP SP3、Frameworks1.1SP1、2.0SP2、3.0SP2、3.5SP1、VisualStudio2005が入っています。
テスト環境は、最初Frameworks、VC++ランタイムとも無しで、アプリのSetupによるFrameworks、VC++ランタイムのインストールをして実行しました。その後UpdateでFrameworksを3.5にアップデートしSPも入れ、VC2005ランタイムもSPなしVer.とSP1バージョン両方入れてみましたが、だめでした。
そもそもの目的はVC6のDLL(ソースなし)をVB2005から呼びたいだけなので、より簡単な代替案がありましたら上記の方法にはこだわりません。
よろしくお願いします。- 編集済み テムズ 2010年3月1日 8:51 誤字
回答
-
結果、実行時エラーで動きませんでした。
コントロールパネル → 管理ツール → イベントビューアから、アプリケーションまたはシステムノードに SideBySide 関連のエラーが登録されていませんか?
エラーイベントが登録されていれば、その中身を見ることで Side by Side のエラー情報を確認できます。
(ランタイムのどのバージョンが要求されたが、見つからなかったなど)
ただし、Side by Side のエラーでない場合は、このイベントが登録されません。上記の4つのdllをテスト用実行ファイルと同じフォルダにコピーしてみましたが、動きませんでした。
どうやら、msvcr80.dllが近くにあっても(インストールされていても)探そうとしていないような気がします。Visual C++ 2005 以降は、Side by Side の仕組みが採用されており、同じフォルダにコピーするだけでは読み込まれません。
詳しくは、Side by Side で調べてみてください。>なお、Visual C++ 2005 のランタイムと一口に言っても、いくつかのバージョンがあります。
32bitの場合、SPなしとSP1の2種類だと思うのですが、どちらをインストールしてもクラスライブラリから参照してくれない状況です。その認識は正しくありません。
ATL の脆弱性修正パッチのリリースもあったことから、SP なし(42)、SP1(762)、SP1 + ATL 修正(4053)、SP なし + ATL 修正(私は未確認のため、番号不明) という 4 つのバージョンが少なくとも存在します。
また、Beta の段階で、正式利用しても良いというライセンスの元で配布されているバージョンもあるかもしれませんし、HotFix でリリースされているバージョンがあるかもしれません。
なお、できあがった DLL がどのバージョンを要求しているかは manifest ファイルを見ると分かります。
ビルドした環境であれば、Debug/Release フォルダに、embedded.manifest なりの名前で残っていると思いますし、exe/dll ファイルのリソースを見ると、RT_MANIFEST として登録されています。
このファイルは XML で書かれていますので、どのバージョンを必要としているか見ることができます。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
自作した DLL ファイル(Visual C++ で作成したファイル)は、同じソリューションにはないのでしょうか?
一つのソリューションに Visual C++ の DLL プロジェクトと、Visual Basic のプロジェクトがあるのであれば、プロジェクト参照も利用できます。
http://msdn.microsoft.com/ja-jp/library/ez524kew.aspx
参照の追加の際に、プロジェクトタブから選択するとソリューションの構成などに応じて、Debug/Release を使い分けてくれるはずです。
(構成マネージャで複雑な設定をあえてした場合はどうなるか存じません)
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク テムズ 2010年3月2日 4:40
すべての返信
-
Dependency Walkerで調べてみてはいかがでしょうか。
[C/C++ 分離アプリケーションおよび side-by-side アセンブリのトラブルシューティング]
http://msdn.microsoft.com/ja-jp/library/ms235342(VS.80).aspx
[Visual C++ アプリケーションの依存関係の理解]
http://msdn.microsoft.com/ja-jp/library/ms235265(VS.80).aspx- 回答の候補に設定 高橋 春樹 2010年2月23日 8:01
-
ありがとうございます。
Dependency Walkerで調べたら、msvcr80.dllが足りないようでした。
VC2005のランタイム?でしょうか。
開発環境からmsvcr80.dllを実行ファイルと同じフォルダにコピーしたらテスト環境で動きました。さらに、
強引な方法だと思いますが、Setupでアプリケーションフォルダにmsvcr80.dllを追加してみました。
「ファイルmsvcr80.dllは c:\program files\common files\merge modules\microsoft_vc80_crt_x86_x64.msmに存在します。マージモジュールを追加しますか?」と出ました、とりあえず、「いいえ」としたら追加できました。
このSetupを使ってインストールするとテスト環境で動きました。
FrameworksもVCランタイムもインストールされていない別のPC(XP SP2)でも、作製したSetupでインストールすると動きました。とりあえず、問題解決なのですが、msvcr80.dllを自力で突っ込むのは少々強引な気がします。
もっとスマートな方法はないものでしょうか?
必須コンポーネントでVC++ランタイムライブラリx86を指定しているのにmsvcr80.dllはインストールされないのでしょうか? -
Dependency Walkerで調べたら、msvcr80.dllが足りないようでした。
VC2005のランタイム?でしょうか。Visual C++ 2005 のランタイム(の一部)です。
さらに、
強引な方法だと思いますが、Setupでアプリケーションフォルダにmsvcr80.dllを追加してみました。
「ファイルmsvcr80.dllは c:\program files\common files\merge modules\microsoft_vc80_crt_x86_x64.msmに存在します。マージモジュールを追加しますか?」と出ました、とりあえず、「いいえ」としたら追加できました。基本的には、再頒布パッケージか、マージモジュールを利用してください。
DLL だけをコピーするやり方は現状認められていないか、推奨されていないかのどちらかです。
Visual Studio のインストール先のどこかにある REDIST.TXT の内容をご確認ください。必須コンポーネントでVC++ランタイムライブラリx86を指定しているのにmsvcr80.dllはインストールされないのでしょうか?
必須コンポーネントと指定した場合、Setup.exe から起動が前提になります。
現状、msi ファイルを直接実行していたりしませんか?
なお、Visual C++ 2005 のランタイムと一口に言っても、いくつかのバージョンがあります。
手動でインストールしたつもりでも、実は必要なバージョンが入っていないことがあるかもしれません。
(新しいバージョンが入っていれば大抵 OK です)
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答の候補に設定 高橋 春樹 2010年2月23日 8:00
-
>そもそもの目的はVC6のDLL(ソースなし)をVB2005から呼びたいだけなので
現状のModule構成は以下のとおりでしょうか?
VB 2005 Managed Application
↓↑
VC 2005 Managed/Unmanagedの橋渡し DLL (C++/CLI)
↓↑
VC 6 Unmanaged DLL
VB 2005からP/Invokeを使用して、
直接VC 6のDLLにAccessしてみては如何でしょうか。
[アンマネージ DLL 関数の処理]
http://msdn.microsoft.com/ja-jp/library/26thfadc(VS.80).aspx- 回答の候補に設定 高橋 春樹 2010年2月23日 8:00
-
構成はそのとおりです。
VC 6 Unmanaged DLLの使いたい関数は、クラスのメンバ関数で、返り値は構造体を返します。
しかも構造体のメンバに別の構造体が含まれていたりという面倒なものになっています。
こういう場合、VBで同じような構造体を定義しなくてはいけないと思うのですが、すんなりと受け渡しできる自信がないのでためらっています。
VC2005の橋渡しがある場合は、VC6DLLの.hがそのまま使えるので簡単なのですが。VC6のDLLへの直接のアクセスは、別の機会に使うこともあるかもしれませんで、その時はまた質問させていただくかもしれません。
ありがとうございます。 -
ありがとうございます。順に試しています。
>必須コンポーネントと指定した場合、Setup.exe から起動が前提になります。
>現状、msi ファイルを直接実行していたりしませんか?
これは大丈夫です。Setup.exeから実行し、VisualC++ランタイムライブラリのインストールの確認画面も出てきますし、プログラムの追加と削除にもMicrosoft Visual C++ 2005 Redistributableと出ています。
テスト用のプログラムとセットアップを作って試しました。
テストは、自作ソフトとVisual C++ 2005 Redistributableを一度すべてアンインストールしてから行いました。
テスト用のDLLはintの引数をそのままreturnするだけのクラスライブラリDLLです。
Setupでは必須コンポーネントでFramework2.0と、VisualC++ランタイムライブラリ(x86)にチェックし、「アプリケーションと同じ場所から必須コンポーネントをダウンロードする」にチェックしています。
Setupではmsvcr80.dllは手動では追加していません。
結果、実行時エラーで動きませんでした。
プログラムの追加と削除でMicrosoft Visual C++ 2005 Redistributableが入っており、サポート情報を見てみるとVersion 8.0.59193でした。
msvcr80.dllは以下の場所にありましたが、何度もインストールをアンインストールを繰り返したPCなのでいつインストールされたものかわかりません。
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_6b128700\msvcr80.dll
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_0de06acd\msvcr80.dll
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989\msvcr80.dll
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.3053_x-ww_b80fa8ca\msvcr80.dll
おそらく再頒布パッケージでインストールされたものが残っているのだと思います。
上記の4つのdllをテスト用実行ファイルと同じフォルダにコピーしてみましたが、動きませんでした。
どうやら、msvcr80.dllが近くにあっても(インストールされていても)探そうとしていないような気がします。
ここまでやって、調べていて、下記のページの3つの方法があると書いてありました。
http://msdn.microsoft.com/ja-jp/library/ms235316(VS.80).aspx
「配置方法の選択」
この1番目の方法:再配布可能マージ モジュールを使用、からリンクをたどると
http://msdn.microsoft.com/ja-jp/library/ms235317(VS.80).aspx
「方法 : セットアップおよび配置プロジェクトを使用して配置する」のなかの「Visual C++ ライブラリ DLL をプライベート アセンブリとして配置する処理手順」を見ると
C:\Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.CRT
から必要なファイルをSetupのアプリケーションフォルダにドラッグして追加するということが書いてありました。
「マージ モジュールの一部である DLL が含まれていることを示す Visual Studio メッセージが表示される場合があります。このメッセージが該当する場合は、[いいえ] をクリックして、この DLL 用の MSM を使用しないことを指定します。」
と書いてあるのですが、この「いいえ」を選択した場合が、上のほうで書いた「強引な方法」と同じだと思います。
今度は「はい」を選択してみてリビルドしたものを(再頒布をアンインストールしたのちに)テスト環境にセットアップしてみましたが、動きませんでした。(実行時エラー)
>なお、Visual C++ 2005 のランタイムと一口に言っても、いくつかのバージョンがあります。
32bitの場合、SPなしとSP1の2種類だと思うのですが、どちらをインストールしてもクラスライブラリから参照してくれない状況です。
msvcr80.dllがインストールされていても(アプリと同じファルダに置いても)使えないということは、マニフェストなどの問題なのでしょうか?
原因がよくわかりません。- 編集済み テムズ 2010年3月1日 8:56 誤字
-
結果、実行時エラーで動きませんでした。
コントロールパネル → 管理ツール → イベントビューアから、アプリケーションまたはシステムノードに SideBySide 関連のエラーが登録されていませんか?
エラーイベントが登録されていれば、その中身を見ることで Side by Side のエラー情報を確認できます。
(ランタイムのどのバージョンが要求されたが、見つからなかったなど)
ただし、Side by Side のエラーでない場合は、このイベントが登録されません。上記の4つのdllをテスト用実行ファイルと同じフォルダにコピーしてみましたが、動きませんでした。
どうやら、msvcr80.dllが近くにあっても(インストールされていても)探そうとしていないような気がします。Visual C++ 2005 以降は、Side by Side の仕組みが採用されており、同じフォルダにコピーするだけでは読み込まれません。
詳しくは、Side by Side で調べてみてください。>なお、Visual C++ 2005 のランタイムと一口に言っても、いくつかのバージョンがあります。
32bitの場合、SPなしとSP1の2種類だと思うのですが、どちらをインストールしてもクラスライブラリから参照してくれない状況です。その認識は正しくありません。
ATL の脆弱性修正パッチのリリースもあったことから、SP なし(42)、SP1(762)、SP1 + ATL 修正(4053)、SP なし + ATL 修正(私は未確認のため、番号不明) という 4 つのバージョンが少なくとも存在します。
また、Beta の段階で、正式利用しても良いというライセンスの元で配布されているバージョンもあるかもしれませんし、HotFix でリリースされているバージョンがあるかもしれません。
なお、できあがった DLL がどのバージョンを要求しているかは manifest ファイルを見ると分かります。
ビルドした環境であれば、Debug/Release フォルダに、embedded.manifest なりの名前で残っていると思いますし、exe/dll ファイルのリソースを見ると、RT_MANIFEST として登録されています。
このファイルは XML で書かれていますので、どのバージョンを必要としているか見ることができます。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
コントロールパネル → 管理ツール → イベントビューアから、アプリケーションまたはシステムノードに SideBySide 関連のエラーが登録されていませんか?
エラーイベントが登録されていれば、その中身を見ることで Side by Side のエラー情報を確認できます。
(ランタイムのどのバージョンが要求されたが、見つからなかったなど)確認作業遅くなりましてすみません。
まだ調べている途中ですが、システムノードで次のエラーがありました。ここからは細かいバージョンなどは分かりませんでした。
イベントの種類: エラー
イベント ソース: SideBySide
イベント カテゴリ: なし
イベント ID: 59
日付: 2010/02/26
時刻: 18:36:35
ユーザー: N/A
コンピュータ:
説明:
Generate Activation Context が C:\Program Files\既定の会社名\Setup1\testclass.dll に失敗しました。 参照エラー メッセージ : この操作を正しく終了しました。
詳細な情報は、http://go.microsoft.com/fwlink/events.asp の [ヘルプとサポート センター] を参照してください。イベントの種類: エラー
イベント ソース: SideBySide
イベント カテゴリ: なし
イベント ID: 59
日付: 2010/02/26
時刻: 18:36:35
ユーザー: N/A
コンピュータ:
説明:
Resolve Partial Assembly が Microsoft.VC80.DebugCRT に失敗しました。 参照エラー メッセージ : 参照されたアセンブリはシステムにインストールされていません。
詳細な情報は、http://go.microsoft.com/fwlink/events.asp の [ヘルプとサポート センター] を参照してください。
イベントの種類: エラー
イベント ソース: SideBySide
イベント カテゴリ: なし
イベント ID: 32
日付: 2010/02/26
時刻: 18:36:35
ユーザー: N/A
コンピュータ:
説明:
従属するアセンブリ Microsoft.VC80.DebugCRT を検出できませんでした。エラー: 参照されたアセンブリはシステムにインストールされていません。
詳細な情報は、http://go.microsoft.com/fwlink/events.asp の [ヘルプとサポート センター] を参照してください。
また、Releaseの~.dll.intermediate.manifestには
<assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.4053' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
と書いてありました。
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989\msvcr80.dll
が、そのバージョンのdllだと思うのですが、どうすれば使うことができるのか方法が分かりません。
マニフェストは「埋め込み」にしています。
'8.0.50727.4053' で検索すると以下のページに当たるのですが、「対象外」などと書いてあるのが気になります。
http://support.microsoft.com/default.aspx/kb/973923/ja
これは、つまり開発環境に入っているサービスパック?が推奨されていないバージョンということなのでしょうか?
よろしくお願いします。 -
>「対象外」
Not applicable、当てはまらない、という意味です。
いわゆるN/Aです。
Version Information Resourceがつけられないか、
つけるファイルではない為、
対象外と表現されているのでしょう。
すでにご指摘のとおり、
現状のInstallerはDebug BuildされたVC 2005 DLLファイルが
指定されていると考えられます。
作成したInstallerでRelease BuildされたVC 2005 DLLファイルが
指定されているか確認しましょう。
Installerで正しいVC 2005 DLLファイルが選択されていれば、
開発環境にあるRelease BuildされたVC 2005 DLLファイルと、
InstallerでInstallされたVC 2005 DLLファイルのファイルサイズは、
同じになるはずですね。
(普通はDebug版のファイルサイズの方が大きいですから、
違いがわかると思います)
あるいは、
InstallerでInstallされたVC 2005 DLLファイルのManifest Resourceを見て、
Microsoft.VC80.DebugCRTではなく、
Microsoft.VC80.CRTが指定されているか確認すれば、
確実ですね。
以下の記載が気になりますが、まずは上記の内容をご確認ください。
>Dependency Walkerで調べたら、
>msvcr80.dllが足りないようでした。
>(省略)
>このSetupを使ってインストールするとテスト環境で動きました。
Debug版のVC 2005 DLLファイルがInstallされているなら、
msvcr80d.dllが足りないと表示されると思います。 -
自作した DLL ファイル(Visual C++ で作成したファイル)は、同じソリューションにはないのでしょうか?
一つのソリューションに Visual C++ の DLL プロジェクトと、Visual Basic のプロジェクトがあるのであれば、プロジェクト参照も利用できます。
http://msdn.microsoft.com/ja-jp/library/ez524kew.aspx
参照の追加の際に、プロジェクトタブから選択するとソリューションの構成などに応じて、Debug/Release を使い分けてくれるはずです。
(構成マネージャで複雑な設定をあえてした場合はどうなるか存じません)
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。- 回答としてマーク テムズ 2010年3月2日 4:40
-
以下の記載が気になりますが、まずは上記の内容をご確認ください。
>Dependency Walkerで調べたら、
>msvcr80.dllが足りないようでした。
>(省略)
>このSetupを使ってインストールするとテスト環境で動きました。
Debug版のVC 2005 DLLファイルがInstallされているなら、
msvcr80d.dllが足りないと表示されると思います。
最初のうちはソリューションが別々だったのでVC2005のDLLをコピーしたりして使用していました。
なので、たまたまRelease版を使っていたのかもしれません。
ソリューションが統一されていなかったのが間違いの根源だったのかもしれません。