viernes, 2 de diciembre de 2011

Análisis de código

Integrada con Visual Studio disponemos de una herramienta de análisis de código, que se encarga de comprobar que el código existente en el proyecto cumple unas ciertas normas (o reglas) de calidad.

Dicha herramienta se configura desde la ventana de propiedades del proyecto, en la pestaña “Code Analysis”

image

 

Como podemos observar en la captura anterior, podemos configurar el análisis de código para que se ejecute automáticamente al compilar el proyecto y más importante, podemos definir el conjunto de reglas de análisis que queremos que se comprueben contra el código. Este conjunto de reglas está predefinido, y las reglas en sí están agrupadas por categorías. Las categorías disponibles aparecen en la siguiente captura, en la que podemos ver también que dichas categorías pueden excluirse del análisis de código como una unidad completa.

image

Para ver las reglas que se aplican en cada categoría, basta con desplegar el árbol correspondiente, y aparecen todas las reglas de la categoría, con un nombre “descriptivo” del sentido de la regla así como una casilla de verificación que nos permite excluir una regla concreta del análisis en lugar de toda la categoría:

image

¿Cómo ejecutamos el análisis de código?

Una vez que hemos seleccionado el conjunto de reglas que queremos aplicar al análisis, es hora de ejecutarlo… Pero ¿cómo lo hacemos?

Fácil fácil, venga que sí de verdad:

  1. Clic con el botón derecho del ratón sobre el proyecto.
  2. Clic en “Run Code Analysis”

image

¿Difícil?

¿Cómo vemos los resultados?

Ésta es una pregunta trampa, ya que como veremos cuando ejecutemos el análisis de código, Visual Studio utilizará la ventana de “Error List” para mostrar todas las incidencias que haya encontrado… Preparaos para un buen SUSTO!!

image

Última consideración

En la última captura podemos ver que las reglas que no se están cumpliendo aparecen como “Warnings” en la ventana, esto es configurable desde la ventana de detalle de las categorías y reglas:

image

Si cambiamos la configuración, el estado de las reglas incumplidas también cambiará pasando a ser error o a desaparecer.

Fin de la historia… ¿Fin? no exactamente, en breve tendré otro artículo para explicar cómo podemos añadir nuestras reglas personalizadas al Análisis de Código.

miércoles, 30 de noviembre de 2011

Controles personalizados, databinding y tabs

Apunte rápido, truco aún más rápido, para que no se me olvide.

Situación

Tenemos un control personalizado al que le asignamos el valor mediante databinding, hasta aquí todo normal.

Metemos el control personalizado en la primera pestaña del control de pestañas de .Net y hasta aquí, todo normal.

Metemos el control en otra pestaña (que no sea la primera, como podemos imaginar) y cuando accedemos a la pestaña en cuestión, el control NO tiene el valor asignado mediante el databinding.

Al turrón

No voy a entrar en mucho detalle, ya que la “solución” adoptada ha sido bastante sencilla, queda pendiente una investigación más ‘a fondo’ para ver si realmente el problema está en al gestión de la información que hace el control Tab (y todos los que hereden de él) o el problema está en el diseño del control personalizado.

No me hago de rogar, la solución ha sido “refrescar” el “BindingContext” del control personalizado.

El trozo de código que he implementado sería:

myCheckListBox.BindingContext = this.BindingContext;

En el caso concreto que me ocupaba, el databinding se realizaba sobre un control incluido dentro del control personalizado, con lo que en la rutina de carga, ha sido suficiente añadir:

this.ListaValores.BindingContext = this.BindingContext;

Fin de la historia.

jueves, 17 de noviembre de 2011

Cómo activar una aplicación heredada con Lync 2010

O cómo pasar una aplicación integrada con OCS 2007 a LYNC 2010 sin morir en el intento

 

Situación inicial

Partimos de una aplicación desarrollada con el UCMA 2.0 de OCS que, básicamente registra un nuevo usuario o SIP en el servicio de OCS y permite establecer conversaciones con él, lo que viene a ser un BOT de toda la vida.

En este artículo no vamos a ver código como tal, ya que la aplicación original no sufre ningún cambio a la hora de ‘migrarla’ a un entorno de LYNC 2010. Como ya podemos imaginarnos, lo más correcto hubiera sido migrar la propia aplicación al UCMA 3.0, pero en esta ocasión no disponemos del tiempo necesario, así que ¿Qué hacemos?

Como explicación inicial, indicar que la aplicación que queremos ‘reconfigurar’ está funcionando correctamente en un entorno OCS 2007, y su configuración inicial se realizó con la herramienta “Application Provisioner” (enlace)

 

Primer intento

Nuestra aplicación está correctamente aprovisionada en el OCS, y dado que nuestra infraestructura lo permite, la primera intención es simplemente modificar el archivo de configuración para apuntar al nuevo servidor de LYNC en lugar de al servidor original. Resultado, no funciona; el endpoint establece correctamente la conexión, la cuenta en el cliente LYNC aparece como disponible, pero al iniciar una conversación, se produce un error.

image

Revisando el visor de eventos, encontramos el siguiente error:

image

 

Segundo intento

A continuación intentamos modificar el host de LYNC (“OCS Pool Fqdn”) mediante la herramienta “Application Provisioner”. Resultado, no se puede, hay que generar un Application Pool nuevo. De acuerdo, si no queda más remedio, creamos uno nuevo, con las mismas características que el anterior, pero utilizando el nuevo Host de LYNC.

Ojo, porque si queremos mantener el servidor de aplicaciones, tendremos que eliminar el Application Pool anterior, ya que de lo contrario nos encontraremos con es siguiente error:

image

Una vez creado el nuevo pool, actualizamos en el archivo de configuración de la aplicación el “GRUU” y lanzamos la prueba. Resultado, no funciona; el cliente LYNC vuelve a mostrar el mismo error de antes, y en el visor de eventos, de nuevo el mismo error.

 

Replanteamiento

Si no puedes con el enemigo, únete a él. En este momento, tenemos una aplicación que no funciona en ningún entorno, así que hacemos marcha atrás, y volvemos a la situación inicial.

Entonces, ¿qué hacemos? tras mucho mirar y remirar por ahí, acabamos llegando a la conclusión (por otra parte lógica) de que el mecanismo de aprovisionamiento para OCS NO es compatible con LYNC y que la única manera de realizar la “reconfiguración” va a ser pelearnos con Powershell en el servidor LYNC.

 

Al turrón

Con la aplicación aprovisionada en el servidor OCS 2007, tenemos que ejecutar unos comandos de Powershell en el servidor LYNC, para lo que iniciamos la consola de administración de LYNC (“Lync Server Management Shell”) que no deja de ser una consola de Powershell (recomendado hacerlo como Administrador) y empezamos a ‘picar’ instrucciones:

  1. “Merge-CsLegacyTopology -TopologyXmlFileName newtopology.xml”
  2. “Publish-CsTopology -FileName newtopology.xml”
  3. “Enable-CsTopology”
    Estas instrucciones recrean el pool original de OCS 2007 en la topología del servidor LYNC.
  4. “Move-CsApplicationEndpoint {identity] -TargetApplicationPool {fqdn} –Force”
    Esta instrucción mueve los contactos al nuevo pool, con lo que en principio ya estaríamos listos.

¿Cómo averiguamos el “{identity}”?

Ejecutamos el comando “Get-CsApplicationEndpoint” y en los resultados buscamos nuestra aplicación y copiamos el valor de la propiedad “Identity”

image

 

Fin de la historia

viernes, 28 de octubre de 2011

Cómo descargar documentos de Sharepoint rápidamente

Así como vimos una manera sencilla de publicar documentos en un servidor de Sharepoint (acceso), en esta ocasión vamos a proceder a la descarga de esos documentos.
En este proceso vamos a utilizar la clase “System.Net.WebClient” lo que implica que estas operaciones no son exclusivas de Sharepoint, sino que servirían ‘virtualmente’ para cualquier tipo de servidor web.

Al turrón

  1. Instanciamos y configuramos el objeto “WebClient”:
    WebClient objWebClient = new WebClient();    
    objWebClient.Credentials = CredentialCache.DefaultCredentials;
  2. Descargamos el documento:
    objWebClient.DownloadFile(txtSource.Text, rutaDes + "\\" + nombreArchivo);

Descargar sin permisos en la biblioteca de origen

En muchas ocasiones, las bibliotecas de Sharepoint que se utilizan como repositorio de aplicaciones tienen especificada una seguridad específica para evitar que el acceso a esa documentación se realice desde ‘fuera’ de las aplicaciones concretas. Para poder realizar el download en estos casos, tendremos que disponer de una cuenta de acceso ‘genérica’ a la biblioteca con los permisos mínimos para poder descargar documentación, y utilizar esa cuenta en la configuración de las credenciales del objeto “WebClient”:
objWebClient.Credentials = new System.Net.NetworkCredential("user","pwd","domain"); 

¿Fácil no?

Adjuntos

Descargar

jueves, 27 de octubre de 2011

Cómo subir un documento a Sharepoint rápidamente con Servicios Web

Cuando queremos utilizar Sharepoint como repositorio de documentos de nuestras aplicaciones, lo primero que tenemos que decidir es cómo queremos conectar con el servidor para almacenar dichos documentos. La decisión en sí no es muy complicada, aunque sí es cierto que dependerá de factores como arquitectura, formas de conexión, seguridad, etc…
En este artículo vamos a desarrollar paso a paso una función de ‘Upload’ utilizando los servicios web nativos de Sharepoint, en su versión 2010. Esta aproximación es la más sencilla de implementar y a continuación veremos cómo

Añadir la referencia web

Como comentaba más arriba, vamos a subir documentación a un servidor de Sharepoint mediante los Servicios Web nativos; en consecuencia, lo primero que tenemos que hacer es añadir la referencia web correspondiente en nuestro proyecto. En el ejemplo realizado se ha utilizado Visual Studio 2010, pero es perfectamente válido también para versiones anteriores.
  1. Sobre el proyecto, clic con el botón derecho del ratón, “Add Service Reference”

    image
  2. Para añadir la referencia web, hacemos clic en el botón “Advanced” y a continuación en el botón “Add Web Reference”

    image

    image
  3. En la caja de texto “URL:” introducimos la url de acceso al servicio web de Sharepoint que nos permitirá subir documentos. Dentro de todos los servicios web que proporciona Sharepoint, el que nos interesa en esta ocasión es “Copy.asmx” y como el resto de los servicios web está alojado en la carpeta “_vti_bin” en este ejemplo vamos a utilizar como ruta para la referencia “http://srvmv07/_vti_bin/copy.asmx
  4. Una vez que la ventana anterior nos ha comprobado la referencia, le damos un nombre (en el ejemplo “WSCopy”) y hacemos clic en “Add Reference” para incluir la referencia en el proyecto.

    image
En este ejemplo, vamos a trabajar con dos parámetros en el archivo de configuración. Uno indicará el sitio de Sharepoint donde queremos subir el documento (“WebUrl”) en formato http://servidor/sitio y el otro indicará la biblioteca de destino (“DocumentLibraryDestination”)

Al turrón

  1. Instanciamos el servicio web:
    //Configuración del Servicio Web         
    WSCopy.Copy copyService = new WSCopy.Copy();         
    copyService.Url = Properties.Settings.Default.WebUrl + "/_vti_bin/copy.asmx";         
    copyService.Credentials = System.Net.CredentialCache.DefaultCredentials;      
    Como podemos ver en el fragmento de código, en este ejemplo estamos utilizando las credenciales por defecto del usuario que está ejecutando el programa. Más adelante veremos cómo actuar si dicho usuario no tendrá permisos sobre la carpeta de destino.
  2. Preparamos los objetos necesarios para realizar el Upload:
    //Declare and initiates the Copy WebService members for uploading       
    string sourcePath = “Ruta completa al archivo a publicar”;       
    string[] destinationUrl = {       
                               Properties.Settings.Default.WebUrl + "/" +       
                               Properties.Settings.Default.DocumentLibraryDestination + "/" +       
                               “Nombre del archivo”       
                               };       
    WSCopy.CopyResult cResult1 = new WSCopy.CopyResult();       
    WSCopy.CopyResult cResult2 = new WSCopy.CopyResult();       
    WSCopy.CopyResult[] cResultArray = { cResult1, cResult2 };       
    WSCopy.FieldInformation fFiledInfo = new WSCopy.FieldInformation();       
    WSCopy.FieldInformation[] fFiledInfoArray = { fFiledInfo };     
    En este fragmento, la parte más relevante está en las últimas dos instrucciones, ya que nos permitirán, completando el código, establecer los valores de metadatos del documento en Sharepoint. De momento no vamos a publicar ningún atributo, así que lo dejamos como está.
  3. Abrimos el archivo que vamos a ‘subir’ y lo convertimos en un array de Bytes, que será lo que tendremos que enviar al servicio web como parámetro:
    //Reading the document contents in to stream       
    FileStream strm = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);       
    byte[] fileContents = new Byte[strm.Length];       
    byte[] r = new Byte[strm.Length];       
    int ia = strm.Read(fileContents, 0, Convert.ToInt32(strm.Length));       
    strm.Close();
  4. Invocamos a la función “CopyIntoItems” del Servicio Web para realizar el upload y… listo!

    uint copyresult = copyService.CopyIntoItems(sourcePath, destinationUrl, fFiledInfoArray, fileContents, out cResultArray);

    Ojo con esta última parte, ay que según la documentación, la función devolverá “0” si todo a ido bien, y otro valor si ha habido algún problema; sin embargo, la manera de comprobar si todo ha ido bien es mediante el parámetro de vuelta “cResultArray”

Realizar el Upload sin permisos en la biblioteca de destino


En muchas ocasiones, las bibliotecas de Sharepoint que se utilizan como repositorio de aplicaciones tienen especificada una seguridad específica para evitar que el acceso a esa documentación se realice desde ‘fuera’ de las aplicaciones concretas. Para poder realizar el upload en estos casos, tendremos que disponer de una cuenta de acceso ‘genérica’ a la biblioteca con los permisos mínimos para poder subir documentación, y utilizar esa cuenta en la configuración de las credenciales del servicio web:
copyService.Credentials = new System.Net.NetworkCredential("user","pwd","domain");
 
Cuidado porque esta práctica provoca que en la biblioteca de documentos el usuario que aparece como última modificación será ese usuario genérico.

Modificar propiedades del documento


Las bibliotecas de Sharepoint pueden contener propiedades o atributos que etiquetan al contenido de las mismas. Para poder aplicar valor a esas propiedades al reaalizar el upload de un documento, tendremso que ‘jugar’ con la clase “FieldInformation” que comentaba más arriba:
fFiledInfo.DisplayName = "Nombre del atributo";
fFiledInfo.Type = WSCopy.FieldType.Text;//Tipo
fFiledInfo.Value = "valor";
 

Adjuntos

Descargar

jueves, 20 de octubre de 2011

Trabajar con archivos de configuración

Como todos sabemos, para añadir parámetros o elementos de configuración a un proyecto .NET, utilizamos los archivos de configuración (indistintamente con el archivo app.config o con el archivo web.config)
Para añadir opciones a estos archivos, disponemos básicamente de dos opciones:
  1. Entrada Manual:
    Con entrada manual me refiero a aquellas entradas que ubicamos en la sección de un archivo de configuración.

    image
    Para acceder a estos valores en tiempo de ejecución, tenemos que utilizar la clase “ConfigurationManager”, siempre que hallamos añadido la referencia correspondiente al ensamblado “System.Configuration.dll”

    image
  2. Entrada Semiautomática:
    Estas entradas son las que se establecen desde la ventana de propiedades de un proyecto.

    image
    Estas entradas se almacenan en el archivo de configuración de una manera un tanto “especial” como ya habréis observado.

    image
    Y para acceder a estos valores en tiempo de ejecución, típicamente haremos lo siguiente:

    image
Pero, ¿tenemos alguna opción adicional para trabajar con estos archivos de configuración? La respuesta es rápida y concisa: .
Si observamos las entradas que se generan en el archivo de configuración al utilizar el panel de propiedades del proyecto, vemos que añade dos elementos, por un lado un “sectionGroup” y por otro lado un “setting” en un nodo con el formato “Namespace.Properties.Settings” que coincide con el atributo “name” del elemento “sectionGroup”
La parte que más interesa ahora mismo es la del “sectionGroup” ya que si la observamos con detenimiento, podemos ver que tiene especificado un “type”, que típicamente será del estilo:
type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=key"

Además la propia entrada “section” tiene también un atributo “type”, que típicamente será del estilo:
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=key"

Con lo anterior lo único que quiero indicar es que si los distintos elementos del archivo de configuración son de tipos concretos del Framework de .NET, ¿por qué no vamos a poder utilizar ahí tipos personalizados creados por nosotros?

En este punto, alguien puede preguntarse por qué nos interesa tener entradas personalizadas, y la respuesta, tal y como yo lo veo, hay que buscarla en el deseo de tener los archivos de configuración organizados y limpios, ya que con esta posibilidad podríamos tener distintas secciones dependiendo de módulos activados en nuestros programas, como podría ser un sistema de trazas o incluso los parámetros necesarios para utilizar componentes genéricos de acceso a datos.

Al turrón


Una vez que hemos visto un poco por encima cómo se utilizan los archivos de configuración, vamos a generar nuestros propios tipos de entradas, para poder organizar los parámetros necesarios para nuestros componentes genéricos.

Lo primero que tenemos que hacer es crear una clase personalizada “ConfigurationSection” que nos sirva para trabajar con los valores del archivo de configuración. Esta clase heredará de la clase “ConfigurationSection”, que nos permitirá trabajar con los datos en tiempo de ejecución.

El siguiente fragmento de código muestra la clase, está disponible en la sección de adjuntos:
     /// 
     /// This class allow us to access the config file data via the Configuration Manager.
     ///
     public class CustomTraceSection : ConfigurationSection
     {
         ///
         /// Create an "active" attribute.
         ///
         [ConfigurationProperty("active", DefaultValue = "false", IsRequired = false)]
         public Boolean Active
         {
             get
             {
                 return (Boolean)this["active"];
             }
             set
             {
                 this["active"] = value;
             }
         }
         ///
         /// Create a "traceLevel" element.
         ///
         [ConfigurationProperty("traceLevel")]
         public TraceLevelElement TraceLevel
         {
             get
             {
                 return (TraceLevelElement)this["traceLevel"];
             }
             set
             {
                 this["traceLevel"] = value;
             }
         }

Con este código lo que estamos generando es el soporte para nuestra sección de configuración personalizada, que quedará así:
image

Además estamos definiendo también los componentes que tendrá nuestra sección de configuración, en este caso un atributo “active” y un elemento “traceLevel”. El elemento “traceLevel” se genera mediante una clase personalizada que hereda de “ConfigurationElement”, cuyo detalle se ve a continuación, a pesar de que es muy similar a la clase anterior:

    public class TraceLevelElement : ConfigurationElement
     {
         ///
         /// Create a "value" attribute.
         ///
         [ConfigurationProperty("value", DefaultValue = "Nothing", IsRequired = true)]
         public TraceLevel Value
         {
             get
             {
                 return (TraceLevel)this["value"];
             }
             set
             {
                 this["value"] = value;
             }
         }
A destacar: En esta última clase hemos utilizado un tipo enumerado para indicar los valores disponibles para la propiedad, a título informativo de las posibilidades que nos brinda el sistema.

Con este código, ya podemos completar nuestra sección de configuración, que quedará así:
image

Ya sólo nos queda utilizar esta sección en nuestro código y lo tendremos todo ligado y bastante organizado:

            //Instanciamos la sección de configuración
            CustomTraceSection config =
                (CustomTraceSection) ConfigurationManager.GetSection("customTraceGroup/customTrace");

            //Acceso a valor concreto
            Boolean active = config.Active;

            //Acceso a valor embebido en un elemento
            TraceLevel traceLevel = config.TraceLevel.Value;


A partir de aquí, ¡a jugar!

Adjuntos

Descargar

Mejoras

  • Podríamos almacenar la ruta de la sección de configuración en una constante.
  • Podemos (tal vez en otro artículo) generar esas entradas en el archivo de configuración de forma ‘programática’, con lo que no sólo dejamos el archivos de configuración organizado, sino que además evitamos tener que poner esas entradas a mano.
  • Cualquier propuesta de mejora adicional, será bienvenida.

jueves, 6 de octubre de 2011

Utilizar IntelliTrace sin Visual Studio 2010

ATENCIÓN: Este procedimiento OBLIGA a tener licencia de Visual Studio 2010 Ultimate.
Como definición rápida (que me perdonen los puristas) el IntelliTrace es una herramienta que permite llevar un registro de todo lo que sucede con una aplicación, de forma que a posteriori somos capaces de reproducir 'exactamente' lo que pasó en una sesión concreta. La idea de esta herramienta es acabar con la mítica situación de "en mi equipo funciona" ¿quién no la ha utilizado alguna vez? Para una definición más exacta podemos visitar este enlace.
Una de las particularidades de esta herramienta es que sólamente está disponible de forma directa desde Visual Studio 2010 Ultimate, y se activa o desactiva a nivel general desde las opciones del producto:


 Bueno, como 'reza' el título de este post, esto no es estrictamente necesario, de forma que podemos utilizar también esta herramienta en equipos en los que no está instalado Visual Studio (ojo porque lo que no está permitido es utilizar esta herramienta en un entorno de producción.
Vamos al 'turrón' ¿Cómo utilizamos esta maravilla sin Visual Studio?
  1. Creamos una carpeta en una ubicación temporal y la llamamos (originales nosotros) IntelliTrace.
  2. En esta carpeta copiamos el contenido de la carpeta "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\TraceDebugger Tools"
  3. A continuación copiamos el archivo "Microsoft.VisualStudio.IntelliTrace.dll" que está en la carpeta "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
  4. Por último copiamos el archivo "TraceLogProfiler.dll" que está en la carpeta "C:\Program Files (x86)\Common Files\Microsoft Shared\VSTS 10.0\Trace Debugger"
  5. Ahora viene una parte 'chunga'. tenemos que obtener lo que se denomina como "CollectionPlan" que es un archivo de configuración que se genera al utilizar IntelliTrace desde Visual Studio. Para obtener este archivo, tenemos que activar el IntelliTrace (captura anterior) y configurar en esas mismas opciones el nivel de traza deseado. Cargamos un proyecto, y vamos a la carpeta "C:\Users\usuario\AppData\Local\Microsoft\VisualStudio\10.0\TraceDebugger\Settings" aquí veremos un archivo de nombre variable, que copiaremos también a la carpeta temporal y renombraremos a algo más claro, como por ejemplo "Collector.xml".
  6. Editamos este archivo con el bloc de notas, y nos aseguramos de que en las entradas "LogFileDirectory" y "DeleteLogOnExit" están configuradas de manera adecuada (ojo porque el primer parámetro puede tener que ser cambiado en la máquina en la que queremos ejecutar el IntelliTrace:


    Para más información acerca de este archivo, visitar el siguiente enlace.
Una vez hemos realizado estas operaciones, el contenido de nuestra carpeta temporal será algo parecido a esto:

Ya tenemos todo preparado para hacer la traza... Sólo queda coger esa carpeta y llevarla a la máquina en la que queremos sacar la traza, y ejecutar la herramienta desde la línea de comandos:
IntelliTrace.exe launch /cp:Collector.xml rutadelprogramaatrazar\programa.exe
Cuando el ejecutable termine, tendremos en la carpeta del IntelliTrace un archivo con extensión .iTrace, que contiene toda la información de la ejecución. Este archivo ya podemos abrirlo con Visual Studio 2010 y ahora disponemos de una 'grabación' de lo que ha pasado en la ejecución (fundamental para detectar errores)
NOTAS:
Aunque venga con Visual Studio 2010, esta herramienta NO necesita el Framework 4.0 y en principio es capaz de sacar trazas de programas desarrollados desd ela versión 2.0 del Framework en adelante.
En el equipo destino puede producirse un error al lanzar el programa, que se ve cuando al abrir el archivo de traza está vacío... Una de las causas que he visto es porque el componente "TraceLogProfiler.dll" no esté registrado en la máquina, si se da el caso, basta con ejecutar un regsvr32 TraceLogProfiler.dll
En la versión de 2010, sólamente podemos realizar trazas sobre programas compilados en 32 bits, pero instalando el Service Pack 1 en principio esta limitación ya no existe, si bien yo no he podido probarlo.
Sin embargo, sí puedo confirmar que modificando el valor de la entrada "AttachOptions" del archivo Collector.xml a Attach64Bit, el intellitrace funciona con un programa ejecutándose en 64 bits!
RESULTADO
A modo informativo, así es como se ve una traza de este estilo:


REFERENCIAS
Esta información ha sido recopilada partiendo de las siguientes entradas:
http://www.techmetadata.com/2010/04/standalone-intellitrace-from-vs-2010.html
Además más información en castellano en el blog del gran Unai Zorrilla, acceso

miércoles, 21 de septiembre de 2011

Utilizar TFS 2010 desde VB 6

Pequeño apunte para que no se me olvide.

Microsoft publicó hace un tiempo un proveedor / componente para permitir que productos que no soportan de forma nativa la conexión con el control de versiones de TFS puedan soportarlo.

Según la documentación de aquí,​ este proveedor permite conectar a TFS 2010 desde, entre otros, Visual Studio .NET 2003, Visual Visual Basic 6 SP6 y SQL Server Management Studio.

Mi experiencia personal ha sido con VS.NET 2003 y funciona 'de lujo' así que entiendo que con el resto de productos funcionará también perfectamente.

¡Ojo! Requiere .NET 4.0 y Team Explorer 2010 para funcionar. El proveedor está disponible para su descarga en el enlace anterior.

viernes, 9 de septiembre de 2011

Excepción BadImageFormatException en IIS 7.5

Ayer tuvimos algún 'pequeño' problema al generar un entorno de prueba de una aplicación web ASP.NET. La situación más o menos vino a ser la siguiente:

Problema:

Al acceder a la dirección web de la aplicación, se produce una excepción de ASP.NET del tipo BadImageFormat.

Solución (¿solución?):

Fácil (yujuu!) El equipo en el que la aplicación está instalada es un Windows 7 en 64 bits, con lo que si está dando esa excepción, el sospechoso más habitual indica que el proyecto en Visual Studio está compilado en 32 bits, así que para solucionar el problema, basta con acceder a las propiedades del proyecto y especificar que la compilación sea compatible con 'Any CPU', tal y como vemos en la siguiente captura (Como el proyecto es en VB.Net, la captura corresponde a las propiedades de un proyecto en ese lenguaje)





Listo. Cambiamos la opción de compilación, compilamos la solución y la instalamos, y a funcionar… un momento, ¿no funciona?

Problema 2:

Al acceder a la aplicación ya compilada correctamente, aparece una nueva excepción. Esta excepción, de la que no tengo captura, decía que no podía cargarse en memoria uno de los ensamblados referenciados por la aplicación (en concreto se trata de un ensamblado Interop) toca 'bucear' un poco en la excepción y darle un poco al 'coco'… Vale, ya lo tenemos!!!

Solución 2:

La segunda excepción está directamente relacionada con la primera, ya que al compilar la aplicación para 'Any CPU' hemos conseguido que la aplicación arranque correctamente en IIS (64 bits) peeero cuando esa aplicación realiza una instancia del componente Interop (compilado en 32 bits) resulta que no puede crear los objetos porque no son compatibles. Menos mal que IIS 7.5 tiene la opción de permitir aplicaciones en 32 bits… ¿dónde?

Vamos al listado de los Application Pools, y en el Pool asociado a la aplicación vamos a las opciones avanzadas:



Aceptamos el cambio, IISReset por si acaso, y a volar!!!!



Explicaciones:

El primer error como he comentado estaba provocado por el tipo de compilación del proyecto. Al compilarlo en 32 bits, los procesos de IIS que se ejecutan en 64 bits no eran capaces de arrancar la aplicación, con lo que cambiamos el modo de compilación a 'Any CPU' para que el compilado sea capaz de adaptarse tanto a 64 como a 32 bits (opción recomendada)

El segundo error estaba provocado precisamente por el cambio realizado en el primer punto, ya que al iniciar la aplicación en 64 bits, cualquier instancia que se realice de ensamblados o dll's compilados en 32 bits, sencillamente 'casca'

Consideración Especial:

Vistos los dos problemas que nos aparecieron, entiendo que la directa hubiera sido configurar el IIS para que permitiera aplicaciones en 32 bits, pero, ¿dónde está la gracia si lo solucionamos tan rápido y sin tener que pensar?

Nota: El segundo problema (ensamblado Interop) en este caso parecía claro que era por una compilación en 32 bits, eso NO quiere decir que en todos los casos esta solución sea válida al 100%.

martes, 6 de septiembre de 2011

Los Informes de TFS 2010 no funcionan (no funcionaban)

Ayer al instalar las plantillas de Scrum para TFS 2010 de Microsoft (Visual Studio Scrum 1.0) me di cuenta de que los informes de estado de TFS no estaban funcionando. Estos informes son los que se utilizan para revisar el estado de un proyecto en TFS (Tareas finalizadas / pendientes, número de Bugs, etc)
Lo que sucedía es que cada vez que accedía a uno de los informes, el servidor de Reporting devolvía este error:
"Error al procesar el informe. (rsProcessingAborted)
Error de ejecución de consulta para el conjunto de datos 'dsBurndown'. (rsErrorExecutingCommand)
Para obtener más información acerca de este error, vaya al servidor de informes en el equipo del servidor local o habilite los errores remotos
"

Tras mucho mirar por ahí y realizar pruebas, la solución resultó ser 'medianamente' sencilla.
El problema, por lo que pude comprobar estaba en el procesamiento del cubo OLAP explotado por los informes. Por lo visto, la primera vez que se tiene que procesar el cubo no funciona directamente desde la herramienta del SQL Management Studio, sino que hay que hacerlo a mano.
¿Cómo lo hacemos a mano? TFS dispone de una serie de Servicios Web de administración que, entre otras cosas, permite precisamente eso. El servicio web en concreto es el que se llama "WarehouseControlWebService" la url de acceso es: http://servidorTFS:puerto/tfs/TeamFoundation/Administration/v3.0/WarehouseControlService.asmx
Una
vez que accedemos al Servicio, hacemos clic en la operación "ProcessAnalysi​sDatabase", establecemos el valor del parámetro "processingType" a Full (tal cual está escrito, es un parámetro de tipo string) y hacemos clic en "Invoke"
Una vez realizada esta operación, teóricamente deberíamos ser capaces de procesar el cubo de nuevo desde el Management Studio, pero no lo he probado, ya que lo que quería era que los informes funcionasen y... voilá, funcionan!
NOTA: Conviene destacar que no he realizado un estudio en profundidad del problema, por lo que no descarto que vuelva a aparecer; simplemente me ha resultado de utilidad constatar que al regenerar el cubo mediante el servicio web de TFS los informes empiezan a funcionar correctamente. ¡Ya tenemos informes de "Sprint Burndown"!