names=ole_query_interface
visibility=public
kind=defined

--- ole_query_interface(iid) -> WIN32OLE

IID（インターフェイスID）を指定してオブジェクトの別のインターフェイスを
持つオブジェクトを取得します。

オブジェクトが複数のオートメーション用インターフェイスを持つ場合に、当
メソッドを利用して既定のインターフェイスとは異なるインターフェイスを取
得します。

@param iid 取得するインターフェイスのIIDを文字列で指定します。
@return iidパラメータで指定したインターフェイスを持つWIN32OLEオブジェクト
@raise WIN32OLERuntimeError 指定したIIDをオブジェクトが持たない場合に通知されます。

    ie = WIN32OLE.new('InternetExplorer.Application')
    ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}')

上例のie_web_appは、ieと同じインスタンスとなります。

COMの仕様では1つのインターフェイスについて同じIID問い合わせに対しては常
に同一のインターフェイスを返すことが決められています。

このため、正しく実装されたOLEオートメーションサーバでは本メソッドが意味
を持つことはありません。というのは、2つ以上の異なるWIN32OLEで操作可能な
インターフェイスを持つということは、IID_IDispatch（OLEオートメーション
のインターフェイスID）を指定した問い合わせに対して異なるインターフェイ
スを返すということになるからです。これは、結果的に呼び出し側プログラム
がいつでも間違えたインターフェイスを呼び出す可能性を持つということを意
味します。当然、それはサーバ実装のバグです。

問題は、C++のvtblアクセスや.NET FrameworkのCOM Interopのために静的型情
報が必要となることです。このため、一度あるインターフェイスを返すことに
決めた場合、実際に返すインターフェイスが元のインターフェイスを継承して
いたとしても、ドキュメント上は異なるインターフェイスとして定義しなけれ
ば追加のメソッドが呼び出せません。

たとえば、当メソッドの存在理由である
[[url:http://www.ruby-forum.com/topic/109954]]（なお、元のパッチと異な
りGUIDの統一フォーマットを利用するように改造されているため、IIDの前後に
{}が必要です）には、Solutionオブジェクトに対してSolution2オブジェクトの
取得を依頼するために、必要ということになっています。実際、Solutionプロ
パティが返すのは、この場合はSolutionインターフェイスを継承した
Solution2インターフェイスです。しかし、Solutionプロパティの型情報は
Solutionインターフェイスを返すことになっているため、静的に型を解決して
いる場合は、追加のメソッドの呼び出しを記述できません。

しかし、WIN32OLEが利用するIDispatchインターフェイスは、メソッド名による
動的なメソッド検索が行われます。このため、Solutionオブジェクト（しかし
その実態はSolution2オブジェクト）に対してSolution2で追加されたメソッド
（たとえばGetProjectTemplate）を指定したとしても正しく呼び出せます。つ
まり、[[url:http://www.ruby-forum.com/topic/109954]]で例示されているよ
うなole_query_interfaceメソッドの呼び出しは不要です。

もし、当メソッドの呼び出しが本当に必要なのであれば、まず、該当するOLEオー
トメーションサーバの修正を依頼してください。その実装は正しくありません。

正しく実装されたオブジェクトに対して当メソッドを適用すると、結果として、
同一オブジェクトの参照カウント値を無駄に増加させることになります。

なお、サポートしているインターフェイスのバージョンを調べたい場合に、以
下のような方法で、インターフェイスのバージョンを調べることができます。

  def check_solution_version(obj)
    [['{CDA7305C-78B6-4D9D-90AD-93EBE71F9341}', 4],
     ['{DF23915F-FDA3-4DD5-9CAA-2E1372C2BB16}', 3],
     ['{FA238614-FBB1-4314-A7F7-49AE8BB6C6BA}', 2]].each do |iid, ver|
      begin
        intf = obj.ole_query_interface(iid)
        intf.ole_free
        return ver
      rescue WIN32OLERuntimeError
      end
    end
    1
  end

しかし、ole_query_interfaceのような特異なメソッドを利用するよりも、
WIN32OLE.new('VisualStudio.DTE.8.0') のように生成時にバージョン番号（こ
の例では8.0）を指定するほうが良いスタイルです。

また、単に特定のメソッドをサポートしているかどうかを知りたいだけであれ
ば、[[m:WIN32OLE#ole_respond_to?]]を利用したダックタイピングをしてくだ
さい。

