September 2010 - Artículos

image47dd1de4

Buenas,

ayer posteé un ejemplo muy básico para la creación de una tarea personalizada para MSBuild. Si eres un desarrollador, seguramente una de los primeros componentes que necesitas está relacionado con la capacidad de dejar trazas, en este caso en una Custom Task para MSBuild. Para esto tenemos a nuestra disposición la clase TaskLoggingHelper, ubicada en Microsoft.Build.Utilities.TaskLoggingHelper y que nos permite tareas como:

Como es posible ver, existen variantes para mostrar información “a pelo”, mostrar información desde un recurso, esto es muy útil para aplicaciones localizadas, a partir de un código, etc. Vamos que las opciones son muchas.

El siguiente ejemplo, muestra la capacidad para dejar trazas del tipo Error, Warning y Message, en las líneas 14, 15 y 16.

   1: using Microsoft.Build.Utilities;
   2: using Microsoft.Build.Framework;
   3: namespace ElBruno.MsBuild
   4: {
   5:     public class MySecondTask : Task
   6:     {
   7:         public string InputData { get; set; }
   8:         [Output]
   9:         public string OutputData { get; set; }
  10:         public override bool Execute()
  11:         {
  12:             bool ret = true;
  13:             OutputData = string.Format(@"{0} Input Data Procesada", InputData);
  14:             Log.LogMessage(OutputData);
  15:             Log.LogWarning(OutputData);
  16:             Log.LogError(OutputData);
  17:             return ret;
  18:         }
  19:     }
  20: }

 

Si generamos un proyecto que utilice esta nueva tarea

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          InitialTargets="Target1">
   3:   <UsingTask TaskName="ElBruno.MsBuild.MySecondTask"
   4:              AssemblyFile="c:\srcBruno\Agile01\MsBuild Tests\Sample 02\bin\Debug\ElBruno.MsBuild.dll" />
   5:   <Target Name="Target1">
   6:     <MySecondTask InputData="Valentino">
   7:       <Output TaskParameter="OutputData" PropertyName="OutputData" />
   8:     </MySecondTask>
   9:   </Target>
  10: </Project>

 

Veremos un resultado similar al siguiente

image

 

 

Saludos @ Here

El Bruno

   

image47dd1de4

Buenas,

hace un tiempo escribí un post donde comenté como crear una tarea personalizada para MSBuild que agrupe un set de strings. Pues este post es un primer paso para mostrar como crear una tarea personalizada para MSBuild, y luego iremos complicando un poquito el tema.

En primer lugar debermos crear un proyecto del tipo Class Library, y agregar las siguientes referencias:

  • Microsoft.Build.Framework
  • Microsoft.Build.Tasks.v3.5
  • Microsoft.Build.Utilities.v3.5

Luego, crearemos una clase llamada [MyFirstTask] que hereda de Task, de esta manera aprovecharemos la funcionalidad ya implementada en esta tarea de MSBuild (esta tarea está incorporada en Microsoft.Build.Utilities.dll). En este ejemplo, crearemos 2 propiedades llamadas InputData y OutputData para poder intercambiar datos con la tarea. El siguiente código muestra un ejemplo:

   1: using Microsoft.Build.Utilities;
   2: using Microsoft.Build.Framework;
   3: namespace ElBruno.MsBuild
   4: {
   5:     public class MyFirstTask : Task
   6:     {
   7:         public string InputData { get; set; }
   8:         [Output]
   9:         public string OutputData { get; set; }
  10:         public override bool Execute()
  11:         {
  12:             bool ret = true;
  13:             OutputData = string.Format(@"{0} Input Data Procesada", InputData);
  14:             return ret;
  15:         }
  16:     }
  17: }

 

Una vez compilado el proyecto, ya podemos crear un proyecto de MSBuild, donde probar la tarea. El siguiente ejemplo, muestra como importar y definir la tarea a partir de un path específico (líneas 4 y 5), y luego como invocar a la misma utilizando las propiedades de Input y output (líneas 8 y 9). Finalmente se muestra en un mensaje el dato que retorna la ejecución de la tarea (línea 11).

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          InitialTargets="Target1">
   3:   <!-- Tareas personalizada -->
   4:   <UsingTask TaskName="ElBruno.MsBuild.MyFirstTask"
   5:              AssemblyFile="c:\srcBruno\Agile01\MsBuild Tests\Sample 01\bin\Debug\ElBruno.MsBuild.dll" />
   6:   <!-- Utilizacion de la tarea en un Target -->
   7:   <Target Name="Target1">
   8:     <MyFirstTask InputData="Valentino">
   9:       <Output TaskParameter="OutputData" PropertyName="OutputData" />
  10:     </MyFirstTask>
  11:     <Message Text="El resultado es: $(OutputData)" />
  12:   </Target>
  13: </Project>

El resultado de ejecución de la tarea es el siguiente

image

En los próximos posts, un poco de material más profundo :D

 

Saludos @ Home

El Bruno

   

DISCLAIMER: No agrego mucho detalle sobre la creación del proyecto, ni explicaciones de funcionamiento, porque creo que viendo los 2 ejemplos de código; más el screenshot del resultadao mucha gente ya podrá darse una idea de como funciona. En caso contrario –> MSDN y curso de pago :D

Como siempre –> una imagen vale más que mil palabras

alt

 

Saludos @ Home

El Bruno

Fuente: http://www.smashingapps.com/2010/09/23/how-to-become-a-famous-blogger.html

Publicado 25/9/2010 21:40 por El Bruno | 1 comment(s)
Archivado en:

image

Buenas,

anoche llegué un poco tarde a la mesa redonda “Ciclo de Vida Unplugged” que organizamos con los chicos de MadridDotNet. La verdad es que era la primera vez que organizábamos un evento de este tipo, y siendo 10 o 12 personas, la verdad que, según mi punto de vista, el resultado fué bastante productivo. Como una de las lecciones aprendidas es intentar organizar las reuniones como “reuniones”, con un temario y un objetivo a tratar, dejaré algunos puntos que son los que me llamaron la atención.

  • Cuando llegué había una discusión muy buena sobre como llevar adelante proyectos, independientemente de la metodología, pero en todos los casos había una especie de capa gris en la capa de management.
  • Existe una sensación general de que los mandos de gestión de proyectos de informática no tienen la formación necesaria para llevar a cabo esta tarea.
  • Más sobre metodología, una frase que derrumba muros y que no me canso de escuchar: “si en un equipo tienes 5 cracks, no importa que metodlogía utilices, el proyecto seguramente será un éxito”.
  • Tema a discutir: sobre la base de que debes tratar a tu equipo como iguales, cómo gestionar cuando dentro de un equipo exista un crack y uno no tan crack? se debe incentivar más a uno que al otro? las diferencias son buenas?
  • Hablamos sobre trabajar con Factorías/Empresas de Software/Developers en la India, hubo experiencias buenas y malas. Eso sí, todos estamos de acuerdo que son más baratos, que todos tienen bigotito que son muy buena gente, y que muchas veces carecen de iniciativa.
  • J nos comentó como lleva adelante su equipo de 4 personas con SCRUM y cómo la experiencia es muy buena, aunque se dá cuenta de que siempre estima por debajo de la realidad. Lo bueno es que en su retrospectiva personal, ya sabe que estima por debajo :D
  • No entramos en detalle para hablar de herramientas, pero sí hicimos una lista de los mínimos para trabajar, yo propuse la siguiente: Gestor de código fuente, Gestor de compilaciones. Gestor de Bugs, Tareas, Requisitos/Escenarios/Historias de Usuario y Pizarra. No todos tenían todas las herramientas, pero todos llevaban adelante el trabajo.
  • También hablamos de la mala gestión que existe en las reuniones aquí en España. Personalmente opino que es algo cultural, ya que muchas veces las reuniones son una excusa que tienen las personas para demostrar que están trabajando; pero cuesta mucho organizar una reunión (que no debería durar más de 20 min) e intentar llevarla adelante. Un gran ejemplo –> el evento de ayer :D
  • El amigo C, que trabaja en una factoría de aviones, soltó una frase lapidaria para vender el porqué de la necesidad de las pruebas: “Sabés porqué no se caen los aviones? por todas las pruebas que les hacen a los mismos
  • ¿Porqué existe esa necesidad en muchas empresas de tener que verte para estar convencidos de que estás trabajando? V dió una respuesta demoledora sobre el problema cultural que existe detrás de todo esto, y que no permite que muchas personas trabajen desde casa.

La verdad que fueron 2 horas muy buenas, no apunté todo lo que hablamos y mucho menos las conclusiones a las que llegamos, pero si que me gustó participar en una reunión diferente donde la tecnología era lo secundario y donde las experiencias eran lo principal :D

Saludos @ Here

El Bruno

   

Publicado 24/9/2010 9:04 por El Bruno | 8 comment(s)
Archivado en: ,

image

Buenas,

hoy también toda hacer un poco de publicidad gratuita pero la verdad es que cuando trabajas con archivos grandes de MSBuild, el panel de Resharper File Structure (Ctrl + Alt +  F) es una de las mejores ayudas que puedes tener. El mismo te muestra una vista en modo árbol de un archivo .proj, en el que es posible distinguir, entre otras cosas:

  • definición de propiedades
  • definición de grupos de propiedades
  • la declaración de Imports
  • la declaración de Usings
  • los targets y los elementos internos de los mismos
  • etc …

El siguiente proyecto de ejemplo, tiene un poco de complejidad y varios elementos diferentes:

   1: <Project DefaultTargets="Inicio"
   2:          xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   3:   <UsingTask AssemblyFile="c:\srcBruno\Agile01\TfsBuild\bin\Debug\ElBruno.TfsBuild.dll"
   4:              TaskName="ElBruno.TfsBuild.StringConcatenate" />
   5:   <ItemGroup>
   6:     <Dll Include="c:\EntLib50Src\bin\*.dll" />
   7:     <Exe Include="c:\EntLib50Src\bin\*.exe" />
   8:   </ItemGroup>
   9:   <PropertyGroup>
  10:     <Nombre>Bruno</Nombre>
  11:     <Edad>34</Edad>
  12:   </PropertyGroup>
  13:   <Target Name="Inicio">
  14:     <CreateProperty Value="Nombre: $(Nombre) -> Edad: $(Edad)">
  15:       <Output TaskParameter="Value" PropertyName="NuevaPropiedad"/>
  16:     </CreateProperty>
  17:     <Message Text="$(NuevaPropiedad)" />
  18:   </Target>
  19:   <Target Name="Ejemplo">
  20:     <ElBruno.TfsBuild.StringConcatenate Items="@(Dll)"
  21:                                         Separator=";"
  22:                                         AppendLine="false">
  23:       <Output TaskParameter="StringResult" PropertyName="StringResultDll" />
  24:     </ElBruno.TfsBuild.StringConcatenate>
  25:     <ElBruno.TfsBuild.StringConcatenate Items="@(Exe)"
  26:                                         Separator=";"
  27:                                         AppendLine="false">
  28:       <Output TaskParameter="StringResult" PropertyName="StringResultExe" />
  29:     </ElBruno.TfsBuild.StringConcatenate>
  30:     <Message Text="$(StringResultDll)" />
  31:     <Message Text="=======================================" />
  32:     <Message Text="$(StringResultExe)" />
  33:   </Target>
  34: </Project>
  35:  
  36: </Project>

La vista de File Structure de este proyecto es la siguiente:

image

 

Simplemente genial !!!

 

 

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image Buenas,

con ganas de salir un poco del formato de las clásicas charlas sobre tecnología, el próximo jueves 23 de Septiembre, nos reuniremos con los amigos de MadridDotNet para hablar sobre el ciclo de vida en general.

El evento se titula “Ciclo de Vida Unplugged” y la idea es compartir experiencias e intentar llegar a algún lugar productivo entre todos:

En esta sesión, tipo mesa redonda, trataremos, entre todos de poner en claro como gestionamos el ciclo de vida de nuestras aplicaciones. El objetivo es que todos podamos aprender de todos e ir mejorando en la gestión de nuestros desarrollos. Desde el punto de ¿cómo gestionais los requisitos? ¿y el código fuente? ¿que repositorio de código usais? ¿estrategias de branching?, hasta ¿y cómo hacéis el testing? ¿y el seguimiento de los despliegues? ¿y el ciclo de vida del mantenimiento?

Los moderadores seremos Luis y el que publica el blog (porque el mono que escribe todavía no habla); y realmente esperamos pasar un buen rato con los que se apunten.

El lugar es donde siempre: las oficinas de MS en Pozuelo, y el registro oficial lo pueden hacer en: https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032462873&Culture=es-ES 

 

 

 

 

Saludos @

El Bruno (@elbruno en Twitter)

 

Homepage: http://madriddotnet.spaces.live.com/default.aspx?wa=wsignin1.0&sa=672549957

PD: la imgen que acompaña, es para que recuerdes que cada vez que:

  • no utilices algún mecanismo de control de código fuente
  • no integres frecuentemente
  • no hagas pruebas unitarias
  • etc …

estás matando un gatito !!!

Publicado 17/9/2010 14:38 por El Bruno | 2 comment(s)
Archivado en: ,,

image

Buenas,

que los chicos de JetBrains son unos cracks no es ninguna novedad, ReSharper es un excelente ejemplo de esto. Si programas con VB.Net o C# y lo utilizas, no hace falta que te explique las ventajas que te brinda y lo que te ayuda programando; personalmente yo lo tengo en la lista de las mejores extensiones para Visual Studio 2010.

Ahora bien, si tu vida no es tan agradable y te toca editar archivos de MSBuild, pues aquí también hay algunas ayudas, por parte de ReSharper que son interesantes. Por ejemplo, la capacidad de ir a declaración o definición de una propiedad.

Por ejemplo, supongamos el siguiente archivo de MSBuild. En el mismo hay 2 tipos de propiedades a tener en cuenta:

  • líneas 5 y 6, con una declaración de una propiedad
  • líneas 11 a 13, con la creación de una propiedad

Luego estas propiedades se utilizan en el Target Inicio, en varias ocasiones.

   1: <Project DefaultTargets="Inicio"
   2:          xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   3:   <!-- Grupo de Propriedades -->
   4:   <PropertyGroup>
   5:     <Nombre>Bruno</Nombre>
   6:     <Edad>34</Edad>
   7:   </PropertyGroup>
   8:   <!-- Target Inicial -->
   9:   <Target Name="Inicio">
  10:     <!-- Crea una nueva propiedad -->
  11:     <CreateProperty Value="Nombre: $(Nombre) -> Edad: $(Edad)">
  12:       <Output TaskParameter="Value" PropertyName="NuevaPropiedad"/>
  13:     </CreateProperty>
  14:     <!-- Muestra el valor de la nueva propiedad -->
  15:     <Message Text="$(NuevaPropiedad)" />
  16:   </Target>
  17: </Project>

 

Veamos que puede hacer ReSharper para ayudarnos.

Si posicionamos el cursor en la línea 11, donde se utiliza la propiedad $(Nombre) y presionamos Ctrl; podremos ver como la misma se convierte en un link:

image

 

Con un click en el mismo, obviamente iremos a la definición de la propiedad en la línea 5.

image

 

De la misma, forma si queremos acceder a la definición de la propiedad $(Nueva Propiedad), en la línea 15:

image

 

ReSharper nos llevará a la línea de la creación de la misma.

image

 

Cuando trabajas con archivos muy grandes, esto se agradece :D

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

después de casi un mes de escribir un poco de MSBuild, a continuación el listado de los posts como para ir comprendiendo un poco de que va MSBuild:

 

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

Publicado 15/9/2010 15:44 por El Bruno | con no comments

image47dd1de4

Buenas,

otra de las novedades en MSBuild 4.0, son dos nuevos targets BeforeTargets y AfterTargets. Hasta la versión 3.5 los MSBuild Targets se definen si el comienzo de un Target depende de la salida de otro Target; utilizando varios atributos para especificar el orden en el que se ejecutan los mismos:

  • Initial targets
  • Default targets
  • First target
  • Target dependencies

Ahora en MSBuild 4.0, se han agregado RunBeforeTargets y RunAfterTargets (MSBuild 4.0) que permiten definir los Targets que se ejecutarán antes y después de un determinado Target.

El siguiente ejemplo posee 3 Targets, y en el atributo de proyecto InitialTargets (línea 3) se los define en el siguiente orden:

  • Target 3
  • Target 2
  • Target 1
   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target3; Target2; Target1">
   4:   <Target Name="Target1" >
   5:     <Message Text="Target1" />
   6:   </Target>
   7:   <Target Name="Target2">
   8:     <Message Text="Target2" Importance="high" />
   9:   </Target>
  10:   <Target Name="Target3">
  11:     <Message Text="Target3" Importance="high" />
  12:   </Target>
  13: </Project>

 

Cuando ejecutamos este proyecto el output del mismo es el siguiente, donde se puede ver como se respeta el orden definido en InitialTargets:

image

 

El siguiente proyecto agrega una pequeña modificación en el Target1 (línea 4), que se define que antes de ejecutar el Target1, se ejecute el Target2.

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target3; Target2; Target1">
   4:   <Target Name="Target1" BeforeTargets="Target2" >
   5:     <Message Text="Target1" />
   6:   </Target>
   7:   <Target Name="Target2">
   8:     <Message Text="Target2" Importance="high" />
   9:   </Target>
  10:   <Target Name="Target3">
  11:     <Message Text="Target3" Importance="high" />
  12:   </Target>
  13: </Project>

 

La compilación del proyecto es la siguiente, en la que se puede ver el cambio de orden en la ejecución de los Targets:

image

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

otra de las novedades incluidas en MSBuild 4.0 son las MSBuild Property Functions. Las mismas permiten trabajar con funciones básicas de scripting para evaluar los valores de una propiedad, incluyendo tareas básicas para trabajo con Strings y otras clases de .Net Framework.

El siguiente proyecto muestra diferentes ejemplos sobre una propiedad:

  • Línea 8: el valor inicial de la propiedad
  • Línea 9: el valor de la propiedad en mayúsculas
  • Línea 10: el valor de la propiedad en minúsculas
  • Línea 11: un substring a partir del valor de la propiedad
  • Línea 12: una evaluación para verificar si la propiedad contiene una cadena

 

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target1">
   4:   <PropertyGroup>
   5:     <Nino>Valentino</Nino>
   6:   </PropertyGroup>
   7:   <Target Name="Target1">
   8:     <Message Text="Valentino: $(Nino)" />
   9:     <Message Text="Upper: $(Nino.ToUpper())" />
  10:     <Message Text="Lower: $(Nino.ToLower())" />
  11:     <Message Text="Substring: $(Nino.Substring(5,4))" />
  12:     <Message Text="Contains Nino: $(Nino.Contains('Nino'))" />
  13:   </Target>
  14: </Project>

 

El resultado de este proyecto es el siguiente:

image

 

Además es posible trabajar con fechas, variables de entorno, etc. El siguiente proyecto muestra un ejemplo, con varios de estos casos:

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target1">
   4:   <Target Name="Target1">
   5:     <Message Text="Time: $([System.DateTime]::Now.ToString('hhmmss'))" Importance="high" />
   6:     <Message Text="Environment Variables: $([System.Environment]::GetEnvironmentVariables().Count)" />
   7:     <Message Text="Processor: $([System.Environment]::GetEnvironmentVariable('PROCESSOR_IDENTIFIER'))" Importance="high" />
   8:     <Message Text="New Guid: $([System.Guid]::NewGuid().ToString())" />
   9:   </Target>
  10: </Project>

 

El resultado es el siguiente:

image

 

La referencia completa de las MSBuild Property Functions se encuentra en http://msdn.microsoft.com/en-us/library/dd633440.aspx 

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

en el post anterior comentaba sobre la capacidad de definir propiedades además de un poco de código para las Inline Tasks en MSBuild 4.0, pero claro, ahora que estamos trabajando con varias variables (definiciones en Xml, código C#, etc); pues es posible que nuestro código tenga errores. En el caso de que se disparen los mismos, el propio compilador de MSBuild, nos informará el detalle y además podremos ver el log de compilación, como si fuese un proyecto C#.

El siguiente proyecto posee un error en la línea 19, donde en el mismo falta un paréntesis para la instrucción Log.LogMessage().

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target1">
   4:   <Target Name="Target1">
   5:     <ParamSample Iteration="55"/>
   6:   </Target>
   7:   <UsingTask
   8:         TaskName="ParamSample"
   9:         TaskFactory="CodeTaskFactory"
  10:         AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
  11:     <ParameterGroup>
  12:       <Iteration ParameterType="System.Int32" />
  13:     </ParameterGroup>
  14:     <Task>
  15:       <Using Namespace="System"/>
  16:       <Code Type="Fragment" Language="cs">
  17:         <![CDATA[
  18: for(int i = 0; i < Iteration; i++)
  19:   Log.LogMessage("i: " + i.ToString();
  20: ]]>
  21:       </Code>
  22:     </Task>
  23:   </UsingTask>
  24: </Project>

Cuando ejecutamos el mismo podemos ver el siguiente output en la consola

image

Si analizamos con mas detalle el log podremos ver el siguiente mensaje

C:\srcBruno\Agile01\MsBuild Tests\InlineTasks_05.targets(5,5): error : The source file for this compilation can be found at:
"C:\Users\bruno\AppData\Local\Temp\1\MSBUILDCodeTaskFactoryGeneratedFilecd57c802-3029-4b97-819e-0f177561737c.txt"

C:\srcBruno\Agile01\MsBuild Tests\InlineTasks_05.targets(5,5): error MSB3758: An error has occurred during compliation. c:\Users\bruno\AppData\Local\Temp\1\zq
mzud02.0.cs(49,38) : error CS1026: ) expected

C:\srcBruno\Agile01\MsBuild Tests\InlineTasks_05.targets(5,5): error MSB4175: The task factory "CodeTaskFactory" could not be loaded from the assembly "C:\Win
dows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll". Object reference not set to an instance of an object.

Que traducido a errores humanos es algo así:

  • Se dispara un error en la línea 5, que es la línea de invocación a la tarea autocontenida.
  • El código C# que se ha intentado compilar está en un archivo temporal en [c:\Users\bruno\AppData\Local\Temp\1\zqmzud02.0.cs]
  • La línea del error es (49,38)
  • El error es: error CS1026: ) expected

Si editamos el archivo temporal de código fuente, que se genera para la tarea autocontenida podremos ver la estructura completa de la clase que se genera para la Inline Task:

   1: //------------------------------------------------------------------------------
   2: // <auto-generated>
   3: //     This code was generated by a tool.
   4: //     Runtime Version:4.0.30319.1
   5: //
   6: //     Changes to this file may cause incorrect behavior and will be lost if
   7: //     the code is regenerated.
   8: // </auto-generated>
   9: //------------------------------------------------------------------------------
  10:  
  11: namespace InlineCode {
  12:     using System;
  13:     using System.Collections;
  14:     using System.Collections.Generic;
  15:     using System.Text;
  16:     using System.Linq;
  17:     using System.IO;
  18:     using Microsoft.Build.Framework;
  19:     using Microsoft.Build.Utilities;
  20:     
  21:     
  22:     public class ParamSample : Microsoft.Build.Utilities.Task {
  23:         
  24:         private bool _Success = true;
  25:         
  26:         public virtual bool Success {
  27:             get {
  28:                 return _Success;
  29:             }
  30:             set {
  31:                 _Success = value;
  32:             }
  33:         }
  34:         
  35:         private int _Iteration;
  36:         
  37:         public virtual int Iteration {
  38:             get {
  39:                 return _Iteration;
  40:             }
  41:             set {
  42:                 _Iteration = value;
  43:             }
  44:         }
  45:         
  46:         public override bool Execute() {
  47:  
  48: for(int i = 0; i < Iteration; i++)
  49:   Log.LogMessage("i: " + i.ToString();
  50:  
  51:             return _Success;
  52:         }
  53:     }
  54: }

En la misma, podemos ver:

  • La definición de la propiedad Iteration entre las líneas 35 y 44
  • La función Execute() que es la contiene el código de la Inline Task, entre las líneas 46 y 52
  • La línea con el error –> 49

En este punto, ya podemos crear una Custom Task para MSBuild, probar este código, depurar, etc.

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image

Buenas,

los amigos del Grupo de Usuarios .Net de Málaga, me han invitado el próximo 30 de Septiembre a que pasemos con ellos un buen rato hablando de Microsoft Robotics. El evento es el clásico y a ver si logramos que funcionen más del 50% de las demos (es lo que tiene trabajar con hardware)

Título:

Conquistando el mundo con Microsoft Robotics

Lugar y Hora:

Salón de actos Edificio BIC Euronova, PTA (Parque Técnológico de Andalucia, Campanillas)

Día 30 de Septiembre a las 18:00

Descripción:

La última versión de Microsoft Robotics Developer Studio por fin nos acerca un poco más al ansiado objetivo de la conquista global del mundo utilizando robots. En esta charla veremos cómo podemos aprovechar esta tecnología y comenzar a programar nuestros primeros robots. Además de programación concurrente, orientación a servicios, etc.; veremos una implantación real de esta tecnología en un escenario concreto; como perseguir a tu mascota utilizando LEGO Mindstorms & Microsoft Robotics Studio, controlar un lanzamisiles USB, y todo lo que entre en la maleta.

Duración:

120 mins.

Agenda:

  • Introducción a Microsoft Robotics
  • Microsoft Robotics Simulation Engine
  • Microsoft Robotics Visual Programming Language
  • Microsoft Robotics Runtime
  • Otras opciones

Registro: https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032461365&Culture=es-ES

Evento: http://malagadnug.org/?p=21

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

en mi post anterior comentaba sobre las nuevas Inline Tasks introducidas en MSBuild 4.0. Además de poder crear y definir este tipo de tareas, es posible también definir propiedades de Input y Output para utilizarlos en la definición de la tarea. Las mismas se definen dentro del elemento <ParameterGroup /> y pueden definir características propias como por ejemplo, el tipo de dato de la propiedad, si es requerida, o si es de tipo Output.

El siguiente proyecto define un parámetro de tipo Boolean en la línea 12, y de acuerdo al valor del mismo, se muestra un Warning o un Error en la consola de Output. Cuando se invoca a la tarea (línea 5), se le pasa el valor correspondiente:

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target1">
   4:   <Target Name="Target1">
   5:     <ParamSample DisplayWarning="false" />
   6:   </Target>
   7:   <UsingTask
   8:         TaskName="ParamSample"
   9:         TaskFactory="CodeTaskFactory"
  10:         AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
  11:     <ParameterGroup>
  12:       <DisplayWarning ParameterType="System.Boolean" Required="true"  />
  13:     </ParameterGroup>
  14:     <Task>
  15:       <Using Namespace="System"/>
  16:       <Code Type="Fragment" Language="cs">
  17:         <![CDATA[
  18: if(DisplayWarning)
  19:   {Log.LogWarning("Hola Valentino!");}
  20: else
  21:  {Log.LogError("Hola Martina!");}
  22: ]]>
  23:       </Code>
  24:     </Task>
  25:   </UsingTask>
  26: </Project>

Este es el resultado con el parámetro en FALSE:

image

Y este es el resultado con el parámetro en TRUE:

image

 

Como además la propiedad es requerida, si no se le pasa un valor a la misma, pues tendremos un error similar al siguiente:

image

 

El siguiente proyecto es similar, pero en el mismo se define una propiedad del tipo Int32 y con el valor de la misma se recorre un bucle FOR, y se muestra un mensaje muy pobre:

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target1">
   4:   <Target Name="Target1">
   5:     <ParamSample Iteration="55"/>
   6:   </Target>
   7:   <UsingTask
   8:         TaskName="ParamSample"
   9:         TaskFactory="CodeTaskFactory"
  10:         AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
  11:     <ParameterGroup>
  12:       <Iteration ParameterType="System.Int32" />
  13:     </ParameterGroup>
  14:     <Task>
  15:       <Using Namespace="System"/>
  16:       <Code Type="Fragment" Language="cs">
  17:         <![CDATA[
  18: for(int i = 0; i < Iteration; i++)
  19:   Log.LogMessage("i: " + i.ToString());
  20: ]]>
  21:       </Code>
  22:     </Task>
  23:   </UsingTask>
  24: </Project>

El resultado es el siguiente:

image

 

Saludos @ Home

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

una de las novedades más interesantes y más peligrosas que se incorporan en MSBuild 4.0, es la capacidad de trabajar con tareas autocontenidas (Inline Tasks). El listado completo de novedades se puede encontrar aquí, pero lo mejor de esta novedad es que para tareas simples, ya no será necesario crear un ensamblado .Net que implemente la interfaz ITask, e integrar el mismo en el proceso de Build. Para definir una Inline Task, se utiliza el elemento UsingTask, y dentro del mismo, se define la implementación de la tarea.

El siguiente proyecto, muestra un ejemplo de una tarea autocontenida. Dentro del mismo:

  • El proyecto especifica explícitamente que la versión es 4.0 (línea 2)
  • Trabajo con un único MSBuild Target inicial donde se invoca a una tarea llamada DisplayTinos (línea 5)
  • La definición de la tarea DisplayTino se realiza entre las líneas 7 y 22, utilizando UsingTask.
  • En la línea 8 se define el nombre de la tarea
  • La definición de la tarea, incluyendo el lenguaje, los usings, y el código de la misma; se realiza entre las líneas 12 y 21
   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   2:          ToolsVersion="4.0" 
   3:          InitialTargets="Target1">
   4:   <Target Name="Target1">
   5:     <DisplayTinos />
   6:   </Target>
   7:   <UsingTask
   8:         TaskName="DisplayTinos"
   9:         TaskFactory="CodeTaskFactory"
  10:         AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
  11:     <ParameterGroup />
  12:     <Task>
  13:       <Using Namespace="System"/>
  14:       <Using Namespace="System.IO"/>
  15:       <Code Type="Fragment" Language="cs">
  16:         <![CDATA[
  17: Log.LogMessage("Hola Valentino!");
  18: Log.LogMessage("Hola Martina!");
  19: ]]>
  20:       </Code>
  21:     </Task>
  22:   </UsingTask>
  23: </Project>

 

El resultado de ejecución del proyecto es el siguiente, donde es posible ver los logs con los nombres de los Tinos en la consola.

image

 

Para demostrar la flexibilidad que nos brinda el trabajo con Tareas autocontenidos, podemos modificar el código para que en lugar de mostrar dos mensajes con los nombres del Valentino y la Martina, nos muestre un Warning y un Error (líneas 17 y 18):

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   2:          ToolsVersion="4.0"
   3:          InitialTargets="Target1">
   4:   <Target Name="Target1">
   5:     <DisplayTinos />
   6:   </Target>
   7:   <UsingTask
   8:         TaskName="DisplayTinos"
   9:         TaskFactory="CodeTaskFactory"
  10:         AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
  11:     <ParameterGroup />
  12:     <Task>
  13:       <Using Namespace="System"/>
  14:       <Using Namespace="System.IO"/>
  15:       <Code Type="Fragment" Language="cs">
  16:         <![CDATA[
  17: Log.LogWarning("Hola Valentino!");
  18: Log.LogError("Hola Martina!");
  19: ]]>
  20:       </Code>
  21:     </Task>
  22:   </UsingTask>
  23: </Project>

 

El resultado de la compilación del proyecto con la muestra del Warning y el Error es el siguiente, donde además es posible información adicional, como por ejemplo el número de línea donde se lanza el Warning o el Error.

image

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image

Buenas,

los amigos de Visual Studio ALM Rangers han liberado una nueva versión de las herramientas de integración para Team Foundation Server. Esta versión soluciona muchos errores de la versión anterior y en la misma podemos encontrar:

  • Adaptador de integración para Team Foundation Server 2010
  • Adaptador de integración para Team Foundation Server 2008
  • Adaptador de integración para Rational ClearCase
  • Adaptador de integración para Rational ClearQuest
  • Adaptador de integración para sistema de archivos 
  • Documentación, guía y casos de estudio actualizados a la última versión
  • Nueva interfaz de usuario para configurar y ejecutar las integraciones
  • Herramientas de monitorización e informes

Descarga: http://visualstudiogallery.msdn.microsoft.com/en-us/5a8d1703-7987-4081-ba2f-9d0b68b0ed3e

Fuente: http://blogs.msdn.com/b/dannawi/archive/2010/09/06/team-foundation-server-integration-tools-august-2010-release.aspx

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

una de las prácticas más impopulares que existen en en mundo de VSTS/VS ALM, es la de modificar las plantillas de proceso para Team Foundation Server. Esto lo comento, porque siempre recomiendo pensar seriamente antes de realizar acciones tan “simple” como agregar un campo a la definición de un WorkItem. Si bien es cierto que hay muchos casos donde es necesario modificar la plantilla, por lo general esto sucede porque queremos acercar la forma de trabajo que conocemos a la que proponen las plantillas para TFS. Es decir, en lugar de estudiar e intentar aprender a trabajar bajo una nueva guidance, pues solemos llevar los errores conocidos a las plantillas.

En mi corta experiencia he visto, por ejemplo:

  • como la definición de un Bug de MSF for Agile contenía más de 150 campos, que obviamente fueron una idea genial para el bug, pero no los completaba nadie al momento de reportar un Bug.
  • como se modificaron las plantillas de la guía de proceso, a medias, dejando una guía de procesos inútil, de la que mejor era escaparse.
  • etc.

Es por esto, que recomiendo, como siempre en nuestra profesión, adaptar las metodologías y las plantillas para TFS en base a pequeñas iteraciones de prueba. Luego de cada iteración, podremos ver si los WITs son adecuados para nuestra forma de trabajo, si invertimos tiempo en modificar la plantilla, o mejor aún en educar al equipo de trabajo, etc.

Si aún así, si todavía te quedan ganas de modificar las plantillas y en especial las Process Guidance, pues ahora las puedes descargar desde:

gracias al trabajo de Allen Clark.

 

Saludos @ Home

El Bruno (@elbruno en Twitter)

image

Buenas,

que los hábitos de las sociedades de consumo están cambiando no es ninguna novedad. Uno de los detalles más interesanes es que cada vez pasamos más tiempo frente al ordenador y menos frente al televisor. Hace unos días, me llamó la atención una frase en twitter donde un usuario comentaba algo similar a

#neox es como internet, pero con publicidad

Realmente es interesante ver como la gente deja de ver series por los canales tradicionales de televisión para tener a su disposición las mismas en internet. De esta manera, es posible elegir el momento para verlas y evitarse la publicidad, entre otras cosas.

Pero claro, lo que no entra por un lado, terminará entrando por otro. Porque ahora que dejamos de pasar tiempo frente al televisor, lo empezamos a “invertir” frente a aplicaciones sociales como Facebook o Twitter. Este cambio de hábito, ha obligado a las agencias de publicidad a aprovechar estos nuevos canales, pero algunas han ido más allá (lamentablemente pocas por ahora) y además aprovechan las capacidades de estas nuevas herramientas.

Un ejemplo es Tipp-Ex, que ha colgado un video donde podemos ver a un cazador que se encuentra con un oso y el video nos presenta 2 opciones: Disparar al oso o No Disparar al oso. Hasta aquí es una novedad más, pero lo interesante es que al poco tiempo, aparece una 3ra opción (ya más relacionada con el producto en sí), que nos permite borrar el título del video y nos da la posibilidad de elegir "qué hacer” con el oso.

Video

Nota: Tipp-Ex es un corrector líquido de tinta muy famoso.

Este ejemplo es muy útil sobre como aprovechar estas medios para la publicidad ya que cumple con varios criterios:

  • El video es muy creativo
  • Demuestra las capacidades del producto de una forma innovadora
  • Es de “digestión rápida”, solo 30 segundos
  • Aprovecha las capacidades Sociales 2.0 ^^

Donde el último punto es el que más me ha llamado la atención, y seguramente sin darme cuenta comenzaré a interactuar con este nuevo tipo de publicidades, en los nuevos medios donde nos empezamos a mover.

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

Publicado 3/9/2010 13:55 por El Bruno | 3 comment(s)
Archivado en: ,

image47dd1de4

Buenas,

en un par de post anteriores a este, escribí sobre la forma de trabajar con grupos de elementos en MSBuild. Cuando los grupos de elementos con los que trabajamos son grupos archivos, podemos acceder a información adicional que nos permite ver datos como la extensión de los archivos, la fecha de modificación, etc. El detalle completo de la metadata disponible se puede consultar aquí.

El siguiente proyecto de ejemplo, define un ItemGroup con una colección de elementos llamados <EntLib50Src> en la que se incluyen todos los archivos con extensión .bat que se almacenan en el directorio de Sources de Enterprise Library 5.0. Luego, en el MSBuild Target principal del proyecto, se muestra información adicional para los items, como por ejemplo el path de cada uno, el directorio raíz, el nombre de los archivos, etc.

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   2:          InitialsTargets="Target1">
   3:   <ItemGroup>
   4:     <EntLib50Src Include="c:\EntLib50Src\**\*.bat" />
   5:   </ItemGroup>
   6:   <Target Name="Target1">
   7:     <Message Text="Fullpath: %(EntLib50Src.FullPath)"/>
   8:     <Message Text="RootDir: %(EntLib50Src.RootDir)"/>
   9:     <Message Text="FileName: %(EntLib50Src.FileName)"/>
  10:     <Message Text="RelativeDir: %(EntLib50Src.RelativeDir)"/>
  11:   </Target>
  12: </Project>

 

El resultado de la  ejecución del proyecto es el siguiente, donde se puede ver como sólo se trabaja con los 8 archivos .bat que se distribuyen con el código fuente de EntLib.

image

 

 

 

Si cambiamos el proyecto para trabajar con clases de C#, archivos con extensión .cs:

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   2:          InitialsTargets="Target1">
   3:   <ItemGroup>
   4:     <EntLib50Src Include="c:\EntLib50Src\**\*.cs" />
   5:   </ItemGroup>
   6:   <Target Name="Target1">
   7:     <Message Text="Fullpath: %(EntLib50Src.FullPath)"/>
   8:     <Message Text="RootDir: %(EntLib50Src.RootDir)"/>
   9:     <Message Text="FileName: %(EntLib50Src.FileName)"/>
  10:     <Message Text="RelativeDir: %(EntLib50Src.RelativeDir)"/>
  11:   </Target>
  12: </Project>

Podemos ver que el tiempo de ejecución del proyecto ha subido de menos de 1 segundo, a casi 7 segundos y que la información  es mucho más completa.

image

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

image47dd1de4

Buenas,

el amigo Michael Perfetti ha actualizado su control para WorkItems para TFS2010. Este WorkItem custom control muestra información histórica de un control en formato gráfico y la verdad es que es muy fácil de utilizar y se agradece la funcionalidad del mismo.

Una vez instalado el WorkItem Custom Control, es posible modificar la definición de un WorkItem y agregar este control, como muestra la siguiente imagen.

WorkflowControl_In_Layout.png

A partir de este momento, cuando visualicemos o editemos un WorkItem podremos ver en el nuevo control diferentes aspectos de la historia del WorkItem, tanto en la vista de Visual Studio como en la vista WebAccess

Visual Studio 2010 View

image 

WebAccess View

image

 

Además posee diferentes opciones de agrupamiento:

Activity

image

Assigned To

image

Changed By

image

Integration Build (this one Rocks !!!!)

image

Iteration Path

image

Priority

image

En excelente control tanto para TFS2010, como para TFS2008.

 

 

 

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

Homepage: http://tfsworkflowcontrol.codeplex.com

Publicado 2/9/2010 19:38 por El Bruno | con no comments

image47dd1de4

Buenas,

ayer fue el turno de las condiciones, asi que es natural que el siguiente post esté relacionado con los CASE/Switch o MSBuild Conditional Constructs, como se definen en MSDN. Este elemento nos permite armar sentencias de selección utilizando:

Como lo mejor es leer un poco de código para comprenderlo, vamos con un proyecto de ejemplo. El siguiente proyecto define una propiedad $(Nino) (línea 3 a 5), que luego es utilizada dentro de un bloque <Choose> para actuar en consecuencia del valor de la misma. Utilizando un evaluador <When> (líneas 7 a 11), se compara el valor de la propiedad y además para el caso de que no coincida, se utiliza además la sentencia <Otherwise> (líneas 12 a 16).

En ambos casos se define un valor para la propiedad $(Msg) que luego se muestra en el MSBuild Target inicial del proyecto.

 

   1: <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   2:          InitialsTargets="Target1">
   3:   <PropertyGroup>
   4:     <Nino>Martina</Nino>
   5:   </PropertyGroup>
   6:   <Choose>
   7:     <When Condition="'$(Nino)'=='Valentino'">
   8:       <PropertyGroup>
   9:         <Msg>Nino == Valentino</Msg>
  10:       </PropertyGroup>
  11:     </When>
  12:     <Otherwise>
  13:       <PropertyGroup>
  14:         <Msg>OtherWise -> Nino != Valentino</Msg>
  15:       </PropertyGroup>
  16:     </Otherwise>
  17:   </Choose>
  18:   <Target Name="Target1">
  19:     <Message Text="$(Msg)"/>
  20:   </Target>
  21: </Project>

El resultado es el siguiente:

image

Si defino otro valor para la propiedad $(Nino), por ejemplo por línea de comandos

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC>msbuild "C:\srcBruno\Agile01\MsBuild Tests\Case_1.targets" /property:Nino=Valentino

El resultado es el siguiente:

image

 

 

 

 

Saludos @ Here

El Bruno (@elbruno en Twitter)

Más artículos Página siguiente >