Esoterico JScript problema hosting: dove si trova il codice di errore quando IDispatch :: Invoke ritorna SCRIPT_E_PROPAGATE?

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

Domanda

La nostra applicazione host di Windows Scripting Host motore JScript ed espone numerosi oggetti di dominio che può essere chiamato dal codice di script.

Uno degli oggetti di dominio è un componente COM che implementa IDispatch (in realtà, IDispatchEx) e che dispone di un metodo che prende uno script-funzione come parametro di richiamo (un IDispatch * come parametro). Questo componente COM viene chiamato dallo script, fa alcune cose, e poi richiama in script tramite il parametro IDispatch fornito prima di tornare allo script chiamante.

Se lo script di call-back accade un'eccezione (ad esempio, effettua una chiamata a un altro componente COM che restituisce qualcosa di diverso da S_OK), poi la chiamata a IDispatch :: Invoke sulla sceneggiatura call-back tornerà SCRIPT_E_PROPAGATE invece del HRESULT dall'altro componente COM; Non l'HRESULT previsto dal l'altro oggetto COM. Se torno che HRESULT (SCRIPT_E_PROPAGATE) al chiamante del primo componente COM (ad esempio, per lo script di chiamata), quindi il motore di script genera correttamente un errore con il valore HRESULT previsto dal l'altro oggetto COM.

Tuttavia, il errore effettivo è introvabile. Non è restituito dalla chiamata Invoke (il valore di ritorno è SCRIPT_E_PROPAGATE). Non è restituito al EXCEPINFO alimentata Invoke (la struttura rimane vuoto). E, non è disponibile tramite GetErrorInfo (i rendimenti chiamata 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)

mi piacerebbe davvero come per mettere le mani su tale errore, perché sarebbe utile per memorizzare nella cache e ritornare lo stesso errore sulle chiamate successive (ottenendo l'errore comporta spesso un'operazione costosa che è definita dallo script-funzione passata come parametro, ma so come memorizzare nella cache l'errore). Esiste un modo per un componente COM script per arrivare a un eccezione generata durante una chiamata, di nuovo in un fornito script funzione ???

È stato utile?

Soluzione

Wow, questo è stato seriamente underdocumented.

La risposta è:

Nel componente COM fare una richiamata nello script ...

  1. QI per ottenere un IDispatchEx puntatore sulla funzione di script da chiamare.
  2. Costruire un oggetto che implementa sia IServiceProvider e ICanHandleException ; per esempio. CScriptErrorCapturer .
    • IServiceProvider :: QueryService può restituire E_NOINTERFACE
    • Se la funzione di script di callback getta, ma non cattura, un'eccezione quando InvokEx'd (vedi sotto), quindi ICanHandleException :: CanHandleException otterrà un (aspetto EXCEPINFO e VARIANT * su MSDN per documentazione ).
    • La variante conterrà l'oggetto lanciato, che potrebbe essere un Errore oggetto.
    • Cercare di ottenere la proprietà "messaggio" "numero" e dal IDispatch su questo Errore oggetto, dove "numero" rappresenta l'errore script vero (HRESULT).
    • Questi valori può / deve essere utilizzato per aggiornare l'EXCEPINFO scode e (opzionalmente) bstrDescription per propagare l'errore fino allo script chiamante. Se non si aggiorna il scode , quindi poi il motore genera un "eccezione generata ma non colto" (0x800A139E), che è ciò che l'EXCEPINFO contiene prima di modificarlo.
    • Non sono sicuro se pfnDeferredFillIn dovrebbe essere eliminato, ma funziona senza fare questo.
    • Nel mio codice, a catturare l'errore qui nel mio CScriptErrorCapturer.
    • Return S_OK. Tornando E_FAIL qui sarà interrompere l'intera esecuzione di script, e non consentono l'eccezione a essere gettato indietro fino alla script chiamante originale.
  3. Chiamata IDispatchEx :: InvokeEx e passare il vostro CScriptErrorCapturer come parametro IServiceProvider.
  4. Al ritorno dal InvokeEx, interrogare il vostro CScriptErrorCapturer per vedere se è catturato un errore. Secondo codice nella GoogleWebKit , a volte InvokeEx può restituire S_OK, anche se viene generato un errore.
  5. Non toccare il valore restituito da InvokeEx, soprattutto se si tratta SCRIPT_E_PROPAGATE (0x80020102)

Nota: questo link contiene alcune delle privi di documenti JScript HRESULTS descritto sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top