首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >深奥的JScript托管问题:当IDis补丁::Invoke返回SCRIPT_E_PROPAGATE时,错误代码在哪里?

深奥的JScript托管问题:当IDis补丁::Invoke返回SCRIPT_E_PROPAGATE时,错误代码在哪里?
EN

Stack Overflow用户
提问于 2010-06-30 01:54:22
回答 1查看 975关注 0票数 2

我们的应用程序承载Windows脚本主机JScript引擎,并公开了几个可以从脚本代码调用的域对象。

其中一个域对象是实现IDispatch (实际上是IDispatchEx)的COM组件,它的方法将脚本函数作为回调参数(idis补丁*作为参数)。这个COM组件由脚本调用,做一些事情,然后通过提供的IDispatch参数调用脚本,然后返回到调用脚本。

如果回调脚本碰巧抛出一个异常(例如,调用另一个返回S_OK以外的东西的COM组件),那么对IDis补丁::调用回调脚本的调用将返回SCRIPT_E_PROPAGATE,而不是从另一个COM组件返回HRESULT;而不是从另一个COM对象返回预期的HRESULT。如果我将HRESULT (SCRIPT_E_PROPAGATE)返回给第一个COM组件的调用方(例如,调用脚本),那么脚本引擎将正确地抛出来自另一个COM对象的预期HRESULT错误。

然而,实际的错误却无处可寻。它不是从调用调用返回的(返回值是SCRIPT_E_PROPAGATE)。它不会通过为调用提供的EXCEPINFO返回(结构仍然是空的)。而且,它无法通过GetErrorInfo获得(调用返回S_FALSE)!

代码语言:javascript
复制
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组件在调用时抛出异常到所提供的脚本函数?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-07-02 17:04:55

哇,这是严重的文件不足。

答案是:

在COM组件中对脚本进行回调.

  1. 获得一个IDispatchEx指针的脚本函数被调用。
  2. 构造一个同时实现IServiceProvider & ICanHandleException;例如CScriptErrorCapturer的对象。
    • IServiceProvider::QueryService可以返回E_NOINTERFACE
    • 如果脚本回调函数在InvokEx'd (见下面)时抛出一个异常,但没有捕获异常,那么ICanHandleException::CanHandleException将得到一个EXCEPINFO和VARIANT* (查看文档的MSDN )。
    • 变体将包含抛出的对象,该对象可能是一个错误对象。
    • 尝试从这个错误对象的IDispatch获取"number“和"message”属性,其中"number“表示实际的脚本错误(HRESULT)。
    • 这些值可以/应该用于更新EXCEPINFO代码和(可选) bstrDescription,以便将错误传播到调用脚本。如果不更新scode,那么引擎将抛出一个“抛出但未捕获的异常”(0x800A139E),这就是EXCEPINFO在修改它之前包含的内容。
    • 不确定是否应该清除pfnDeferredFillIn,但是它不需要这样做。
    • 在我的代码中,我在这里捕获CScriptErrorCapturer中的错误。
    • 返回S_OK。在这里返回E_FAIL将中止整个脚本运行,并且不允许将异常抛回原始调用脚本。

  1. 调用IDispatchEx::InvokeEx并将CScriptErrorCapturer作为IServiceProvider参数传递。
  2. 从InvokeEx返回时,查询您的CScriptErrorCapturer以查看它是否捕获了错误。根据GoogleWebKit中的代码,有时InvokeEx可能返回S_OK,即使抛出错误也是如此。
  3. 不要触摸InvokeEx的返回值,特别是如果它是SCRIPT_E_PROPAGATE (0x80020102)

注意:此链接包含上面描述的一些无文档的JScript HRESULTS。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3145992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档