Esoteric JScript problème d'hébergement: où est le code d'erreur lorsque IDispatch :: retourne Invoke SCRIPT_E_PROPAGATE?

StackOverflow https://stackoverflow.com/questions/3145992

Question

Nos hôtes d'application du moteur JScript Windows Scripting Host et expose plusieurs objets de domaine qui peut être appelé à partir du code de script.

L'un des objets de domaine est un composant COM qui implémente IDispatch (en fait, IDispatchEx) et qui a une méthode qui prend un script fonction en tant que paramètre de rappel (IDispatch * comme paramètre). Ce composant COM est appelé par le script, fait certaines choses, et appelle ensuite revenir dans le script via ce paramètre IDispatch fourni avant de retourner au script appelant.

Si le script de rappel arrive à lancer une exception (par exemple, fait un appel à un autre composant COM qui renvoie autre chose que S_OK), l'appel à IDispatch :: Invoke sur le script de rappel sera de retour SCRIPT_E_PROPAGATE au lieu du HRESULT de l'autre composant COM; pas le HRESULT attendu de l'autre objet COM. Si je reviens que HRESULT (SCRIPT_E_PROPAGATE) à l'appelant du premier composant COM (par exemple, au script appelant), le moteur de script lance correctement une erreur avec le HRESULT attendu de l'autre objet COM.

Cependant, ERREUR RÉEL est introuvable. Ce n'est pas revenu de l'appel Invoke (la valeur de retour est SCRIPT_E_PROPAGATE). Ce n'est pas retourné par le EXCEPINFO fourni à Invoke (la structure reste vide). ET, ce n'est pas disponible via GetErrorInfo (l'appel retourne 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)

Je vraiment comme pour mettre la main sur cette erreur, car il serait utile de mettre en cache et retourner la même erreur sur les appels suivants (se rendre à l'erreur implique souvent une opération coûteuse qui est défini par le script fonction passée en paramètre, mais je ne sais comment mettre en cache l'erreur). Est-il possible pour un composant COM scénarisé pour se rendre à une exception levée lors d'un rappel dans un script fonction fourni ???

Était-ce utile?

La solution

Wow, cela a été sérieusement underdocumented.

La réponse est à:

Dans le composant COM faisant un rappel dans le script ...

  1. QI pour obtenir un IDispatchEx pointeur sur la fonction de script à appeler.
  2. Construire un objet à la fois la mise en œuvre IServiceProvider & ICanHandleException ; par exemple. CScriptErrorCapturer .
    • IServiceProvider :: QueryService peut retourner E_NOINTERFACE
    • Si la fonction de rappel de script lance, mais ne se coince pas, une exception lorsque InvokEx'd (voir ci-dessous), puis ICanHandleException :: CanHandleException et obtenir un EXCEPINFO VARIANT * (regard sur MSDN pour documentation ).
    • La variante contiendra l'objet jeté, ce qui pourrait être un Erreur objet.
    • Essayez d'obtenir les propriétés "nombre" et "message" du IDispatch sur cette Erreur objet, où "nombre" représente l'erreur de script réel (HRESULT).
    • Ces valeurs peuvent / doit être utilisé pour mettre à jour le EXCEPINFO scode et (éventuellement) bstrDescription afin de propager l'erreur jusqu'à le script appelant. Si vous ne mettez pas à jour scode , puis ensuite le moteur lancera une « exception levée, mais pas pris » (0x800A139E), qui est ce que le EXCEPINFO contient avant de le modifier.
    • Je ne sais pas si pfnDeferredFillIn devrait être autorisé, mais il fonctionne sans le faire.
    • Dans mon code, je capture l'erreur ici dans mon CScriptErrorCapturer.
    • S_OK. De retour E_FAIL ici annulerait la course entière de script, et ne pas laisser l'exception à être rejetées jusqu'au script appelant d'origine.
  3. Appel IDispatchEx :: InvokeEx et passez votre CScriptErrorCapturer comme paramètre IServiceProvider.
  4. Au retour de InvokeEx, votre requête CScriptErrorCapturer pour voir si elle a détecté une erreur. Selon dans le GoogleWebKit , parfois InvokeEx peut retourner S_OK, même si une erreur est levée.
  5. Ne touchez pas la valeur de retour de InvokeEx, surtout si elle est SCRIPT_E_PROPAGATE (0x80020102)

Note: cette lien contient certains des sans papier JScript HRESULTS décrit ci-dessus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top