viernes, 3 de mayo de 2013

Mesa redonda "Cómo mejorar nuestras capacidades de comunicación", Abril 2013.

Ha pasado casi un mes desde la celebración de este evento, mi primer evento como organizador y promotor, y no había tenido tiempo para dejar reposar lo aprendido y poder hacer una crónica sobre lo ocurrido.

Primero, y antes que nada, darles las gracias a David Salgado y Vanesa Pizarro por apuntarse como ponentes a la primera. Gastar un sábado por la mañana y de forma totalmente altruista, merece mucho más que un fuerte aplauso.

A continuación, y no por ello menos agradecido, un gran gracias a Pablo Carballude que consiguió la sala en las instalaciones en Microsoft, el parking, y que ejerció de anfitrión para los que fuimos al evento.

Por último, agradecer mucho a los asistentes: Bruno Capuano, Victor González, Juan María Laó Ramos – que se vino desde Sevilla -, Roberto Luis Bisbé y el presente que escribe estas líneas (a mí mismo no me agradezco, que queda mal).

WP_20130406_001

La charla la inició Salgado, que no solamente fue interesantísima si no que se pudo alargar en el tiempo hasta quedar saciados de sabiduría por parte de uno de los mejores speakers del panorama técnico en España.

En mi caso me ha causado una epifanía que me ha llevado a plantearme que ciertamente quiero mejorar mi capacidad de compartir mis conocimientos y experiencias en público.

Una hora y media después arranco Vanesa, Community Manager profesional, que nos explicó de forma sencilla las técnicas que ayudarán a nuestros post a obtener un SEO lo más positivo posible. Incluyendo una plantilla que en Weblog SL, donde escribo, la utilizamos; pero que ella me ha dado buenas ideas que he puesto en acción y mejoran aún más la posición y visibilidad de mis artículos.

Por último, y en los últimos quince minutos, nos plantamos delante de Pablo, como coordinador y responsable del programa de Technical Rangers, y le planteamos varias dudas que nos estaban reconcomiendo desde hace tiempo.

La conclusión ha sido sencilla, a pesar de lo que parece, Microsoft no va a cerrar el programa.

El programa va a recibir un potente impulso en los próximos trimestres una vez que MS relaje la presión sobre Windows 8.

Se va a realizar una criba en el programa para que nos quedemos los que se adhieran a la Visión del programa: difundir el ecosistema de Microsoft desde un punto de vista técnico. Y así darles más valor a los miembros del programa, y que ser Technical Rangers no sea un mero “título” sin sentido, si no el reconocimiento de un buen trabajo.

Por último recibimos la buena noticia de que Devify.es no será el único sitio de reporte, que Pablo y David han reconocido que es muy incómodo y poco funcional. Y que están trabajando en una forma automatizada de obtener el ranking de cada TR y su aportación.

Mientras ha pasado un mes y el programa ha vuelto al “limbo”, por lo cual este es el artículo que marca el regreso a mi empuje personal (porque me da la gana y me apetece) del programa y que se plasmará en unos pocos días en otra Acción en Conjunto.

WP_20130406_002

Si eres un Technical Ranger, y estás leyendo estas líneas... ponte las pilas (si te apetece, claro).

martes, 26 de marzo de 2013

Excel Reader, una excelente dll para manejar ficheros Excel xls

Estoy metido en una aplicación que importa datos desde una Excel, los desmenuza y los inserta/actualiza en una base de datos SQL.

Como ya me he encontrado anteriormente con el dolor de trabajar con las Interop, me puse a buscar algo más sencillo y me encontré con un proyecto en Code Project de Liu Junfeng, del 2009.

Así de una forma mucho más sencilla puedo leer de libro que quiera, la fila y la celda oportuna.

Y no pongo un ejemplo, porque en la propia página vas a tener uno tan sencillo como el que estoy utilizando yo, y que cubre las necesidades de mi proyecto.

Espero que sea tan útil como lo ha sido para mí.

viernes, 22 de marzo de 2013

XAML, ajustar el tamaño de la página durante el diseño

Este es uno de esos inconveniente que se producen cuando se está aprendiendo y aún se es bastante ignorante sobre la tecnología que utilizo.

Trabajando en Visual Studio 2012, para una preciosa aplicación WPF con XAML, me encuentro que el compañero que ha realizado el diseño del interfaz ha bindeado el alto y ancho de las páginas.

Esto está muy bien para que se ajuste el tamaño a todo tipo de pantalla o dispositivo, pero tiene el inconveniente de que tiene dos efecto secundarios muy molestos:

1. El diseñador de Visual Studio le pone un ancho y alto prácticamente infinito y no hay forma de manipular de forma interactiva las pantallas.

2. Al estar calculando constantemente el inabarcable tamaño, cualquier actuación en el diseñador se hace con una lentitud insoportable.

¿Cual es la solución? Utilizar el tamaño en diseño.

Es decir, le indico al contenedor principal, en este caso una Page, que quiero que durante el diseño el tamaño de la misma sea lo suficientemente pequeño para ser editable. Y esto lo hago con las siguientes 4 líneas en el XAML que he separado con un salto de línea:

<Page x:Class="TSA_KMSPanel.View.ImportacionKMS"
     
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     
     
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     
mc:Ignorable="d"
     
d:DesignWidth="600"
     
d:DesignHeight="800"
   
     
Title="Gestion Listado Estatus"
     
Name="PageGestionListadoEstatus"
     
FontSize="14">

  • Primero hago la referencia al esquema xml de Blend en su versión 2008.
  • A continuación le digo que el prefijo del esquema “d” sea ignorado por el compilador. Si no haces esto VS2012 te avisa que no encuentra lo siguiente en el esquema y no te deja continuar, aunque en la realidad funciona perfectamente.
  • Le añado dos propiedades del esquema “d” que indican el ancho y alto de la página durante el diseño

Y con esto no solamente ahora puedo diseñar de forma visual mi pantalla, si no que la velocidad de manipulación ahora es más que aceptable.

lunes, 25 de febrero de 2013

Exportar un StreamWriter a texto con acentos y ñ

Manda narices que a estas alturas y con los lustros de picar código que llevo aún me pegue con los acentos y letras como la ñ al ir a exportar datos de la pantalla a un fichero de texto.

Así tengo un StreamWriter que bebe de un Grid, y que quiero guardar todos sus datos como un CSV (fichero de texto separados los valores por punto y coma, para ser abierto directamente dese una Excel).

Me volví loco intentando codificar directamente los valores que estaba añadiendo al StreamWriter, cuando lo que realmente hay que hacer es codificar el objeto stream en sí mismo.

Primero voy a poner la solución y luego, por si le valiera a alguien, el ejemplo completo de exportar el contenido de un objeto DataGrid de WPF a un fichero csv que se pueda abrir desde Excel.

var sw = new StreamWriter(rutaFichero, false, Encoding.UTF8);

Y con esto consigo que los acentos y la letra ñ me salgan perfecto en Excel.

Ahora el código completo:

public void Exportar_a_csv(DataGrid pDgHistorial)
        {
           
if (pDgHistorial.IsNotNull())
            {
                var sw = new StreamWriter(rutaFichero, false, Encoding.UTF8);
               
var separador = ";";

                foreach (DataGridColumn columna in pDgHistorial.Columns)
                {
                    sw.Write(columna.Header);
                    sw.Write(separador);
                }
                sw.Write(sw.NewLine);


               
foreach (var registro in pDgHistorial.Items)
                {
                   
var historial = (ClaseAlmacenadaEnElGrid)registro;
                    sw.Write(historial.PrimerCampo
));
                    sw.Write(separador);
                    sw.Write(historial.SegundoCampo);
                    sw.Write(sw.NewLine);
                }
                sw.Flush();
                sw.Close();
            }
        }

Y ahora explico dos cosas que tienes que tener muy en cuenta:

  • El objeto de WPF DataGrid, te almacena objetos tipados. A diferencia del GridView de asp.net. Así lo que recupero son una colección de objetos de una clase específica que he tenido que definir en el momento de la carga de datos en el control. En este caso ClaseAlmacenadaEnElGrid.
  • El parámetro RutaDelFichero, puede ser un string o, lo ideal, que lo recuperes del app.config de la aplicación.

Espero que resulte útil.

ConfigurationSettings.AppSettings está obsoleto

Pequeña tontería que quiero compartir.

Un compañero en una aplicación ha utilizado el siguiente código para acceder a claves den el fichero de configuración app.config:

string NombreFichero = ConfigurationSettings.AppSettings.Get("FicheroExportar");
string TipoFichero = ConfigurationSettings.AppSettings.Get("TipoFicheroExportar");

Lo cual hace que salte una alarma en Visual Studio avisándote que este código es obsoleto y que lo cambies por el actual.

La duda viene a que no es tan directo como el llamar a un nuevo namespace y ya está, pero vamos a empezar por eso:

using System.Configuration;

Esto no nos dará error alguno, pero si intentas introducir ConfigurationManager en el Intellisense no te vá a salir. Para ello debes hacer referencia del ensamblado adecuado en el proyecto, para lo cual pulso con el botón derecho encima del proyecto principal y escojo “Add Reference”.

image

Se me abre la ventana para seleccionar el ensamblado adecuado: System.Configuration. Fíjate que estoy en .NET 4.0.

image

Pulso aceptar y ahora si que si puedo utilizar el código correcto:

var nombreFichero = ConfigurationManager.AppSettings["FicheroExportar"];
var tipoFichero = ConfigurationManager.AppSettings["TipoFicheroExportar"];

Espero que sea útil.

miércoles, 6 de febrero de 2013

Recuperar un valor de un elemento de un XDocument

Que XML no es santo de mi devoción, como tampoco lo es JavaScript, es algo que destila en todo el blog. Y no lo es ninguna de las dos tecnologías por la misma razón, no son nada amigables en su aprendizaje.

Así me encuentro con la siguiente respuesta de un Webservice, que es básicamente un XmlElement con el body del mensaje SOAP en el innerXML.

<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <reactiveSecureClientResponse xmlns="http://irdeto.com/pisys/secureclient">
    <reactiveSecureClientResult>
      <code>1028</code>
      <message>OK</message>

    </reactiveSecureClientResult>
  </reactiveSecureClientResponse>
</soap:Body>

Del cual quiero extraer el valor de los elementos hijos code y message, y que he resaltado en negrita.

Pues bién, llevo casi 6 horas probando mil métodos y la primera aproximación, antes de refactorizarlo – y que va a ser otro artículo – es un tanto extravagante:

Primero convierto el XmlElement en un XDocument (cuidadín con liarte y utilizar XmlDocument, que se montan unos líos de aupa si mezclamos Linq to SQL con XmlDocumentde .NET).

XDocument documento = XDocument.Parse(cuerpoDelMensajeSoap.InnerXml);

¿Porqué XDocument.Parse() en vez de el conocido documento.LoadXml()? Ni idea, pero creo que es para joder. Porque ya me contarás porqué algo tan lógico como lo segundo lo cambian por algo tan raro (un constructor estático con parámetros) como lo primero.

A continuación tiro de las capacidades de Linq to XML para hacer una búsqueda que, personalmente, me parece rara de narices:

XElement code = (from XElement xmlElemento in documento.Descendants()
                       
where xmlElemento.Name.LocalName.Equals("code")
                       
select xmlElemento).FirstOrDefault();

El primer problemón que me encontré es que, a pesar de lo que dicta el sentido común, los xmlElemento que obtengo de los descendientes del XDocument (documento.Descendants()) componen su nombre con dos partes diferenciadas: el namespace y el nombre del nodo en sí.

<{http://irdeto.com/pisys/secureclient}code>1028</code>

Osea, que no solo hay que buscar por el Name del elemento, si no también por su nombre Local.

where xmlElemento.Name.LocalName.Equals("code")

Y así, y entonces si, podemos cargar el valor del nodo de marras que quería recuperar. Por cierto, te aconsejo comprobar primero si el XElement no es nulo para evitar una excepción por objeto no instanciado al querer recuperar el Value.

string codigo = (code != null) ? code.Value : string.Empty;

 

Ahora a refactorizar, que me “huele mal” cuando me tengo que traer dos valores,

public string ExtraerRespuestaDelBody(XmlElement cuerpoDelMensajeSoap)
        {

           
XDocument documento = XDocument.Parse(cuerpoDelMensajeSoap.InnerXml);

           
XElement code = (from XElement xmlElemento in documento.Descendants()
                       
where xmlElemento.Name.LocalName.Equals("code")
                       
select xmlElemento).FirstOrDefault();


           
string codigo = (code != null) ? code.Value : string.Empty;
 
           
return codigo;
        }

jueves, 20 de diciembre de 2012

Migrando de TFS11Beta a TFS2012 with Update 1

Ha llegado el momento ineludible y me pongo a migrar un TFS11Beta de producción – si, ya sé que no debiera – a un TFS2012.

Primer escollo, no se puede instalar un TFS2012 actualizando un TFS11 Beta. Hay que desinstalar el TFS11Beta antes. Lo cual – menos mal que tengo todo en máquinas virtuales – implica hacer una backup en forma de snapshot de la máquina virtual.

Segundo escollo NO SE PUEDE ACTUALIZAR HASTA UN TFS2012 con UPDATE1… debes primero actualizar al TFS2012 y después aplicarle el Update1.

Asegurado que no voy a perder más de una hora en volver al punto anterior, desinstalo el TFS11 Beta. Y, sin necesidad de reiniciar la máquina, me pongo a instalar desde la Web el TFS2012.

image

Al instalar el .NET 4.5 pide un reinicio inmediato… es decir que se reinicia en cuanto pulses OK. Al volver al sistema continua guardando en local los ficheros de instalación. (Tal vez debiera haberme tirado del todo al rio y haber actualizado el Windows 2008 server R2 a un Windows 2012 Server, lo cual puede dar para otro artículo). Y, finalmente se pone a instalar – sin preguntarme aún si quiero actualizar.

Me pide el número de serie, y cómo no lo tengo a mano, le digo que me ponga un Trial de 90 días. A lo cual me abre el Configuration Center y selecciono Upgrade y Start Wizard.

image

Lo primero que me pregunta es cual es la base de datos de TFS que voy a actualizar. Para comprobar que es la correcta pulso en el enlace de List Available Databases y me tiene que salir, como poco, la de Tfs_configuration. Además, ya que estoy utilizando un snapshot como copia de seguridad, hago check en la casilla inferior en donde le digo que tengo un backup actual.

image

La siguiente pantalla trata de la cuenta de servicio que voy a utilizar para mi Application-Tier, la cual (por si no te acuerdas) debería ser algo como TFSSERVICE. No es buena práctica utilizar una cuenta de sistema.

image

Continuamos con la configuración del Reporting Server en donde le indico cual es el servidor que voy a utilizar y le doy al enlace de Populate URLs para que me añada el solito las URL adecuadas.

image

Ahora empezamos con chicha, le tengo que indicar cual es la base de datos que soporta el Team Foundation Warehouse. Lo pruebo pinchando en el enlace de Test y a continuación compruebo las bases de datos pinchando en el enlace List Avaliable Databases. Al menos debe aparecer una.

image

Continuamos indicando cual es la base de datos que soporta los Analisys Services, y comprobamos su correcto funcionamiento pinchado en Test.

image

Continuamos por la configuración de la cuenta de servicio que va a ser utilizada para contactar con el servidor de Reportes, la cual no debiera ser de sistema y debería ser algo como TFSREPORT.

image

Ahora configuremos el acceso a SharePoint para los portales de los proyectos, lo cual es muy sencillo: los dejo como estaba.

image

Ahora nos vamos a la pantalla de Review y lanzamos la verificación de todos los datos que hemos introducido.

image

Aquí me salto la alerta avisándome que no se podía actualizar la base de datos y, buscando en internet, encontré que era a causa de que no se puede actualizar directamente de TFS11 beta TFS2012 con Update 1. Hay que pasar primero por TFS2012 normal, que puedes encontrar aquí: Team Foundation Server 2012 without Update 1 en el enlace superior derecho, no en el listado de TFS a descargar.

Le doy a verificar y, si todo está correcto, deberían salir todos verdes.

image

Le damos al botón Configure, y se pone a configurar el TFS2012 en la base de datos y a hacer sus cosas raras que hace por dentro. Es el momento de la verdad, si algo rompe aquí la cosa va a pintar bastos.

image

Y después de un rato de redoble de tambores… tachan!!! Lo que estaba esperando de agua de Mayo: la pantalla de Sucess. La alerta que me sale es que no se puede cambiar el grupo Contributor de SharePoint, lo cual está bien.

image

Ahora a por el Update 1, pero eso será otro artículo (si merece la pena).