Tengo un programa .NET que interactúa con un objeto mshtml de otro proceso. Escribí un pequeño proyecto de muestra desde cero para ilustrar el problema. En este ejemplo, uso directamente una referencia COM para la interoperabilidad de mshtml.
HTMLDocument document = Document; IHTMLElement activeElement = document.activeElement; Log.Verbose(activeElement.tagName); bool isHtmlFrameElement = activeElement is HTMLFrameElement; Log.Verbose("active Element is " + (isHtmlFrameElement ? "" : "NOT ") + "a frame element");Hago referencia a un mshtml personalizado, generado con la siguiente llamada:
tlbimp c:\Windows\System32\mshtml.tlb /out:c:\tmp\Interop.mshtml.dllEn mi máquina de desarrollo (donde está instalado Office), obtengo este registro, que es el comportamiento esperado:
INPUT active Element is NOT a frame elementPero en una máquina desnuda , donde no está instalada ninguna oficina (y ninguna interoperabilidad de mshtml), obtengo el siguiente registro:
INPUT active Element is a frame element Por supuesto, no es un HTMLFrameElement y cualquier acceso a uno de sus miembros provoca una excepción de miembro no encontrado .
¿Por qué COM permite esta conversión no válida en el segundo escenario? ¿Puedo trabajar con mi interoperabilidad (en el directorio de compilación) o tengo que instalarlo en GAC (como lo hace MS Office)?
La conversión no falla porque el objeto devuelto es NULL. Los detalles se explican aquí
En breve, dice que no hay excepciones mientras se lanza incorrectamente. Para ser honesto, trabajar con objetos COM no es lo más fácil. En primer lugar, dll debe registrarse correctamente, en segundo lugar, los objetos deben describirse correctamente.
HTMLFrameElement de HTMLFrameElement es una coclase COM generada por .NET. En realidad y para abreviar, esto no existe más allá de herramientas (como tlbimp, etc.). Por lo general, solo usamos su GUID (el CLSID) para poder "cocrearlo".
Esta coclase declara que implementa DispHTMLFrameElement , que es un dispinterface . Nuevamente, estos son más metadatos para herramientas, no tienen un uso real en su caso. Puede verlo declarado en mshtml.h de Windows SDK:
EXTERN_C const IID DIID_DispHTMLFrameElement;
#si está definido(__cplusplus) && !definido(INTERFAZ)
MIDL_INTERFACE("3050f513-98b5-11cf-bb82-00aa00bdce0b") DispHTMLFrameElement : public IDispatch { };#else /* interfaz de estilo C */
Entonces, .NET crea algunas clases sofisticadas sobre estas, pero no deben usarse para detectar el soporte de interfaces COM en su caso. Por qué el comportamiento es diferente según el contexto solo significa que la implementación de estas clases varía.
En su caso, debe consultar con IHTMLFrameElement que también se define en MsHTML.h:
EXTERN_C const IID IID_IHTMLFrameElement;
#si está definido(__cplusplus) && !definido(INTERFAZ)
MIDL_INTERFACE("3050f313-98b5-11cf-bb82-00aa00bdce0b") IHTMLFrameElement : public IDispatch { public: virtual /* [id][propput] */ HRESULT STDMETHODCALLTYPE put_borderColor( /* [in] */ VARIANT v) = 0; virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_borderColor( /* [out][retval] */ __RPC__out VARIANT *p) = 0; };#else /* interfaz de estilo C */
Tenga en cuenta que el IID es similar pero, de hecho, diferente y probar con este es realmente lo que quiere hacer:
bool isHtmlFrameElement = activeElement is IHTMLFrameElement;