lunes, 29 de septiembre de 2008

Problema (y solución) al instalar .NET Framework 3.5 (IV)

Para continuar con la serie de problemas que nos están dando las instalaciones del .NET Framework 3.5, aquí tenéis otro error al instalarlo:

[XX/XX/XX,XX:XX:XX] RGB Rast: [2] Error: Installation failed for component RGB Rast. MSI returned error code 1601
[XX/XX/XX,XX:XX:XX] WapUI: [2] DepCheck indicates RGB Rast is not installed.

En el directorio temporal del usuario (%TEMP% en Inicio -> Ejecutar) encuentro varios ficheros con el nombre dd_RGB9RAST_x86.msiXXXX.txt (el final del nombre del fichero varía con un número aleatorio) en el que hay más información sobre el error:

=== Verbose logging started: XX/XX/XXXX XX:XX:XX Build type: SHIP UNICODE 3.01.4000.2435 Calling process: X:\XXXXXXXXXXXXXX\setup.exe ===
MSI (c) (2C:48) [XX:XX:XX:XXX]: Resetting cached policy values
MSI (c) (2C:48) [XX:XX:XX:XXX]: Machine policy value 'Debug' is 0
MSI (c) (2C:48) [XX:XX:XX:XXX]: ******* RunEngine:
******* Product: X:\XXXXXX\RGB9RAST_x86.msi
******* Action:
******* CommandLine: **********
MSI (c) (2C:48) [XX:XX:XX:XXX]: Client-side and UI is none or basic: Running entire install on the server.
MSI (c) (2C:48) [XX:XX:XX:XXX]: Grabbed execution mutex.
MSI (c) (2C:48) [XX:XX:XX:XXX]: No se puede conectar al servidor. Error: 0x80070005
MSI (c) (2C:48) [XX:XX:XX:XXX]: Failed to connect to server.
MSI (c) (2C:48) [XX:XX:XX:XXX]: MainEngineThread is returning 1601
=== Verbose logging stopped: XX/XX/XXXX XX:XX:XX ===

Intentamos instalar manualmente el componente RGB RAST (desde aquí podéis descargar la versión de 32 bits y la de 64 bits) pero se produce un error de Windows Installer. Comprobamos que el servicio de Windows Installer está detenido, y no permite arrancarlo dando el siguiente error:

No se puede encontrar la clave de búsqueda solicitada en ningún servicio de activación activa.

Encontramos una solución en esta página que consiste en re-registrar el servicio Windows Installer ejecutando los comandos:
- msiexec /unreg
- msiexec /regserver

Tras esto ejecutamos el instalador del componente y después el instalador del .NET Framework normalmente.

Relacionado:
Problema (y solución) al instalar .NET Framework 3.5 (I)
Problema (y solución) al instalar .NET Framework 3.5 (II)
Problema (y solución) al instalar .NET Framework 3.5 (III)

Problema (y solución) al instalar .NET Framework 3.5 (III)

Como no hay dos sin tres, os presento otro problema que nos ocurrió al instalar el .NET Framework 3.5:


[XX/XX/XX,XX:XX:XX] WIC Installer: [2] Setup Failed on component WIC Installer
[XX/XX/XX,XX:XX:XX] WapUI: [2] DepCheck indicates WIC Installer is not installed.
[XX/XX/XX,XX:XX:XX] WIC Installer: [2] Error code 1603 for this component means "Error grave durante la instalación."

Al revisar el fichero dd_WIC.txt, que está en el directorio temporal del usuario (%temp% desde Inicio -> Ejecutar), encontramos lo siguiente:

4.062: Unable to get File Version
4.062: Failed to copy spupdsvc.exe to system32
4.234: DeRegistering the Uninstall Program -> WIC, 0
4.234: WIC Setup canceled.
4.234: Update.exe extended error code = 0xf00d
4.234: Update.exe return code was masked to 0x643 for MSI custom action compliance.


La solución la encontré aquí y consiste simplemente en renombrar el fichero spupdsvc.exe (que está en el directorio System32 de la instalación de Windows) y volver a ejecutar el instalador.


Relacionado:


Problema (y solución) al instalar .NET Framework 3.5 (II)

Seguimos con los problemas que nos vamos encontrando al instalar el .NET Framework 3.5, hay que tener en cuenta que las instalaciones se realizan en una gran cantidad de equipos (más de 2.000) con diferentes versiones de Windows y con distintas políticas de administración. Si bien es cierto que la gran mayoría no dan problemas, hay algunos en los que los errores de instalación son bastantes rebuscados, como este caso:


[XX/XX/XX,XX:XX:XX] Microsoft .NET Framework 2.0a: [2] Error: Installation failed for component Microsoft .NET Framework 2.0a. MSI returned error code 1603
[XX/XX/XX,XX:XX:XX] WapUI: [2] DepCheck indicates Microsoft .NET Framework 2.0a is not installed.


Esto se debía a que los equipos tenían instalados la versión .NET Framewok 2.0 with Security Updates, que según la knowledge base de Microsoft, da problemas cuando quieres instalar cualquier otra versión del .NET Framework (http://support.microsoft.com/kb/923100/)


El problema añadido es que no permite desinstalar esta versión desde Agregar/Quitar Programas, por lo que es necesario usar una herramienta que haga una desinstalación segura (limpiando el registro y eliminando los ficheros necesarios). Para este caso encontré la .NET Framework CleanUp Utility, creada por Aaron Stebner, que se puede descargar desde este link)

Es muy sencilla de utilizar así que no me voy a detener en explicarlo, lo único que diré es que funciona muy bien y no necesita instalar nada en el equipo en que queremos ejecutarla.


Una vez desinstalado el .NET Framework 2.0 pudimos continuar con la instalación del .NET Framework 3.5 sin problemas.

Relacionado:

Problema (y solución) al instalar .NET Framework 3.5 (I)

miércoles, 3 de septiembre de 2008

Poison Messages en SQL Server Service Broker, ¿qué son y cómo evitarlos?

En varios proyectos en los que estoy trabajando estamos utilizando una característica que se introdujo en SQL Server 2005, Service Broker, SSB para los amigos. Brevemente diré que SSB proporciona una plataforma de comunicaciones basada en mensajes que forma parte del motor de base de datos, si queréis saber algo más tenéis información detallada aquí y aquí.


El caso es que cuando empezamos a hacer pruebas de nuestra aplicación nos encontramos que a veces se detenía el servicio sin motivo aparente, y buscando información nos encontramos con los poison messages.


¿Qué es un poison message?
Un poison message (traducido literalmente “mensaje envenenado”) es un mensaje en una cola que ha excedido el número máximo de intentos de ser recibido por una aplicación. Esta situación puede producirse, por ejemplo, cuando una aplicación lee un mensaje de una cola como parte de una transacción, pero debido a errores (error de conversión, duplicidad de clave,...) no puede procesarlo. Si la aplicación aborta la transacción en la que se recibió el mensaje, éste es automáticamente devuelto a la cola. Si el problema con el mensaje no es solucionado puede provocarse un bucle infinito, provocando un poison message.


Service Broker provee detección automática de poison messages que deshabilita la cola (y te aseguro que no hace ninguna gracia que te pase esto en producción) si una transacción que recibe mensajes de una cola hace rollback 5 veces. Si se llega a dar este caso, el mensaje debe ser eliminado por una aplicación diferente o por un administrador de forma manual.


La detección automática también genera un evento de tipo Broker: Queue Disabled, que puede ser interceptado por un procedimiento almacenado que reactive la cola (vuelva a establecer su STATUS a ON). Además se pueden usar las alertas de SQL Agent para notificar al administrador que la cola se ha desactivado para que actúe en consecuencia.


¿Cómo tratar los poison message?
Debido a que la detección automática de poison messages provoca la detención de la cola, y por tanto, de todos los procesos asociados a ella, las aplicaciones deberían, como parte de su lógica, detectar y sacar de las colas de forma segura los mensajes que sean susceptibles de convertirse en poison messages.


- Usar bloques TRY ... CATCH para capturar todos los errores. Comprobar si la transacción (en caso de que exista) se pueda confirmar con la función XACT_STATE().

- Cuando se detecte un error que potencialmente pueda provocar un poison message, asegurarnos de que el mensaje ha sido sacado de la cola y finalizar la conversación con END CONVERSATION ... WITH ERROR.

- También es muy recomendable guardar el mensaje que provocó el poison message para su posterior tratamiento (podemos corregirlo y volver a introducirlo en el ciclo normal) y guardarnos un log.


Un control de poison messages podría ser algo así:


BEGIN TRY
BEGIN TRANSACTION
RECEIVE
.
.
.
COMMIT TRANSACTION
END TRY

BEGIN CATCH
DECLARE @state INT;
SET @state = XACT_STATE();
SELECT @error = ERROR_NUMBER(), @error_message = ERROR_MESSAGE();

IF @state = 1 -- Hay transacción de usuario activa y se puede confirmar
BEGIN
-- Se finaliza la conversación con error
END CONVERSATION @conversation_handle
WITH ERROR = @error description = @error_message;
COMMIT;
END
ELSE IF @state = -1
-- Hay transacción de usuario activa y no se puede confirmar, sólo revertir
BEGIN
ROLLBACK TRANSACTION; -- Se revierte la transacción

-- Se saca de la cola el mensaje y se finaliza la conversación con error
BEGIN TRANSACTION;
RECEIVE TOP(1) @msgBody = message_body
FROM [queue]
WHERE conversation_handle = @conversation_handle;
END CONVERSATION @conversation_handle
WITH ERROR = @error description = @error_message;
COMMIT;
END
END CATCH




He de reconocer que no es una solución perfecta pero por ahora es lo mejor que he encontrado y funciona bastante bien. En todo caso os recomiendo el blog de Remus Rusanu para profundizar en el uso de Service Broker.



Bola extra

Por si a alguien le interesa, buscando información sobre los poison messages en Service Broker me encontré que MSMQ realiza un tratamiento parecido, tenéis más información en esta página.


Edito: (08/09/08) hasta hoy no me di cuenta que lo de Bola Extra es una copia descarada, digo ... homenaje a los camaradas de Halon disparado, si es que de lo que se come se cría :p