PowerShell para la administración automática de Dynamics AX 2012 (PS-II)

En la primera entrega de esta serie sobre PowerShell y DevOps para Microsoft Dynamics AX 2012  hablábamos sobre los principios más básicos de PowerShell y su sintaxis. También vimos en post anteriores como PowerShell se puede usar de formas bastante creativas.

Keyboard

Esta vez vamos a ver los comandlets específicos para la administración de Microsoft Dynamics AX 2012, que podemos separar en varias familias:

Gestión de Modelos y la Model Store

Estos comandlets son muy importantes y van a ser la base de nuestra estrategia DevOps, combinada con los procesos builds automáticos que tendremos configurados en nuestro TFS, si es que los utilizamos.

La combinación de estos componentes va a permitirnos diseñar procesos que actualicen automáticamente nuestros entornos, orientando nuestros procesos hacia la integración o el despliegue continuo de nuestros entornos, especialmente entornos de desarrollo y/o pruebas. Hablaremos sobre esto en los siguientes posts de esta serie.

Estos son los que normalmente utilizamos para estas tareas, aunque vale la pena echar un vistazo a la referencia completa porque todos pueden ser útiles para tareas concretas o para scripts que automaticen tareas más completas:

Modelos

Comando Descripción
New-AXModel  Crea un nuevo modelo en la Model Store
Uninstall-AXModel  Elimina un modelo de la Model Store
Install-AXModel  Importa un modelo (desde un fichero) en la Model Store
Export-AXModel  Exporta un model de la Model Store a un fichero .axmodel
Move-AXModel  Mueve los objetos de un modelo a otro modelo, combinando todos los objetos en este último.

Unit Testing X++ code in Visual Studio (AX 2012) [EN]

I’m pretty sure everybody who has tried will agree with me that the Unit Testing framework included in the AX 2012 development environment (aka MorphX) has some limitations. Sometimes such limits become so impacting that makes the framework almost useless when the code you need to test starts growing (let’s discuss design problems in a separate post :)).

But I’m not going to talk here about limitations, but about what we actually can do, and one of such things is to use X++ proxy classes to write our unit tests in Visual Studio, and use the native testing framework included here with all its possibilities. Let’s see how it works with an easy example.

I wrote this simple X++ class in order to have something to test:

Test Unitarios de código X++ en Visual Studio (AX 2012)

Creo que todo el que lo haya intentado estará de acuerdo en que el framework para Unit Testing integrado en el propio entorno de desarrollo de Microsoft Dynamics AX 2012 (del nuevo Dynamics AX, AX 7, hablaremos otro día) es bastante limitado. Tan limitado que resulta prácticamente inutilizable en cuanto quieres probar algo más o menos serio.

Pero hoy no quiero hablar de limitaciones sino de lo que podemos hacer, y entre estas cosas está la posibilidad de utilizar classes proxy del código X++ para poder escribir las pruebas unitarias en el propio Visual Studio, y utilizar así sus posibilidades y su flexibilidad. Veamos un ejemplo sencillo.

Voy a intentar probar una clase que he hecho en X++ específicamente para esto, con este código:

Novedades Mayo 2016 en Lifecycle Services (LCS)

Microsoft Dynamics Lifecycle Services

Ya está disponible la revisión de Mayo de Microsoft Dynamics Lifecycle Services (LCS). Los cambios más importantes son sin duda las primeras funcionalidades disponibles para el manejo de diferentes versiones del nuevo Microsoft Dynamics AX, cuya primera actualización fue publicada ayer, como comentaba en este otro post:

  • Al desplegar nuevos entornos en Azure desde LCS para desarrollo o Demo, podemos elegir la versión original (RTM) o la versión de Mayo (Update 1):

Microsoft Dynamics AX RTW Update 1

  • Es posible cambiar la configuración de versión de un proyecto de implementación de cliente existente y desplegar nuevos entornos en la nueva versión.
  • La biblioteca de activos ahora permite copiar elementos directamente desde el interfaz.
  • Actualizada la hoja Excel Subscription estimator. Nuevas pestañas, nuevo cuestionario y mejores validaciones.

Puedes ver todas las notas y ejemplos de estas novedades en el siguiente enlace:

Y los cambios de la actualización anterior aquí

Microsoft Dynamics AX RTW Update 1

Parece que la primera actualización del nuevo Dynamics AX está a punto de ser anunciada. De momento ya se puede desplegar en Azure aunque todavía no se ha anunciado oficialmente, no hay documentación y no se puede descargar la máquina virtual de desarrollo, pero iré actualizando este post conforme se liberen las novedades 🙂Microsoft Dynamics AX RTW Update 1

Este primer paquete de actualización nos va a servir para conocer el plan y el funcionamiento de las actualizaciones en el nuevo sistema web, así como las herramientas que van a permitir estas actualizaciones basadas en LCS (recordemos que no hay versión on-premise por el momento).

ACTUALIZADO 25/05/2016

ACTUALIZADO 01/06/2016

[AX TIP] Errores Interop CLR y nivel de transacciones

Hace un tiempo publiqué un artículo explicando las buenas prácticas recomendadas para el manejo de excepciones CLR y cómo mostrarlas correctamente en el InfoLog de Dynamics AX. Sin embargo olvidé entonces un detalle importante que hay que tener en cuenta al capturar estas excepciones, que es el nivel de transacciones en la base de datos (TTS Level).

En el siguiente código de ejemplo, nuestro try..catch NO funcionará. Si se produce un error en el try, por ejemplo, si el método get_Content() no existe en el objeto en tiempo de ejecución, la ejecución del código terminará directamente sin mostrar nada en el InfoLog, lo que no es muy deseable.

Esto es debido a que, para poder capturar una excepción CLR, el nivel de transacciones debe ser 0. O lo que es lo mismo, no podemos capturar errores del Interop dentro de una transacción. Para que este código funcione tendremos que re-escribirlo para que el manejo de ese objeto CLR genérico se realice antes de abrir la transacción.

CLRObject       obj;


ttsBegin;  // ttsLevel + 1

info(strFmt("TTS level: %1", appl.ttsLevel())); // TTS level: 1

try
{
    obj = response.get_Content();
    if (!CLRInterop::isNull(obj))
    {
        // ...
    }
}
catch(Exception::CLRError) // Este catch nunca se ejecutará porque ttsLevel > 0
{
    error(AifUtil::getClrErrorMessage());
}

ttsCommit; // ttsLevel - 1

En realidad, y debido al alto riesgo de que se produzcan errores CLR que deben capturarse y procesarse de forma especial, el manejo de objetos CLR debe encapsularse siempre en clases o métodos específicos donde quede claro su funcionamiento y aislado el riesgo de problemas.