5

皆さんがこの質問の長さ、そして物語のやり方を許してくれることを願っています。ブログで状況を詳しく説明することにしました。後でジョエルのこのサイトへの招待を見て、誰かが状況について何か洞察を持っているかどうかを確認するために、ここに貼り付けたいと思いました。

私は、ATLを使用してC++で記述された中間層COM+コンポーネントに対してDCOMを話すVisualBasicシッククライアントで構成されるアプリケーションを作成し、現在サポートしています。8つのオフィスすべてで稼働しています。各オフィスは、COM +アプリケーション(18の個別のコンポーネントで構成される)とSQLServerを含むバックエンドサーバーをホストします。SQLServerは通常、同じバックエンドサーバー上にありますが、そうである必要はありません。

最近、最大のオフィスであるニューヨークのバックエンドサーバーをMSCクラスターからVMWareのESXテクノロジーでホストされる新しい仮想マシンに移行しました。COM +アプリケーションの場所が古いサーバーから別の名前の新しいサーバーに移動したため、すべてのクライアントをリダイレクトして、新しいサーバーでCOM+アプリケーションをアクティブ化する必要がありました。同様のインフラストラクチャのアップグレードを行ったいくつかの小規模なオフィスで基本的に同じことを行ったため、手順は古くからありました。

すべてが日常的なもののようで、月曜日の朝、オフィス全体(約1,000台のWindows XPワークステーション)が新しいサーバーで問題なく実行されていました。しかし、その後、私のモバイルグループから電話がかかってきました。自宅でVPN接続を使用している弁護士がいて、新しいサーバーにリダイレクトされた後、奇妙なエラーが発生していました。

FillTreeView2のエラー-スタブが不正なデータを受信しました。

は?私はこれまでこのエラーメッセージを見たことがありませんでした。それは新しいサーバーでしたか?しかし、オフィス内のすべてのワークステーションは正常に機能していました。私はモバイルグループに弁護士を古いサーバー(まだ稼働していた)に戻すように指示しましたが、エラーは消えました。では、違いは何でしたか?この弁護士は自宅でVistaを運営していたことが判明しました。

私たちはどのオフィスでもVistaを運営していませんが、自宅でVistaを運営している弁護士がいます(確かに私のニューヨークのオフィスには何人かいます)。私もそうですが、この問題は見たことがありません。問題があったことを確認するために、Vistaラップトップを起動し、新しいサーバーをポイントすると、同じエラーが発生しました。私はそれを古いサーバーに戻しました、そしてそれはうまくいきました。明らかに、Vistaと新しいサーバー上のコンポーネントに問題がありました。これは、XPクライアントには影響しないように思われる問題です。どうなり得るか?

次の停止-私のラップトップのアプリケーションエラーログ。これにより、エラーに関する詳細情報が得られました。

出典:Microsoft-Windows-RPC-Events
日付:2008年9月2日11:56:07 AM
イベントID:10
レベル:エラー
コンピューター:DevLaptop
説明:アプリケーションが正しくないため、COM呼び出しを完了できませんでした
インターフェイスIDがパラメータとして渡されました。

予想されるインターフェイスIDは00000555-0000-0010-8000-00aa006d2ea4でした。
返されたインターフェイスIDは00000556-0000-0010-8000-00aa006d2ea4でした。

User Action-アプリケーションの更新バージョンについては、アプリケーションベンダーにお問い合わせください。

インターフェイスIDは、謎を解明するために必要な手がかりを提供しました。「予期される」インターフェイスIDは、MDACのRecordsetインターフェイス(具体的にはそのインターフェイスのバージョン2.1)を識別します。「返された」インターフェイスは、Recordsetの新しいバージョンに対応します(バージョン2.5は、vtableの最後に1つの追加エントリが含まれている点でバージョン2.1とは異なります--メソッドSave)。

実際、私のコンポーネントのインターフェースは、Recordsetを出力パラメーターとして渡す多くのメソッドを公開しています。それで、彼らは突然、異なるインターフェースIDを持つ新しいバージョンのRecordsetを返しましたか?確かにそうだったようです。そして、なぜそれが重要なのかと思いました。vtableは、古いインターフェイスのクライアントと同じように見えます。実際、DCOMではなくインプロセスCOMについて話していた場合、この明らかに無害なインピーダンスの不一致は黙って無視され、問題は発生しなかったと思います。

もちろん、プロセスとマシンの境界が関係する場合、クライアントとサーバーの間にプロキシとスタブがあります。この場合、私はフリースレッドマーシャラーでタイプライブラリマーシャリングを使用していました。したがって、解決すべき2つの謎がありました。

新しいサーバーのメソッドから出力パラメーターで異なるインターフェイスを返すのはなぜですか?

これがVistaクライアントにのみ影響するのはなぜですか?

私のサーバーソフトウェアは8つのオフィスのそれぞれのサーバーでホストされていたので、Vistaクライアントを順番にすべてのオフィスに向けて、Vistaに問題があるものとないものを確認することにしました。照明テスト。古いサーバーの一部は引き続きVistaで動作しましたが、新しいサーバーは動作しませんでした。古いサーバーのいくつかはまだWindows2000を実行していましたが、新しいサーバーは2003年でしたが、それは問題ではなかったようです。

コンポーネントDLLの日付を比較した後、クライアントが2003Vistaより前の日付のコンポーネントDLLを持つサーバーをポイントした場合は常に問題がないように見えました。しかし、2003年以降の日付のDLLを持っているものには問題がありました。信じられないかもしれませんが、何年もの間、サーバーコンポーネントのコードに変更はありませんでした(または少なくとも重要な変更はありませんでした)。どうやら、日付が異なるのは、単に開発マシンでコンポーネントを再コンパイルしたためです。そして、それらの再コンパイルの1つが2003年に行われたように見えました。

電球が点灯しました。Recordsetsをサーバーからクライアントに戻すとき、私のATLC++コンポーネントはインターフェイスを_Recordsetとして参照します。このシンボルは、msado15.dll内に埋め込まれたタイプライブラリに由来します。これは私がC++コードで持っていた行です:

#import "c:\ Program Files \ Common Files \ System \ ADO \ msado15.dll" no_namespace rename( "EOF"、 "adoEOF")

msdad15.dllの15にだまされないでください。どうやらこのDLLはMDACバージョンの長いシリーズで名前を変更していません。

当時、アプリケーションをコンパイルしたとき、MDACのバージョンは2.1でした。したがって、2.1インターフェイスIDでコンパイルされた_Recordsetは、これらのコンポーネントを実行しているサーバーによって返されるインターフェイスです。

すべてのクライアントは、1999年に生成された(私が信じる)COM +アプリケーションプロキシを使用します。私のインターフェイスを定義するタイプライブラリには、次の行が含まれています。

importlib( "msado21.tlb");

これは、メソッドの出力パラメーターにバージョン2.1のRecordsetが必要な理由を説明しています。明らかに問題は、2003年の再コンパイルと、その時点で_Recordsetシンボルがバージョン2.1に対応しなくなったことにありました。実際、_Recordsetは、別個のインターフェースIDを持つ2.5バージョンに対応していました。私にとっての解決策は、C++コードのすべての参照を_RecordsetからRecordset21に変更することでした。コンポーネントを再構築し、新しいサーバーにデプロイしました。出来上がり-クライアントは再び幸せそうに見えた。

結論として、私には2つのやっかいな質問が残っています。

プロキシ/スタブインフラストラクチャがVistaクライアントとは異なる動作をするように見えるのはなぜですか?Vistaは、XPよりもメソッドパラメータから返されるインターフェイスIDを厳密にチェックしているようです。

これが起こらないように、1999年にこれをどのように別の方法でコーディングする必要がありましたか?インターフェイスは不変であると想定されており、新しいバージョンのMDACで再コンパイルすると、メソッドが出力パラメーターとして別のRecordsetインターフェイスを返すようになったため、誤ってインターフェイスを変更しました。私の知る限り、当時のタイプライブラリにはバージョン固有のシンボルがありませんでした。つまり、MDACタイプライブラリの新しいバージョンではRecordset21が定義されていますが、そのシンボルは2.1タイプライブラリでは使用できませんでした。

4

1 に答える 1

2

Microsoft がセキュリティの信奉者になったとき、DCOM (およびその基盤となる RPC) は多くの注目を集め、セキュリティ ホールを塞ぐための変更が確実に行われ、マーシャリングがより厳格になりました。XP ではなく Vista でこれが表示されることに驚きましたが、Vista では追加のチェックが追加された可能性があります。または、XP のオプションの厳密性が Vista で必須になった可能性があります。

これを防ぐことができたかどうかを知るには、MDAC について十分な知識がありませんが、Microsoft が下位互換性を犠牲にすることを厭わない数少ない分野の 1 つであることは知っています。より良い」1999年にさかのぼります。

于 2008-09-18T06:10:31.627 に答える