¿Cómo puedo devolver tanto una cadena de error y el código de error para VB6 de un control ActiveX ATL?

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

Pregunta

Estoy tratando de devolver un error detallado a VB6 utilizando CComCoClass :: error , pero parece que sólo puedo devolver un código de error / o / un mensaje -. pero no ambos

return Error(_T("Not connected"), __uuidof(IMyInterface), HRESULT_FROM_WIN32(ERROR_CONNECTION_INVALID));

resultados en un genérico "Método 'Solicitud' de 'IMyInterface' objeto" mensaje de error en Err.Description en el lado VB6 (pero ERROR_CONNECTION_INVALID en Err.Number), mientras

return Error(_T("Not connected"));

resultados en el mensaje de error apropiado, pero un código de error genérico en Err.Number. ¿Cómo puedo obtener lo mejor de ambos mundos?

¿Fue útil?

Solución

No se puede, esto parece ser por diseño. Detalles más adelante, pero en definitiva tiene tres opciones:

  • Vuelta ningún mensaje y un error COM amable VB, es decir, uno bien conocido por el tiempo de ejecución VB según esta artículo KB ; el tiempo de ejecución de VB se traducirá este 'error COM' a un error VB además de mensajes.
  • devolverá un mensaje de error y DISP_E_EXCEPTION; el tiempo de ejecución de VB pasará a través de este 'Error del servidor' y su mensaje de error personalizado. Esto es lo que está sucediendo de forma implícita en su segundo ejemplo, véase más abajo para más detalles.
  • Vuelta ningún mensaje y cualquier otro error COM, es decir, uno no conocido por el tiempo de ejecución VB; el tiempo de ejecución de VB recurrirá a la HRESULT prima más el mensaje genérico "Method '~' of object '~' failed".
    • Tenga en cuenta que este comportamiento en tiempo de ejecución también se aplica, si lo hace suministrar un mensaje de error aquí, es decir, su mensaje simplemente será ignorado! Esto es lo que está sucediendo en su primer ejemplo, véase más abajo para más detalles.

Para la tarea se reduce a dos opciones:

  • Si desea proporcionar contextualmente correctos '' errores COM para clientes de automatización como VB (y probablemente debería) debe omitir los mensajes de error personalizados.
  • Si desea proporcionar mensajes de error personalizados para los "errores del servidor (es decir, una condiciones de error personalizados en cuanto a la funcionalidad dentro de el servidor de automatización) su única opción es DISP_E_EXCEPTION.

Detalles

El tiempo de ejecución de VB parece ofrecer un manejo muy restringida solamente en lo que se refiere a los errores COM. Esto es probablemente por razones históricas y / o técnicos adaptados a la forma de VB se ha aplicado y no de particular interés aquí (palabras clave serían IDispatch única vs interfaz dual y ActiveX como un 'subconjunto' de COM).

Si bien no he podido salir a la superficie una especificación explícita para el comportamiento descrito anteriormente es posible comprenderla de excavación a través de otras fuentes:

Desde el artículo KB justadreamer ya se ha señalado :

  

[...] se hace una llamada a la   GetErrorInfo método para recuperar la   información de error disponible. los   tiempo de ejecución determina entonces si   bstrDescription tiene un valor distinto   NULO. Si el tiempo de ejecución encuentra un valor   distinto de NULL, [...], el HRESULT prima   valor se utiliza en este escenario. Si el   tiempo de ejecución encuentra un valor NULL, [...]   Visual Basic utiliza entonces HRESULT   para buscar el correspondiente Visual   error básico.

Esto explica el comportamiento en relación con su puño ejemplo: usted hizo suministrar un mensaje de error, por lo tanto, el tiempo de ejecución simplemente recurre a su mensaje genérico "HRESULT", además de su CComCoClass::Error

.

El comportamiento de su segundo ejemplo también es consistente vez que nos fijamos en la definición del constructor (primera lista) para <=> : tiene valores predeterminados para los parámetros no especificados, especialmente 'hRes = 0'. La sección 'Observaciones' afirma además que "Si hRes es cero, entonces los primeros cuatro versiones de DISP_E_EXCEPTION de retorno de error.". En consecuencia esto desencadena implícitamente el 'error de servidor' pasar a través de comportamiento.

Por último, para una muestra de C ++ concreta implementación de un VB como el comportamiento de los clientes de automatización ver por ejemplo los párrafos 'El manejo de errores' y la 'Ejercicio 5' siguiente en Automatización de Microsoft Office 97 y Microsoft Office 2000 .

Otros consejos

Derivar la clase que implementa la interfaz COM-expuesta desde ISupportErrorInfoImpl, llame SetErrorInfo para establecer la explicación detallada del error si se presenta alguna. No se olvide de incluir en el ISupportErrorInfo COM_MAP de su clase.

Estoy luchando con esto ahora también. Hasta ahora mi excavación indica que el código de error es realmente el valor HRESULT. VB6 trata de ser inteligente e interpretar el HRESULT pero parece tener una lista bastante limitado de HRESULT se entiende. Para el HRESULT VB6 no está familiarizado con, simplemente pone el HRESULT en la propiedad Err.Number y espera que el desarrollador es lo suficientemente inteligente como para saber qué hacer con él.

Lo más cerca que he llegado a devolver un número de error es mediante el uso MAKE_SCODE para generar un HRESULT con el campo de código de la HRESULT ajustado a lo que yo quiero, establece el indicador de gravedad y lo que espero es la instalación correcta.

Esto en conjunto con CreateErrorInfo y SetErrorInfo me traiga un código de error y una descripción del error en VB6. Y eso nos lleva de nuevo a VB6 tratando de ser inteligente con una lista limitada de errores.

http://support.microsoft.com/kb/827994 . Por lo que su objeto debe implementar el método ISupportsErrorInfo :: InterfaceSupportsErrorInfo () que devuelve S OK. y luego, antes de regresar se debe llamar SetErrorInfo con un puntero a un objeto COM que implementa IErrorInfo :: GetDescription (). Hay un ejemplo aquí: http://msdn.microsoft.com/en-us/library/ms221409. aspx .

Si SetErrorInfo antes de vuelta, VB consultará el método GetDescription del puntero de objeto que pasó a SetErrorInfo.

No soy demasiado profundo en el código atribuido que está utilizando - yo preferiría para probarlo mediante COM más crudo que seguramente es siempre una gran cantidad de código repetitivo - pero al menos funciona, entonces se podría usar envolturas sofisticados en lugar de a él.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top