2

このアプリケーションは、Windows Scripting Host JScriptエンジンをホストし、スクリプトコードから呼び出すことができるいくつかのドメインオブジェクトを公開します。

ドメインオブジェクトの1つは、IDispatch(実際にはIDispatchEx)を実装し、スクリプト関数をコールバックパラメーター(IDispatch *をパラメーター)として受け取るメソッドを持つCOMコンポーネントです。このCOMコンポーネントはスクリプトによって呼び出され、いくつかのことを実行してから、呼び出し元のスクリプトに戻る前に、指定されたIDispatchパラメーターを介してスクリプトにコールバックします。

コールバックスクリプトがたまたま例外をスローした場合(たとえば、S_OK以外のものを返す別のCOMコンポーネントを呼び出す場合)、コールバックスクリプトでIDispatch :: Invokeを呼び出すと、HRESULTではなくSCRIPT_E_PROPAGATEが返されます。他のCOMコンポーネントから。他のCOMオブジェクトから期待されるHRESULTではありません。そのHRESULT(SCRIPT_E_PROPAGATE)を最初のCOMコンポーネントの呼び出し元(たとえば、呼び出し元のスクリプト)に戻すと、スクリプトエンジンは、他のCOMオブジェクトからの予想されるHRESULTでエラーを正しくスローします。

ただし、実際のエラーはどこにも見つかりません。Invoke呼び出しからは返されません(戻り値はSCRIPT_E_PROPAGATEです)。Invokeに提供されたEXCEPINFOを介して返されることはありません(構造は空のままです)。また、GetErrorInfoでは使用できません(呼び出しはS_FALSEを返します)。

Script
    Defines ScriptCallback = function() { return ComComponentB.doSomething(); }
    Invokes ComComponentA.execute(ScriptCallback)
        Invokes ScriptCallback()
            Invokes ComComponentB.doSomething()
                Returns E_FAIL (or some other HRESULT)
            Throws returned HRESULT
        Receives SCRIPT_E_PROPAGATE <--- WHERE IS THE ACTUAL ERROR?
        Returns SCRIPT_E_PROPAGATE
    Throws E_FAIL (or whatever HRESULT was returned from ComComponentB)

私は本当にそのエラーを手に入れたいと思っています。なぜなら、それをキャッシュして、後続の呼び出しで同じエラーを返すことが役立つからです(エラーに到達するには、スクリプト関数によって定義される高価な操作が必要になることがよくあります。パラメータですが、エラーをキャッシュする方法を知っています)。スクリプト化されたCOMコンポーネントが、提供されたスクリプト関数へのコールバック中にスローされた例外を取得する方法はありますか?

4

1 に答える 1

2

うわー、これはひどく文書化されていませんでした。

答えは次のとおりです。

COMコンポーネントで、スクリプトへのコールバックを作成しています...

  1. 呼び出されるスクリプト関数のIDispatchExポインターを取得するためのQI 。
  2. IServiceProviderICanHandleExceptionの両方を実装するオブジェクトを作成します。例:CScriptErrorCapturer
    • IServiceProvider::QueryServiceはE_NOINTERFACEを返すことができます
    • スクリプトコールバック関数がInvokExを実行したときに例外をスローしたがキャッチしなかった場合(以下を参照)、ICanHandleException ::CanHandleExceptionはEXCEPINFOとVARIANT*を取得します(ドキュメントについてはMSDNを参照してください)。
    • バリアントには、スローされたオブジェクトが含まれます。これは、Errorオブジェクトである可能性があります。
    • このErrorオブジェクトのIDispatchから「number」および「message」プロパティを取得してみてください。「number」は実際のスクリプトエラー(HRESULT)を表します。
    • これらの値は、エラーを呼び出し元のスクリプトに伝播するために、EXCEPINFO scodeおよび(オプションで)bstrDescriptionを更新するために使用できます/使用する必要があります。scodeを更新しない場合、エンジンは「例外がスローされましたがキャッチされません」(0x800A139E)をスローします。これは、変更する前にEXCEPINFOに含まれているものです。
    • pfnDeferredFillInをクリアする必要があるかどうかはわかりませんが、これを行わなくても機能します。
    • 私のコードでは、CScriptErrorCapturerでエラーをキャプチャします。
    • S_OKを返します。ここでE_FAILを返すと、スクリプトの実行全体が中止され、例外が元の呼び出し元のスクリプトに戻されることはありません。
  3. IDispatchEx :: InvokeExを呼び出し、CScriptErrorCapturerをIServiceProviderパラメーターとして渡します。
  4. InvokeExから戻ったら、CScriptErrorCapturerにクエリを実行して、エラーが検出されたかどうかを確認します。GoogleWebKitのコードによると、エラーがスローされた場合でも、InvokeExがS_OKを返す場合があります。
  5. 特にSCRIPT_E_PROPAGATE(0x80020102)の場合は、InvokeExからの戻り値に触れないでください。

注:このリンクには、上記の文書化されていないJScriptHRESULTSの一部が含まれています。

于 2010-07-02T17:04:55.527 に答える