|
Publicado el 06/Nov/2006
Hasta el momento hoy se han anunciado varios lanzamientos que pueden resultaros interesantes. Por un lado, ya está disponible el redistribuible de .NET Framework 3.0, incluyendo novedades como WPF (Windows Presentation Foundation, ó Avalon), WCF (Windows Communication Foundation, ó Indigo) y WWF (Windows Workflow Foundation). Por otro lado, también está disponible la RC1 de SQL Server Compact Edition (aunque al instalarla aparece aún como SQL Server Everywhere). Además, Office 2007 ya es RTM (versión final) y se ha anunciado en las subscripciones MSDN que todos los subscriptores tendrán disponibles tanto Office 2007 como Windows Vista para descargar en un plazo de 7 días después del anuncio, así que habrá que estar al tanto. Finalmente, hoy empieza el TechEd en Barcelona (donde hay varias presentaciones sobre Windows CE 6.0 que se lanzó la semana pasada), con lo que probablemente se producirán más anuncios interesantes a lo largo de los próximos días; pondremos la antena a ver qué se cuece.
Publicado el 01/Nov/2006
Así es, la versión compacta de SQL Server vuelve a cambiar de nombre, al parecer para quedarse con SQL Compact Edition. Tenéis todos los detalles en el blog de Steve Lasker. Al parecer, estará disponible en pocas semanas la versión 3.1, cuya ventaja principal es la de poder usarse en cualquier entorno, incluido Windows 2000. Ya están planificadas también las demás versiones con cambios en el motor de sincronización y la posibilidad de adaptarse a más situaciones.
Publicado el 03/Oct/2006
Si habéis leído mi post anterior probablemente habréis comprobado mi tendencia a usar en muchas ocasiones el camino más largo para llegar a un sitio dado. Como era de esperar, esto también funciona en .NET Compact Framework: System.Environment.OSVersion.Version (un poco más facil que lo anterior ¿no?) Esta propiedad devuelve un objeto de tipo Version que tiene sobrescrito el método ToString para obtener el string de versión habitual (x.x.xxxx); aunque también da acceso a los diferentes componentes de la versión. Como bonus, podéis examinar un poco más la clase Environment y veréis que podéis obtener lo siguiente: - Versión del runtime de .NET en ejecución - System.Environment.Version
- Directorios especiales (necesarios para acceder a los directorios en caso de que se ejecute la aplicación en equipos con diferentes idiomas, ej. "Startup" vs "Inicio") - Enum System.Environment.SpecialFolder, usado con la función System.Environment.GetFolderPath
- Tiempo que lleva el equipo encendido - System.Environment.TickCount
Recordatorio final: Antes de hacer nada, mirar si ya está implementado, antes de hacer nada, mirar si ya está implementado, antes de hacer nada, mirar si ya está implementado, antes de hacer nada, mirar si ya está implementado, antes de hacer nada, mirar si ya está implementado, antes de hacer nada, mirar si ya está implementado.
Publicado el 25/Sep/2006
A veces es necesario saber la versión del sistema operativo sobre la que está ejecutándose una aplicación .NET para tomar alguna deción sencilla. El ejemplo más claro que me he encontrado recientemente es el de usar la función Bitmap.Save en .NET Compact Framework para guardar un Bitmap a disco. Si se lee la documentación de esta función, se indica que se le puede pasar un parámetro de tipo ImageFormat (un enum) diciéndole el tipo de imagen a guardar. Entre los diferentes valores del enum se dispone de PNG por ejemplo. Pero si se intenta guardar un bitmap usando el formato PNG en un dispositivo Windows Mobile 2003 (cuya base de sistema operativo es Windows CE 4.2) obtendremos una excepción en tiempo de ejecución (NotSupportedException) ya que en Windows CE 4.2 GDI no dispone de la posibilidad de tratar PNGs. En cambio, si se ejecuta ese código en un dispositivo Windows Mobile 2005, basado en Windows CE 5.0, funcionará sin problemas. Para evitar estos problemas basta con que detectemos la versión del sistema operativo para escoger un formato de imagen u otro dependiendo del tipo de dispositivo que sea. Una forma de obtener rápidamente la versión del sistema operativo es mediante la función GetVersionEx del API de Windows. Su declaración sería similar a lo siguiente: [DllImport("coredll.dll")] public static extern int GetVersionEx(byte[] lpVersionInfo); Si se busca la documentación de esta función, como parámetro se pide una estructura de tipo OSVERSIONINFO. En este caso (como en muchos otros en los que el API requiere estructuras) resulta casi más fácil pasarle a la función como parámetro un array de bytes que luego la función rellenará. Lo que necesitamos saber, eso si, es el tamaño del array a pasar, que se puede ver en la documentación (sumando los tamaños de los campos de la estructura). Luego, cuando la función rellene el array, se podrá leer fácilmente su contenido usando la clase BitConverter, lo que facilita mucho las declaraciones de p/invoke, ya que no hay que traducir las estructuras a .NET. Esta misma técnica está usada en el ejemplo de Ping para Compact Framework que podéis encontrar aquí. Teniendo en cuenta esto, el código para obtener la versión será entonces algo parecido a: byte[] lpVersionInfo = new byte[138]; int resp = GetVersionEx(lpVersionInfo); if (resp == 1) { Int32 dwMajorVersion = BitConverter.ToInt32(lpVersionInfo, 4); Int32 dwMinorVersion = BitConverter.ToInt32(lpVersionInfo, 8); Int32 dwBuildNumber = BitConverter.ToInt32(lpVersionInfo, 12); Int32 dwPlatformId = BitConverter.ToInt32(lpVersionInfo, 16); } Para un equipo con Windows Mobile 2003 el valor de dwMajorVersion será 4 y el de dwMinorVersion será mayor o igual a 2 (Windows CE 4.2). En el caso de un equipo Windows Mobile 2005 la versión será mayor o igual a 5.0. Siguiendo el ejemplo anterior, la función Bitmap.Save pasándo como parámetro un formato de tipo PNG, funcionará sólo para equipos con dwMajorVersion >= 5.
Publicado el 25/Sep/2006
Hace unos días vi en dev.licio.us (una comunidad similar a Geeks.ms) una viñeta que me resultó graciosa que supongo que no necesita explicación si habéis visto la película 'La vida de Brian': (Traducción por si lo necesitáis: Bien, bien, pero además de los Genéricos, los Métodos Anónimos, los iteradores, las Clases Parciales, LINQ, WPF y WCF, ¿qué ha hecho Microsoft por nosotros? El frente de liberación de los Bloggers ) 
Publicado el 03/Sep/2006
Después de la muerte prematura de NDOC 2.0 Microsoft ha liberado una utilidad que 'lo sustituye', llamada Sandcastle.
Para aquellos que no lo sepan, estas utilidades permiten generar documentación de código a partir de los assemblies y sus correspondientes documentos XML que genera por ejemplo Visual Studio, a partir de los comentarios del código. Usa además Reflection para obtener documentación adicional de las posibles dependencias que pueda usar nuestra aplicación.
Tenía previsto describir a la vuelta de vacaciones como funciona Sandcastle ya que es una herramienta un poco dura de usar, únicamente mediante línea de comandos, pero he encontrado un Wiki sobre el tema que no conocía y que hace referencia a algunas utilidades que ya se han escrito por ahí que proporcionan un interface de usuario para Sandcastle, con lo que se hace un poco irrelevante escribir ya sobre cómo usar los comandos para generar la documentación.
Una de las que más me ha gustado es 'Sandcastle Help File Builder' que tiene un interface de usuario casi idéntico al que tiene NDOC con lo que usarla se hace muy sencillo para los que ya hemos usado esa herramienta (si no se ha usado, es muy fácil de aprender).
Para usarla, lo primero que se necesita tener instalado es Sandcastle, al menos con la CTP de Agosto de 2006. Una vez hecho esto, simplemente hay que seleccionar un assembly que hayamos compilado con la opción de generación de documentación XML en Visual Studio y pedirle a la utilidad que compile el archivo de ayuda. La salida de SandCastle se ve en la parte inferior de la ventana mostrando si se ha producido algún error. Si todo ha funcionado como debiera, la herramienta generará un archivo de ayuda con la documentación del código.
Una opción interesante que incluye esta utilidad es la de poder abrir directamente un proyecto o solución de Visual Studio para que la herramienta lo inspeccione y cargue los assemblies de salida, agilizando aún más el proceso.
Una pequeña pega ocurre si pasamos a la utilidad un assembly o proyecto de .NET Compact Framework. Si lo hacemos sin más, veremos un error similar al siguiente (para un proyecto con UI):
Error: Unresolved assembly reference: System.Windows.Forms (System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=969db8053d3322ac) required by …
Para poder generar documentación de .NET Compact Framework adecuadamente, hay que indicarle a la utilidad que busque las dependencias de los assemblies de .NET Compact Framework en el sitio correcto ya que si no lo hacemos, intentará buscarlas en el GAC del PC en el que se ejecute, donde no las encontrará. Para ello simplemente hay que incluir en la colección de dependencias de la utilidad (en la sección Build) el directorio en el que se encuentran los assemblies correspondientes; que en una instalación en los directorios por defecto de Visual Studio y sustituyendo X.X por la versión correspondiente de .NET Compact Framework será similar a
C:\Program Files\Microsoft Visual Studio 8\SmartDevices\SDK\CompactFramework\X.X\vX.X\WindowsCE
Una vez incluido el directorio en las dependencias, se puede compilar el archivo de ayuda sin problemas.
Archivado como:
Publicado el 17/Jul/2006
SQL Server Everywhere es el nombre bajo el que aparecerá la nueva versión de SQL Server orientada principalmente a desarrollos móviles. Realmente es una evolución del actual SQL Server Mobile, que ahora puede ejecutarse en dispositivos móviles Windows Mobile (basados en Windows CE) y en Tablet PCs (basados en Windows XP). Después de varias peticiones originadas por muchas partes, se va a modificar el producto para que pueda ser ejecutado en otros entornos, como PCs portátiles o de sobremesa. Actualmente, si se desarrolla una aplicación de sobremesa que use SQL Mobile, esta funcionará en la máquina de desarrollo (porque tiene Visual Studio instalado) o en un equipo que tenga instalado SQL Server 2005. Pero si la aplicación se intenta ejecutar en un PC que no tenga ninguno de estos productos, al intentar usar los componentes de SQL Mobile, nos encontraremos con una excepción que prohíbe su uso. La actual CTP de SQL Server Everywhere incluye simplemente aquellas DLLs que se han de distribuir junto con la aplicación para que la aplicación pueda ejecutarse en cualquier PC; es decir, no incluye ningún componente específico para dispositivos, ya que son los mismos que el actual SQL Mobile. Estas DLLs permiten entonces usar el mismo código que ya se usa en aplicaciones desarrolladas para dispositivos con SQL Mobile (por ejemplo la capacidad de replicar datos mediante replicación Merge o RDA con un servidor SQL Server) pero para aplicaciones de escritorio o para portátiles, convirtiéndose en una alternativa bastante interesante a otras bases de datos (SQL Server Express por ejemplo) debido a su mucho menor tamaño y mejor facilidad de distribución, aunque hay que evaluar también sus limitaciones. SQL Everywhere se distribuye como un archivo .msi que se puede incluir junto al instalable de nuestra aplicación, pero también se pueden simplemente incluir las dlls correspondientes junto con nuestro ejecutable, en el mismo directorio y crear un paquete de instalación que las incluya como DLLs individuales. Por otro lado, recientemente se ha anunciado que se va a incluir soporte para Windows 2000 (inicialmente sólo iba a estar disponible Windows XP y Windows Vista posteriormente), lo que da la ventaja de poder crear componentes de acceso a datos únicos, que puedan correr tanto en terminales móviles (Windows Mobile) como en PCs con Windows 2000 en adelante. El uso de esas DLLs está documentado, con lo que no voy a repetirlo aquí. Por otro lado, hay más gente que ha publicado cómo usar las dlls que se incluyen con Visual Studio 2005 para crear aplicaciones que usen SQL Mobile en el PC (con la limitación mencionada de que sólo se pueden ejecutar en PCs con Visual Studio o SQL Server 2005 o Tablet PCs). Siguiendo esos mismos pasos, pero ahora usando las DLLs incluidas en la CTP (se llaman exactamente igual) los ejemplos y aplicaciones que las usaban deberían funcionar sin más, pero ahora ampliándose el número de máquinas distintas en las que podrán ejecutarse.
Archivado como:
Publicado el 10/May/2006
 Este año el Developer Day está dedicado a la seguridad. Por suerte esta vez contamos con un superhéroe a nuestro lado que nos ayudará a librarnos de los malos, aunque bien es cierto no es la primera vez que nos echa una mano, trayéndose a unos amigos por si acaso.
Publicado el 24/Apr/2006
En ocasiones es necesario medir el tiempo que transcurre en completarse alguna operación en nuestro código, ya sea para optimizar su rendimiento o por cualquier otra razón. Para ello, en ciertas situaciones se puede utilizar la propiedad 'Now' de la clase DateTime, que devuelve una instancia de DateTime con la fecha y hora actuales. Se toma este valor en dos puntos diferentes del código y se restan para obtener el tiempo transcurrido.
Esta aproximación sólo será válida si la duración de la operación a realizar es relativamente larga, pero, en muchas ocasiones, la precisión ofrecida por este método no será suficiente y obtendremos que el tiempo transcurrido es 0, lo que no da mucha información. Para estos casos se usan habitualmente las funciones QueryPerformanceFrequency y QueryPerformaceCounter del API de Windows. Si se realiza una búsqueda sobre estas funciones en cualquier buscador, se verán cientos de artículos explicando su funcionamiento, con lo que no voy a extenderme aquí en su uso.
Lo que si puede resultar interesante en este caso es saber que estas funciones también se pueden utilizar en Windows CE, y, por tanto, están disponibles en Pocket PC y SmartPhone. Para utilizarlas hay que declararlas mediante P/Invoke de la siguiente forma:
[DllImport("coredll")]
private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[DllImport("coredll")]
private static extern bool QueryPerformanceFrequency(out long lpFrequency);
Como se ve están definidas en la librería coredll.dll que contiene casi todo el API nativo de Windows CE.
Para mostrar su uso, se adjunta un ejemplo (PerformanceMeter.zip) que contiene una solución de Visual Studio 2005 para Windows Mobile 2005 Pocket PC, con lo que es necesario disponer del SDK de Pocket PC 2005 para poder probarlo tal cual está (si no se dispone de ese SDK, se puede crear una solución en Compact Framework 2.0 para Pocket PC 2003 y añadir las clases a ese proyecto para utilizarlas). Esta solución contiene 2 proyectos. El primero, llamado PerformanceMeter, contiene tres clases cuyo objetivo es facilitar la realización de pruebas de rendimiento a lo largo del código de manera cómoda y reutilizable. El proceso sería el siguiente:
- Crear una instancia de la clase PerformanceMeter
- Crear un nuevo test de rendimiento mediante la llamada a PerformanceMeter.NewTest(), que devuelve una instancia de la clase PerformanceTest. Esta instancia es almacenada automáticamente en una colección interna de PerformanceMeter.
- En el punto en el que se quiera iniciar el test, se hace una llamada a la función Start() de la instancia de la clase PerformanceTest obtenida en el paso anterior.
- Cuando se quiera finalizar el test, se hace una llamada a la función Stop() de la misma instancia anterior.
- Para ver los resultados de los test realizados hay que consultar la propiedad PerformanceTests que contiene la colección de pruebas realizadas.
El objetivo de estas clases es el de poder realizar varios tests de rendimiento a lo largo de las pruebas de una aplicación dada para posteriormente poder crear un informe de cómo han resultado las pruebas, de la manera menos intrusiva para el código posible. Cada test contiene la siguiente información:
- Nombre y descripción del test, útil si se va a disponer de varios tests y se quiere sacar un listado de ellos.
- Número de iteraciones que realiza el test de un código determinado. Este valor sólo es una propiedad que se usa para calcular una media, de manera que si se entre la ejecución de la función Start y la función Stop el código realiza 10 iteraciones, la podemos establecer con ese valor para que devuelva la media por iteración.
- Fecha y hora de inicio y fin del test, obtenidos con DateTime.Now. Hay que tener en cuenta que los contadores de precisión no devuelven la hora.
- Tiempo de ejecución del test en milisegundos obtenidos con la resta de los anteriores.
- Duración media por iteración en alta precisión (propiedad AverageDurationPerIteration - tipo double), si se miden varias iteraciones.
- Tiempo de ejecución del test en alta precisión (propiedad TotalDuration - tipo Double)
Como ejemplo del uso de estas clases está el segundo proyecto incluido en la solución, PerformanceTests. Este proyecto presenta un formulario para Pocket PC y un menú, Tests, que hace, a modo de ejemplo, dos tests, uno de concatenación de strings y otro de búsquedas en un documento XML.
El primer test compara lo que tarda el código en concatenar 2000 cadenas con y sin usar la clase StringBuilder, y el otro test mide lo que tarda el código en acceder un nodo de un documento XML con XmlDocument y lo compara con lo que se tarda en acceder al mismo nodo usando XmlTextReader.
Cuando finalizan los tests, muestra en la ventana los tiempos medidos.
En este ejemplo, para que los resultados sean más reales, conviene ejecutar cada test dos veces y usar los resultados de la segunda ejecución, ya que la primera vez que se ejecutan cada uno de ellos hay un tiempo de carga e instanciación de clases que hacen que el primer test sea mucho más lento que el segundo.
Espero que resulte interesante.
PerformanceMeter.zip (63,17 KB)
|