Esoteric JScript-Hosting-Problem: Wo ist der Fehlercode, wenn IDispatch :: Invoke SCRIPT_E_PROPAGATE zurückkehrt?

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

Frage

Unsere Anwendungshosts der Windows Scripting Host JScript-Engine und setzt mehrere Domain-Objekte, die von Script-Code aufgerufen werden kann.

Eine der Domain-Objekte ist eine COM-Komponente, dass Geräte IDispatch (eigentlich IDispatchEx) und die eine Methode hat, die eine Skript-Funktion als Rückruf Parameter übernimmt (ein IDispatch * als Parameter). Diese COM-Komponente von Skript aufgerufen wird, hat einige Dinge, und ruft dann zurück in Skript über die mitgelieferten IDispatch-Parameter, bevor mit dem anrufenden Skript zurück.

Wenn der Call-Back-Skript eine Ausnahme werfen geschieht (zB einen Anruf an einem anderen COM-Komponente, die etwas anderes als S_OK zurückgibt), dann den Anruf an IDispatch :: Invoke auf dem Call-Back-Skript zurück SCRIPT_E_PROPAGATE statt der HRESULT von der anderen COM-Komponente; nicht die erwartete HRESULT von dem anderen COM-Objekt. Wenn ich diese HRESULT (SCRIPT_E_PROPAGATE) zurück an den Aufrufer der ersten COM-Komponente zurückgeben (zum Beispiel an das anrufende Skript), dann richtig der Skript-Engine einen Fehler mit dem erwarteten HRESULT von dem anderen COM-Objekt wirft.

Allerdings ist die ACTUAL ERROR ist nirgends zu finden. Es ist nicht von dem Invoke-Aufruf (der Rückgabewert SCRIPT_E_PROPAGATE) zurückgegeben. Es ist nicht zurück über die EXCEPINFO zu Invoke geliefert (die Struktur bleibt leer). Und es ist nicht über GetErrorInfo zur Verfügung (der Anruf kehrt 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)

Ich würde wirklich wie meine Hände auf diesem Fehler zu bekommen, weil es nützlich wäre, es zu cachen und die gleichen Fehler bei nachfolgenden Aufrufen zurückgeben (nach Fehlern immer beinhaltet oft eine teure Operation, die wird durch die Skript-Funktion übergeben als Parameter definiert ist, aber ich weiß, wie der Fehler-Cache). Gibt es eine Möglichkeit für eine Skript-COM-Komponente auf eine Ausnahme während eines Rückrufs in eine mitgelieferte Skript-Funktion ???

geworfen zu bekommen
War es hilfreich?

Lösung

Wow, war das ernst underdocumented.

Die Antwort ist:

In der COM-Komponente einen Rückruf in Skript machen ...

  1. QI eine IDispatchEx Zeiger auf die Skriptfunktion erhalten aufgerufen werden.
  2. Erstellen Sie ein Objekt der Umsetzung sowohl IServiceProvider & ICanHandleException ; z.B. CScriptErrorCapturer .
    • IServiceProvider :: Query können E_NOINTERFACE zurückkehren
    • Wenn das Skript Callback-Funktion auslöst, aber nicht fangen, eine Ausnahme, wenn InvokEx'd (siehe unten), dann ICanHandleException :: CanHandleException wird eine EXCEPINFO und VARIANT * (Blick auf MSDN erhalten für Dokumentation ).
    • Die Variante enthält das Objekt geworfen, die ein Fehler sein könnte Objekt.
    • Versuchen Sie, die „Nummer“ und „Meldung“ Eigenschaften von der IDispatch auf diesem Fehler zu bekommen Objekt, wobei „Nummer“ stellt den eigentlichen Skriptfehler (HRESULT).
    • Diese Werte können / sollen verwendet werden, um die EXCEPINFO zu aktualisieren Scode und (optional) bstrDescription , um den Fehler bis zum Aufruf Skript zu propagieren. Wenn Sie nicht aktualisieren Sie die Scode , dann dann wird Motor eine „Exception geworfen, aber nicht gefangen“ werfen (0x800A139E), das ist, was die EXCEPINFO enthält, bevor Sie es ändern.
    • Nicht sicher, ob pfnDeferredFillIn sollten gelöscht werden, aber es funktioniert, ohne dass dies zu tun.
    • In meinem Code, ich den Fehler erfassen hier in meinem CScriptErrorCapturer.
    • Zurück S_OK. Wiederkehrende hier E_FAIL wird das gesamte Skript läuft, und nicht zulassen, dass die Ausnahme abbrechen zurückgeworfen bis zur ursprünglichen Berufung Skript werden.
  3. Anruf IDispatchEx :: InvokeEx und übergeben Sie Ihre CScriptErrorCapturer als IServiceProvider Parameter.
  4. Nach der Rückkehr von InvokeEx Abfrage Ihrer CScriptErrorCapturer zu sehen, ob es einen Fehler gefangen. Nach Code in der GoogleWebKit , manchmal InvokeEx kann S_OK zurückgeben, auch wenn ein Fehler ausgelöst wird.
  5. Do den Rückgabewert von InvokeEx nicht berührt werden, besonders wenn es SCRIPT_E_PROPAGATE ist (0x80020102)

Hinweis: diese Link einige der undokumentierten JScript HRESULTS enthält oben beschrieben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top