1

私は、ActiveX DLL を使用して別の一般的なアプリ (より適切な言葉がないため、別名「ホスト」アプリ) に接続する Delphi 6 アプリを持っています。ホスト アプリは統合 DLL を提供します。私はそのソースコードやそれを制御するものを持っていません。DLL を使用するには、IDEインポート ActiveX コントロール機能を使用して TypeLib を作成します。

この問題は、ホスト アプリ ベンダーが ActiveX DLL の新しいバージョンを作成するときに発生します。ユーザーがホスト アプリ ベンダーの最新バージョンまたはベータ バージョンにアップグレードするときに、ユーザーに新しいバージョンのプログラムを提供する必要があります。そうしないと、古い TypeLib と新しい DLL の違いにより、統合 DLL に対して特定の呼び出しが行われると、もちろんアプリがクラッシュします。これは、ホスト アプリの古いバージョンをまだ使用しているユーザーのサポートを維持するために、アプリの複数のコード ベースを維持する負担にもつながります。実行時に現在の DLL バージョンに適応できるコードのバージョンを作成するために、統合 DLL によって公開されているすべてのものを目に見えるようにラップする、大規模で厄介なコードのオーバーホールを回避しようとしています。

それが私の質問につながります。Delphi によって生成される TypeLib は、IDispatch のメソッドとプロパティの大きなリストです。どうやら、Delphi コンパイラはこれらをバックグラウンドで IDispatch.Invoke() 呼び出しに変換します。これで、 CoCreate() を呼び出して ActiveX オブジェクトを作成するに、ホスト アプリの現在のバージョンを検出できます。では、実行時に 2 つの DLL TypeLib 定義を切り替える方法はありますか? 現在、ビルド対象のホスト アプリのバージョンに基づいた正しい TypeLib を含むコンパイル時の条件を使用して実行しています。これができるのは、TypeLib の各バージョンを保持し、ベンダーが DLL を更新するときに一意の名前を付けるからです。しかし、それは実行時にそれを行うのに役立ちません。

定義された変数からメソッド呼び出しまでのすべてがコンパイルされた TypeLib に基づいているため、これを行う方法を理解することはできません。しかし、これを実現するために IDispatch レベルでできる賢い方法があるかどうか疑問に思っていました。そうしないと、ホスト アプリの現在のバージョンに基づいて正しい TypeLib メソッド/プロパティ定義を呼び出す、公開された各オブジェクトのラッパーを作成するのに行き詰まります。これは大きな仕事であり、かなり複雑なコードにもなります。

これと同じ苦境に直面した人は、どのように解決したり対処したりしましたか?

4

1 に答える 1

3

CreateOleObject実際の解決策は、タイプライブラリを介した早期バインディングを使用する代わりに、遅延バインディング (参照を使用して参照を取得し、実行時に参照を解決する) を使用することです。これは、ベンダーが機能を削除しない限り、インストールされているコントロールのバージョンに関係なく、コードが引き続き機能することを意味します。

MS Office アプリケーションでこれを行う例については、 Deborah Pate のサイト(以下の注を参照)で古い (ただし正確で使用可能な) 投稿のいくつかを見ることができます。たとえば、の Word の例では、遅延バインディングを使用して、現在実行中の Word インスタンスを取得するか、新しいインスタンスを作成します。

var 
  Word: Variant; 
  Filename: OleVariant;
begin 
  try 
    Word := GetActiveOleObject('Word.Application');    
  except 
    Word := CreateOleObject('Word.Application');    
  end; 

  FileName := 'C:\WordDocs\MyFile.doc';
  Word.Documents.Open(FileName, EmptyParam, EmptyParam, EmptyParam,
                      EmptyParam, EmptyParam, EmptyParam, EmptyParam,
                      EmptyParam, EmptyParam);  
  Word.Visible := True;

ここにはタイプ ライブラリが含まれておらず、Word.DocumentsまたはDocuments.Openメソッドの事前宣言がないことに注意してください。これらは両方とも実行時に解決され、実装されていない場合は例外が発生します。

于 2012-12-25T05:46:11.890 に答える