<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
> <channel><title>Jorge Iván Meza Martínez &#187; C#</title> <atom:link href="http://blog.jorgeivanmeza.com/tag/c/feed/" rel="self" type="application/rss+xml" /><link>http://blog.jorgeivanmeza.com</link> <description>The Fire Within Me: &#34;knowledge will set you free&#34;</description> <lastBuildDate>Tue, 31 Jan 2012 18:18:13 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <item><title>Cifrado y descifrado asimétrico con RSA utilizando C#/Mono</title><link>http://blog.jorgeivanmeza.com/2010/11/cifrado-y-descifrado-asimetrico-con-rsa-utilizando-cmono/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cifrado-y-descifrado-asimetrico-con-rsa-utilizando-cmono</link> <comments>http://blog.jorgeivanmeza.com/2010/11/cifrado-y-descifrado-asimetrico-con-rsa-utilizando-cmono/#comments</comments> <pubDate>Tue, 02 Nov 2010 02:58:36 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Linux/Solaris/BSD]]></category> <category><![CDATA[Seguridad]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[asimétrico]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[cifrado]]></category> <category><![CDATA[Hipergalaxia]]></category> <category><![CDATA[Mono]]></category> <category><![CDATA[RSA]]></category> <guid
isPermaLink="false">http://blog.jorgeivanmeza.com/?p=11295</guid> <description><![CDATA[Introducción. En criptografía, RSA (Rivest, Shamir y Adleman) es un sistema criptográfico de clave pública desarrollado en 1977. En la actualidad, RSA es el primer y más utilizado algoritmo de este tipo y es válido tanto para cifrar como para &#8230; <a
href="http://blog.jorgeivanmeza.com/2010/11/cifrado-y-descifrado-asimetrico-con-rsa-utilizando-cmono/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<h2>Introducción.</h2><p
style="padding-left: 30px;">En criptografía, RSA (Rivest, Shamir y Adleman) es un sistema criptográfico de clave pública desarrollado en 1977. En la actualidad, RSA es el primer y más utilizado algoritmo de este tipo y es válido tanto para cifrar como para firmar digitalmente.</p><p
style="padding-left: 30px;">La seguridad de este algoritmo radica en el problema de la factorización de números enteros. Los mensajes enviados se representan mediante números, y el funcionamiento se basa en el producto, conocido, de dos números primos grandes elegidos al azar y mantenidos en secreto. Actualmente estos primos son del orden de 10200, y se prevé que su tamaño aumente con el aumento de la capacidad de cálculo de los ordenadores.</p><p
style="padding-left: 30px;">Como en todo sistema de clave pública, cada usuario posee dos claves de cifrado: una pública y otra privada. Cuando se quiere enviar un mensaje, el emisor busca la clave pública del receptor, cifra su mensaje con esa clave, y una vez que el mensaje cifrado llega al receptor, este se ocupa de descifrarlo usando su clave privada.</p><p
style="padding-left: 30px;">Se cree que RSA será seguro mientras no se conozcan formas rápidas de descomponer un número grande en producto de primos. La computación cuántica podría proveer de una solución a este problema de factorización.</p><p
style="text-align: right;">Tomado del artículo <a
href="http://es.wikipedia.org/wiki/RSA" target="_blank">RSA</a> de Wikipedia.</p><h2>Implementación.</h2><p>La aplicación de demostración de esta técnica requiere del uso de por lo menos los siguientes <em>namespaces</em>.</p><pre class="c#">using System;
using System.IO;
using System.Security;
using System.Security.Cryptography;</pre><h3>Proveedor del servicio de cifrado RSA.</h3><p>El núcleo de la implementación es el objeto <span
style="font-family: 'courier new', courier;">RSACryptoServiceProvider</span> que realiza las labores de cifrado/descifrado de información.</p><pre class="c#">public static RSACryptoServiceProvider rsa;</pre><h3>Establecer los valores iniciales del servicio.</h3><p>En este punto se establecen los valores iniciales de configuración del servicio, los cuales son en su mayoría opcionales, y se instancia el objeto mencionado anteriormente.</p><pre class="c#">const string CONTAINER_NAME = "ContenedorRSA";
CspParameters cspParams;
cspParams = new CspParameters(1);	// PROV_RSA_FULL
cspParams.Flags = CspProviderFlags.UseDefaultKeyContainer;
cspParams.KeyContainerName = CONTAINER_NAME;
// Instanciar el algoritmo de cifrado RSA
rsa = new RSACryptoServiceProvider(cspParams);</pre><h3>Generar las llaves.</h3><p>En esta etapa se crea una pareja de llaves: pública y privada, para las labores de cifrado.  Estas se almacenan por conveniencia en formato XML en los archivos <span
style="font-family: 'courier new', courier;">llave_publica.xml</span> y <span
style="font-family: 'courier new', courier;">llave_privada.xml</span> correspondientemente.</p><pre class="c#">// Generar y almacenar la llave pública
writer = new StreamWriter(@"llave_publica.xml");
string publicOnlyKeyXML = rsa.ToXmlString(false);
writer.Write(publicOnlyKeyXML);
writer.Close();
// Generar y almacenar la llave privada
writer = new StreamWriter(@"llave_privada.xml");
string publicPrivateKeyXML = rsa.ToXmlString(true);
writer.Write(publicPrivateKeyXML);
writer.Close();</pre><h3>Cargar las llaves.</h3><p>Una vez que han sido creadas y almacenadas las llaves, estas no deben ser creadas nuevamente.  Para su uso se cargan desde los correspondientes archivos XML y se asocian con el proveedor de cifrado.</p><pre class="c#">// Cargar y asociar la llave pública al proveedor de cifrado
StreamReader reader = new StreamReader(@"llave_publica.xml");
string publicOnlyKeyXML = reader.ReadToEnd();
rsa.FromXmlString(publicOnlyKeyXML);
reader.Close();
// Cargar y asociar la llave privada (y pública) al proveedor de cifrado
StreamReader reader = new StreamReader(@"llave_privada.xml");
string publicPrivateKeyXML = reader.ReadToEnd();
rsa.FromXmlString(publicPrivateKeyXML);
reader.Close();</pre><h3>Cifrar la información.</h3><p>Para realizar el <em>cifrado</em> de los datos es necesario contar con la <em>llave pública</em> del destinatario.</p><pre class="c#">cargarLlavePublica();
// Convertir el texto a cifrar (plano) a su representación en bytse
byte[] textoPlanoBytes = System.Text.Encoding.UTF8.GetBytes(textoPlano);
// Realizar el proceso de cifrado
byte[] textoCifradoBytes = rsa.Encrypt(textoPlanoBytes, false);
// Convertir el mensaje cifrado a su representación en cadena
string MensajeCifrado = Convert.ToBase64String(textoCifradoBytes);</pre><h3>Descifrar la información.</h3><p>Para <em>descifrar</em> los datos y obtener el mensaje original es necesario contar con la <em>llave privada</em> del destinatario del mensaje.</p><pre class="c#">cargarLlavePrivada();
// Convertir el texto cifrado a su representación en bytse
byte[] textoCifradoBytes = Convert.FromBase64String(textoCifrado);
// Realizar el proceso de descifrado
byte[] textoPlanoBytes = rsa.Decrypt(textoCifradoBytes, false);
// Convertir el mensaje descifrado a su representación en cadena
string MensajeDescifrado = System.Text.Encoding.UTF8.GetString(textoPlanoBytes);</pre><h2>Aplicación de demostración.</h2><div
id="attachment_11297" class="wp-caption aligncenter" style="width: 691px"><a
href="http://blog.jorgeivanmeza.com/wp-content/uploads/2010/11/MonoDevelop-External-Console_004.png"><img
class="size-full wp-image-11297" title="MonoDevelop External Console_004" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2010/11/MonoDevelop-External-Console_004.png" alt="Aplicación de demostración del uso del algoritmo " width="681" height="208" /></a><p
class="wp-caption-text">Aplicación de demostración del uso del algoritmo RSA</p></div><p><span
style="font-family: 'courier new', courier;">$ gmcs "/out:RSASample.exe" "/r:/usr/lib/mono/2.0/System.dll" /t:exe "RSASample/Main.cs"</span></p><h2>Enlaces.</h2><ul><li>Aplicación de demostración de cifrado asimétrico con RSA.<br
/> <a
href="http://demo.jorgeivanmeza.com/NET/RSASample/" target="_blank"> http://demo.jorgeivanmeza.com/NET/RSASample/</a></li><li>RSA en Wikipedia.<br
/> <a
href="http://es.wikipedia.org/wiki/RSA" target="_blank"> http://es.wikipedia.org/wiki/RSA</a></li><li>RSACryptoServiceProvider Class.<br
/> <a
href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx" target="_blank"> http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx</a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2010/11/cifrado-y-descifrado-asimetrico-con-rsa-utilizando-cmono/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Cifrado y descifrado simétrico con Rijndael (AES) utilizando C#/Mono</title><link>http://blog.jorgeivanmeza.com/2010/10/cifrado-y-descifrado-simetrico-con-rijndael-aes-utilizando-cmono/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cifrado-y-descifrado-simetrico-con-rijndael-aes-utilizando-cmono</link> <comments>http://blog.jorgeivanmeza.com/2010/10/cifrado-y-descifrado-simetrico-con-rijndael-aes-utilizando-cmono/#comments</comments> <pubDate>Sun, 31 Oct 2010 23:07:54 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Linux/Solaris/BSD]]></category> <category><![CDATA[Seguridad]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[AES]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[cifrado]]></category> <category><![CDATA[Hipergalaxia]]></category> <category><![CDATA[Mono]]></category> <category><![CDATA[Rijndael]]></category> <category><![CDATA[simétrico]]></category> <guid
isPermaLink="false">http://blog.jorgeivanmeza.com/?p=11068</guid> <description><![CDATA[Introducción. Advanced Encryption Standard (AES), también conocido como Rijndael (pronunciado "Rain Doll" en inglés), es un esquema de cifrado por bloques adoptado como un estándar de cifrado por el gobierno de los Estados Unidos. El AES fue anunciado por el &#8230; <a
href="http://blog.jorgeivanmeza.com/2010/10/cifrado-y-descifrado-simetrico-con-rijndael-aes-utilizando-cmono/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<h2>Introducción.</h2><div
style="padding-left: 30px;"><p><strong>Advanced Encryption Standard (AES)</strong>, también conocido como <strong>Rijndael</strong> (pronunciado "<em>Rain Doll</em>" en inglés), es un esquema de <strong>cifrado por bloques</strong> adoptado como un estándar de cifrado por el gobierno de los Estados Unidos. El AES fue anunciado por el Instituto Nacional de Estándares y Tecnología (NIST) como FIPS PUB 197 de los Estados Unidos (FIPS 197) el 26 de noviembre de 2001 después de un proceso de estandarización que duró 5 años.  Se transformó en un estándar efectivo el 26 de mayo de 2002. Desde 2006, el AES es uno de los algoritmos más populares usados en <strong>criptografía simétrica</strong>.</p><p>El cifrador fue desarrollado por dos criptólogos belgas, Joan Daemen y Vincent Rijmen, ambos estudiantes de la Katholieke Universiteit Leuven, y enviado al proceso de selección AES bajo el nombre "Rijndael".</p></div><p
style="text-align: right;">Tomado del artículo <em><a
href="http://es.wikipedia.org/wiki/Rijndael" target="_blank">Advanced Encryption Standard</a></em> de Wikipedia.</p><h2>Implementación con <em>strings</em>.</h2><p>La aplicación de demostración de esta técnica requiere del uso de por lo menos los siguientes <em>namespaces</em>.</p><pre class="c#">using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;</pre><h3>Establecer la <em>clave</em> y el <em>vector de inicio</em>.</h3><p>Estos valores pueden ser especificados manualmente o de manera automática por el <em>framework</em>.  La implementación para permitir que se definan automáticamente estos valores es la siguiente.</p><pre class="c#">Rijndael rijndael = Rijndael.Create();
byte[] key = rijndael.Key;
byte[] iv  = rijndael.IV;</pre><p>Es posible forzar la generación de nuevas claves y nuevos vectores de inicio para el algoritmo utilizando los métodos <span
style="font-family: 'courier new', courier;">rijndael.GenerateKey()</span> y <span
style="font-family: 'courier new', courier;">rijndael.GenerateIV()</span> respectivamente.</p><p>Si por el contrario se desea especificar estos valores manualmente su implementación es la siguiente siendo <span
style="font-family: 'courier new', courier;">strKey</span> y <span
style="font-family: 'courier new', courier;">strIv</span>, la clave y el vector de inicialización como cadenas de texto.</p><pre class="c#">byte[] key = UTF8Encoding.UTF8.GetBytes(strKey);
byte[] iv  = UTF8Encoding.UTF8.GetBytes(strIv);</pre><p>Especificando estos valores manualmente es necesario garantizar que sus longitudes sean válidas para el algoritmo.  En este caso se utilizará una longitud de clave de 32 bits y una longitud de vector de inicio de 16 bits.</p><pre class="c#">int keySize = 32;
int ivSize = 16;
Array.Resize(ref key, keySize);
Array.Resize(ref iv, ivSize);</pre><h3>Cifrado de cadenas de texto.</h3><p>Para cifrar la información se requiere de los siguientes parámetros.</p><ol><li>Cadena de texto con los datos a cifrar.</li><li>Clave.</li><li>Vector de inicio.</li></ol><p>El proceso retornará finalmente una cadena de texto con los datos cifrados.</p><pre class="c#">/**
 * Cifra una cadena texto con el algoritmo de Rijndael
 *
 * @param	plainMessage	mensaje plano (sin cifrar)
 * @param	Key		        clave del cifrado para Rijndael
 * @param	IV		        vector de inicio para Rijndael
 * @return	string		        texto cifrado
 */
public static string encryptString(String plainMessage, byte[] Key, byte[] IV)
{
    // Crear una instancia del algoritmo de Rijndael
    Rijndael RijndaelAlg = Rijndael.Create();
    // Establecer un flujo en memoria para el cifrado
    MemoryStream memoryStream = new MemoryStream();
    // Crear un flujo de cifrado basado en el flujo de los datos
    CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                 RijndaelAlg.CreateEncryptor(Key, IV),
                                                 CryptoStreamMode.Write);
    // Obtener la representación en bytes de la información a cifrar
    byte[] plainMessageBytes = UTF8Encoding.UTF8.GetBytes(plainMessage);
    // Cifrar los datos enviándolos al flujo de cifrado
    cryptoStream.Write(plainMessageBytes, 0, plainMessageBytes.Length);
    cryptoStream.FlushFinalBlock();
    // Obtener los datos datos cifrados como un arreglo de bytes
    byte[] cipherMessageBytes = memoryStream.ToArray();
    // Cerrar los flujos utilizados
    memoryStream.Close();
    cryptoStream.Close();
    // Retornar la representación de texto de los datos cifrados
    return Convert.ToBase64String(cipherMessageBytes);
}</pre><h3>Descifrado de cadenas de texto.</h3><p>El proceso inverso, el de descifrado, se realiza de manera antagónica.  Para hacerlo es necesario contar con los siguientes parámetros.</p><ol><li>Cadena de texto con los datos cifrados.</li><li>Clave.</li><li>Vector de inicio.</li></ol><p>El proceso retornará finalmente una cadena de texto con los datos descifrados.</p><pre class="c#">/**
 * Descifra una cadena texto con el algoritmo de Rijndael
 *
 * @param	encryptedMessage	mensaje cifrado
 * @param	Key			clave del cifrado para Rijndael
 * @param	IV			vector de inicio para Rijndael
 * @return	string			texto descifrado (plano)
 */
public static string decryptString(String encryptedMessage, byte[] Key, byte[] IV)
{
    // Obtener la representación en bytes del texto cifrado
    byte[] cipherTextBytes = Convert.FromBase64String(encryptedMessage);
    // Crear un arreglo de bytes para almacenar los datos descifrados
    byte[] plainTextBytes = new byte[cipherTextBytes.Length];
    // Crear una instancia del algoritmo de Rijndael
    Rijndael RijndaelAlg = Rijndael.Create();
    // Crear un flujo en memoria con la representación de bytes de la información cifrada
    MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
    // Crear un flujo de descifrado basado en el flujo de los datos
    CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                 RijndaelAlg.CreateDecryptor(Key, IV),
                                                 CryptoStreamMode.Read);
    // Obtener los datos descifrados obteniéndolos del flujo de descifrado
    int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
    // Cerrar los flujos utilizados
    memoryStream.Close();
    cryptoStream.Close();
    // Retornar la representación de texto de los datos descifrados
    return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}</pre><h2>Implementación con archivos.</h2><p>El cifrado y descifrado de mensajes en archivos se realiza de manera similar al expuesto anteriormente con cadenas, sin embargo varían los flujos (<em>streams</em>) utilizados para obtener y dirigir el flujo de la información.</p><h3>Cifrado a archivos.</h3><pre class="c#">/**
 * Cifra una cadena texto con el algoritmo de Rijndael y lo almacena en un archivo
 *
 * @param	plainMessage	mensaje plano (sin cifrar)
 * @param	filename	        nombre del archivo donde se almacenará el mensaje cifrado
 * @param	Key		        clave del cifrado para Rijndael
 * @param	IV		        vector de inicio para Rijndael
 * @return	void
 */
public static void encryptToFile(String plainMessage, String filename, byte[] Key, byte[] IV)
{
    // Crear un flujo para el archivo a generarse
    FileStream fileStream = File.Open(filename, FileMode.OpenOrCreate);
    // Crear una instancia del algoritmo Rijndael
    Rijndael RijndaelAlg = Rijndael.Create();
    // Crear un flujo de cifrado basado en el flujo de los datos
    CryptoStream cryptoStream = new CryptoStream(fileStream,
                                                 RijndaelAlg.CreateEncryptor(Key, IV),
                                                 CryptoStreamMode.Write);
    // Crear un flujo de escritura basado en el flujo de cifrado
    StreamWriter streamWriter = new StreamWriter(cryptoStream);
    // Cifrar el mensaje a través del flujo de escritura
    streamWriter.WriteLine(plainMessage);
    // Cerrar los flujos utilizados
    streamWriter.Close();
    cryptoStream.Close();
    fileStream.Close();
}</pre><h3>Descifrado de archivos.</h3><pre class="c#">/**
 * Descifra el contenido de un archivo con el algoritmo de Rijndael y lo retorna
 * como una cadena de texto plano
 *
 * @param	filename		nombre del archivo donde se encuentra el mensaje cifrado
 * @param	Key			clave del cifrado para Rijndael
 * @param	IV			vector de inicio para Rijndael
 * @return	string			mensaje descifrado (plano)
 */
public static string decryptFromFile(String filename, byte[] Key, byte[] IV)
{
    // Crear un flujo para el archivo a generarse
    FileStream fileStream = File.Open(filename, FileMode.OpenOrCreate);
    // Crear una instancia del algoritmo Rijndael
    Rijndael RijndaelAlg = Rijndael.Create();
    // Crear un flujo de cifrado basado en el flujo de los datos
    CryptoStream cryptoStream = new CryptoStream(fileStream,
                                                 RijndaelAlg.CreateDecryptor(Key, IV),
                                                 CryptoStreamMode.Read);
    // Crear un flujo de lectura basado en el flujo de cifrado
    StreamReader streamReader = new StreamReader(cryptoStream);
    // Descifrar el mensaje a través del flujo de lectura
    string plainMessage = streamReader.ReadLine();
    // Cerrar los flujos utilizados
    streamReader.Close();
    cryptoStream.Close();
    fileStream.Close();
    return plainMessage;
}</pre><h2>Aplicación de demostración.</h2><p>La <a
href=" http://demo.jorgeivanmeza.com/NET/Rijndael-AES-Sample/" target="_blank">aplicación de demostración</a> incluye los conceptos y el código expuestos en este artículo.  Con ella es posible cifrar y descifrar un mensaje que consiste en una cadena de texto arbitraria en memoria y en un archivo.</p><div
id="attachment_11136" class="wp-caption aligncenter" style="width: 699px"><a
href="http://blog.jorgeivanmeza.com/wp-content/uploads/2010/10/MonoDevelop-External-Console_003.png"><img
class="size-full wp-image-11136" title="MonoDevelop External Console_003" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2010/10/MonoDevelop-External-Console_003.png" alt="Aplicación de demostración del uso del algoritmo Rijndael" width="689" height="191" /></a><p
class="wp-caption-text">Aplicación de demostración del uso del algoritmo Rijndael</p></div><h3>Construír la aplicación.</h3><p>La aplicación de demostración puede construírse utilizando la solución incluída en la distribución con MonoDevelop o Visual Studio.  También es posible construírla desde línea de comando (Mono) mediante la siguiente instrucción.</p><p><span
style="font-family: 'courier new', courier;">$ gmcs "/out:RijndaelSample.exe" "/r:/usr/lib/mono/2.0/System.dll" /t:exe "RijndaelSample/Main.cs"</span></p><h2>Enlaces.</h2><ul><li>Aplicación de demostración del cifrado Rijndael (AES) de cadenas y archivos.<br
/> <a
href="http://demo.jorgeivanmeza.com/NET/Rijndael-AES-Sample/" target="_blank"> http://demo.jorgeivanmeza.com/NET/Rijndael-AES-Sample/</a></li><li>Advanced Encryption Standard &#8211; AES (Rijndael).<br
/> <a
href="http://es.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank"> http://es.wikipedia.org/wiki/Advanced_Encryption_Standard</a></li><li>AES Algoritm information.<br
/> <a
href="http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html" target="_blank"> http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html</a></li><li>Rijndael Class en MSDN.<br
/> <a
href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx</a></li><li>How To: Encrypt and Decrypt Data Using a Symmetric (Rijndael) Key (C#/VB.NET).<br
/> <a
href="http://www.obviex.com/samples/Encryption.aspx" target="_blank"> http://www.obviex.com/samples/Encryption.aspx</a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2010/10/cifrado-y-descifrado-simetrico-con-rijndael-aes-utilizando-cmono/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Calculando hashes (MD5 y SHA1) con C#/Mono</title><link>http://blog.jorgeivanmeza.com/2010/10/calculando-hashes-md5-y-sha1-con-cmono/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=calculando-hashes-md5-y-sha1-con-cmono</link> <comments>http://blog.jorgeivanmeza.com/2010/10/calculando-hashes-md5-y-sha1-con-cmono/#comments</comments> <pubDate>Sat, 30 Oct 2010 22:44:37 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Linux/Solaris/BSD]]></category> <category><![CDATA[Seguridad]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[hash]]></category> <category><![CDATA[Hipergalaxia]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[MD5]]></category> <category><![CDATA[Mono]]></category> <category><![CDATA[SHA1]]></category> <guid
isPermaLink="false">http://blog.jorgeivanmeza.com/?p=11042</guid> <description><![CDATA[Introducción. Una función de hashing recibe un bloque de datos arbitrarios y genera de manera determinística un arreglo de bytes con el valor de su hash, el cual tiene como característica el ser único para los datos procesados. Los valores &#8230; <a
href="http://blog.jorgeivanmeza.com/2010/10/calculando-hashes-md5-y-sha1-con-cmono/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<h2>Introducción.</h2><p>Una función de <em>hashing</em> recibe un bloque de datos arbitrarios y genera de manera determinística un arreglo de bytes con el valor de su <em>hash</em>, el cual tiene como característica el ser único para los datos procesados.</p><p>Los valores de <em>hash</em> tienen múltiples usos, entre ellos se utilizan en la criptografía para garantizar que la información de un mensaje no ha sido modificada.  Con este mismo uso, comúnmente se utiliza para determinar si la descarga de archivos ha sido exitosa o no (<span
style="font-family: 'courier new', courier;"><a
href="http://en.wikipedia.org/wiki/Md5sum" target="_blank">md5sum</a></span>).</p><p>Existen varios algortimos de <em>hashing</em>, los mas conocidos son <a
href="http://en.wikipedia.org/wiki/MD5" target="_blank">MD5</a> de 128 bits y <a
href="http://en.wikipedia.org/wiki/SHA-1" target="_blank">SHA1</a> de 160 bits.  El primero de ellos es muy utilizado actualmente, especialmente para el almacenamiento de contraseñas, sin embargo ya no se considera seguro por lo cual es conveniente utilizar el segundo mencionado.</p><h2>Implementación en C#/Mono.</h2><p>Para la implementaciones que se describen a continuación se utilizaron los siguientes <em>namespaces</em>.</p><pre class="c#">using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;</pre><h3>Calcular el <em>hash</em> de una cadena.</h3><p>El primer paso es crear instancias de los algoritmos de <em>hashing</em>.</p><pre class="c#">HashAlgorithm md5  = HashAlgorithm.Create("MD5");
HashAlgorithm sha1 = HashAlgorithm.Create("SHA1");</pre><p>Posteriormente se calcula el valor del <em>hash</em> de la cadena texto (<span
style="font-family: 'courier new', courier;">text</span>) especificada.</p><pre class="c#">Byte[] md5Data  = md5.ComputeHash(UTF8Encoding.UTF8.GetBytes(text));
Byte[] sha1Data = sha1.ComputeHash(UTF8Encoding.UTF8.GetBytes(text));</pre><p>Finalmente su valor puede ser manipulado o entregado al usuario.</p><pre class="c#">Console.WriteLine("MD5:  " + BitConverter.ToString(md5Data).Replace("-", ""));
Console.WriteLine("SHA1: " + BitConverter.ToString(sha1Data).Replace("-", ""));</pre><h3>Calcular el <em>hash</em> de un archivo.</h3><p>El procedimiento es muy similar al cálculo de <em>hash</em> de una cadena, pero a diferencia de este, los datos provienen de un flujo de archivo al cual se le calcula su valor.</p><pre class="c#">FileStream fs = File.OpenRead(filename);
md5Data  = md5.ComputeHash(fs);
sha1Data = sha1.ComputeHash(fs);
fs.Close ();</pre>]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2010/10/calculando-hashes-md5-y-sha1-con-cmono/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Georreferenciando de manera fácil y simple con GeoNames utilizando C#/Mono</title><link>http://blog.jorgeivanmeza.com/2010/10/georreferenciando-de-manera-facil-y-simple-con-geonames-utilizando-cmono/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=georreferenciando-de-manera-facil-y-simple-con-geonames-utilizando-cmono</link> <comments>http://blog.jorgeivanmeza.com/2010/10/georreferenciando-de-manera-facil-y-simple-con-geonames-utilizando-cmono/#comments</comments> <pubDate>Fri, 22 Oct 2010 19:00:22 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Linux/Solaris/BSD]]></category> <category><![CDATA[Software geográfico]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[geocodificación]]></category> <category><![CDATA[GeoNames]]></category> <category><![CDATA[georreferenciación]]></category> <category><![CDATA[Hipergalaxia]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[Mono]]></category> <category><![CDATA[servicio web]]></category> <guid
isPermaLink="false">http://blog.jorgeivanmeza.com/?p=10597</guid> <description><![CDATA[Introducción. Últimamente he tenido ganas de desarrollar en C# para retomar este lenguaje que tengo un poco abandonado y al mismo tiempo probar los avances que ha tenido el proyecto Mono.  Que mejor inicio que desarrollar una aplicación muy simple &#8230; <a
href="http://blog.jorgeivanmeza.com/2010/10/georreferenciando-de-manera-facil-y-simple-con-geonames-utilizando-cmono/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<h2>Introducción.</h2><p>Últimamente he tenido ganas de desarrollar en C# para retomar este lenguaje que tengo un poco abandonado y al mismo tiempo probar los avances que ha tenido el <a
href="http://www.mono-project.com/" target="_blank">proyecto Mono</a>.  Que mejor inicio que desarrollar una aplicación muy simple para georreferenciar ciudades aprovechando el servicio web de <a
href="http://www.geonames.org/" target="_blank">Geonames</a>, esta a su vez me servirá para complementarla y solucionar un problema de información que tengo para otro proyecto.</p><p>Como se podrá apreciar, el código es muy sencillo ya que no utilizo ninguna librería adicional a las estándar, sin embargo es interesante y puede serle de utilidad a alguien mas.</p><h2>Cuál es la necesidad ?</h2><p>El problema que se tiene es la necesidad de georreferenciar ubicaciones, es decir, conociendo su nombre obtener su ubicación en términos de latitud y longitud.</p><p
style="padding-left: 30px;">Si estoy en <strong>Manizales, Caldas, Colombia</strong> estaré realmente en <a
href="http://maps.google.com/maps/api/staticmap?&amp;amp;zoom=7&amp;amp;size=300x450&amp;amp;sensor=false&amp;amp;markers=color:blue|label:X|5.07,-75.52056" target="_blank"><strong>latitud 5.07, longitud -75.52056</strong></a>.</p><p>Es necesario tener en cuenta que muchas veces el servicio de georreferenciación retorna múltiples resultados ya que pueden haberse referenciado varios sitios con el mismo nombre, haberse cambiado el nombre de la ubicación o tenerse varios hitos de diferente nivel administrativo.  En Geonames esto último se identifica mediante los campos de características.  Consulte el sitio web de Geonames para mas información acerca de los <a
href="http://www.geonames.org/export/codes.html" target="_blank"><em>feature codes</em></a>.</p><h2>Cómo es el servicio web ?</h2><p>El <a
href="http://www.geonames.org/export/geonames-search.html" target="_blank">servicio web de búsquedas de Geonames</a> recibe una cadena de texto con la ubicación que se desea georreferenciar y retorna una cadena de texto en formato XML (en este caso) con los resultados obtenidos.</p><p>Por ejemplo, la consulta de <strong>Manizales, Caldas, Colombia</strong> se realizaría a través del siguiente URL.</p><p
style="padding-left: 30px;"><a
href="http://ws.geonames.org/search?lang=es&amp;type=xml&amp;style=FULL&amp;q=Manizales,Caldas,Colombia" target="_blank">http://ws.geonames.org/search?lang=es&amp;type=xml&amp;style=FULL&amp;q=Manizales,Caldas,Colombia</a></p><p>Retornará el siguiente resultado.</p><pre class="xml">&lt;geonames style="FULL"&gt;
    &lt;totalResultsCount&gt;2&lt;/totalResultsCount&gt;
    &lt;geoname&gt;
        &lt;toponymName&gt;Manizales&lt;/toponymName&gt;
        &lt;name&gt;Manizales&lt;/name&gt;
        &lt;lat&gt;5.07&lt;/lat&gt;
        &lt;lng&gt;-75.52056&lt;/lng&gt;
        &lt;geonameId&gt;3675443&lt;/geonameId&gt;
        &lt;countryCode&gt;CO&lt;/countryCode&gt;
        &lt;countryName&gt;Colombia&lt;/countryName&gt;
        &lt;fcl&gt;P&lt;/fcl&gt;
        &lt;fcode&gt;PPLA&lt;/fcode&gt;
        &lt;fclName&gt;city, village,...&lt;/fclName&gt;
        &lt;fcodeName&gt;seat of a first-order administrative division&lt;/fcodeName&gt;
        &lt;population&gt;357814&lt;/population&gt;
        &lt;alternateNames&gt;Manisales,Manisalesas,Manizales,Манисалес&lt;/alternateNames&gt;
        &lt;elevation/&gt;
        &lt;continentCode&gt;SA&lt;/continentCode&gt;
        &lt;adminCode1&gt;37&lt;/adminCode1&gt;
        &lt;adminName1&gt;Caldas&lt;/adminName1&gt;
        &lt;adminCode2/&gt;
        &lt;adminName2/&gt;
        &lt;alternateName lang="en"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="pl"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="lt"&gt;Manisalesas&lt;/alternateName&gt;
        &lt;alternateName lang="bg"&gt;Манисалес&lt;/alternateName&gt;
        &lt;alternateName lang="cs"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="link"&gt;http://en.wikipedia.org/wiki/Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="de"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="sv"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="es"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="no"&gt;Manizales&lt;/alternateName&gt;
        &lt;alternateName lang="pt"&gt;Manizales&lt;/alternateName&gt;
        &lt;timezone dstOffset="-5.0" gmtOffset="-5.0"&gt;America/Bogota&lt;/timezone&gt;
        &lt;score&gt;1.0&lt;/score&gt;
    &lt;/geoname&gt;
    &lt;geoname&gt;
        &lt;toponymName&gt;Manizales&lt;/toponymName&gt;
        &lt;name&gt;Manizales&lt;/name&gt;
        &lt;lat&gt;5.08333&lt;/lat&gt;
        &lt;lng&gt;-75.5&lt;/lng&gt;
        &lt;geonameId&gt;3675444&lt;/geonameId&gt;
        &lt;countryCode&gt;CO&lt;/countryCode&gt;
        &lt;countryName&gt;Colombia&lt;/countryName&gt;
        &lt;fcl&gt;A&lt;/fcl&gt;
        &lt;fcode&gt;ADM2&lt;/fcode&gt;
        &lt;fclName&gt;country, state, region,...&lt;/fclName&gt;
        &lt;fcodeName&gt;second-order administrative division&lt;/fcodeName&gt;
        &lt;population/&gt;
        &lt;alternateNames/&gt;
        &lt;elevation/&gt;
        &lt;continentCode&gt;SA&lt;/continentCode&gt;
        &lt;adminCode1&gt;37&lt;/adminCode1&gt;
        &lt;adminName1&gt;Caldas&lt;/adminName1&gt;
        &lt;adminCode2&gt;3675444&lt;/adminCode2&gt;
        &lt;adminName2&gt;Manizales&lt;/adminName2&gt;
        &lt;timezone dstOffset="-5.0" gmtOffset="-5.0"&gt;America/Bogota&lt;/timezone&gt;
        &lt;score&gt;0.3448537290096283&lt;/score&gt;
    &lt;/geoname&gt;
&lt;/geonames&gt;</pre><p>Finalmente la tarea de la aplicación que consuma el servicio será procesar el documento XML y obtener la información que necesite.</p><h2>Cómo es la implementación ?</h2><p>Las librerías (<em>namespaces</em>) utilizados son los siguientes.</p><pre class="c#">using System;
using System.Net;
using System.Text;
using System.Xml;
using System.Collections.Generic;</pre><p>Se prepara el URL para consumir el servicio con la ubicación a geocodificar.  En este caso, especifico una por defecto si no suministra una.</p><pre class="c#">string location = (args.Length == 0) ? "Manizales, Caldas, Colombia" : args[0];
string url = "http://ws.geonames.org/search?lang=es&amp;type=xml&amp;style=FULL&amp;q=" + location;</pre><p>Se consume el servicio web y se obtiene la cadena de texto con la respuesta en formato XML.</p><pre class="c#">WebClient client = new WebClient();
string xml = client.DownloadString(url);</pre><p>Se crea un objeto para manipular el documento XML recién recibido, se obtienen los nodos relacionados con la respuesta de la georreferenciación (<span
style="font-family: courier new,courier;">geoname</span>)  y se verifica que haya registros, de lo contrario no habrá nada que hacer.</p><pre class="c#">XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeList geonames = doc.GetElementsByTagName("geoname");
if(geonames.Count == 0)
 throw new Exception("There is no geonames in the result!");
else
 Console.WriteLine("I found " + geonames.Count + " places!\n");
</pre><p>Se recorren los resultados obtenidos extrayéndoles la información georreferenciada que se requiera.</p><pre class="c#">foreach(XmlElement place in geonames)
{
 Console.WriteLine("* LUGAR: " + place["name"].InnerText + "\n");
 Console.WriteLine("\tNombre: "          + place["name"].InnerText);
 Console.WriteLine("\tDepartamento: "    + place["adminName1"].InnerText);
 Console.WriteLine("\tLatitud: "         + place["lat"].InnerText);
 Console.WriteLine("\tLongitud: "        + place["lng"].InnerText);
 Console.WriteLine("\tPaís: "            + place["countryName"].InnerText +
                   " (" + place["countryCode"].InnerText + ")");
 Console.WriteLine("\tPoblación: "       + place["population"].InnerText + " habitantes");
 Console.WriteLine("\tPaís: "            + place["countryName"].InnerText +
                   " (" + place["countryCode"].InnerText + ")");
 Console.WriteLine("\tCaracterísticas: " + place["fcl"].InnerText + "/" + place["fcode"].InnerText +
                   "&gt; " + place["fclName"].InnerText + " (" + place["fcodeName"].InnerText + ")");
 Console.WriteLine();
}
</pre><h2>Cómo construyo el programa ?</h2><p>Si se utiliza VisualStudio/MonoDevelop sólo es necesario abrir la solución (incluída en el paquete de demostración) y ejecutar el comando de <em>Build</em> o <em>Run</em> del menú.</p><p>Si se desea realizar manualmente deberá ejecutarse un comando como el siguiente.</p><p><span
style="font-family: courier new,courier;">$ gmcs "/out:<strong>GeoCoderSimple.exe</strong>" "/r:/usr/lib/mono/2.0/System.dll" "/r:/usr/lib/mono/2.0/System.Xml.dll" /t:exe "<strong>geonames_search_raw/Main.cs</strong>"</span></p><p>Donde <span
style="font-family: courier new,courier;">geonames_search_raw/Main.cs</span> es el código fuente de la aplicación y <span
style="font-family: courier new,courier;">GeoCoderSimple.exe</span> será el archivo binario resultante.</p><h2>Cómo ejecuto el ejemplo ?</h2><p>Ya sea invocándolo desde el IDE o desde línea de comando, el programa recibe un argumento.  En caso de obviarse este argumento se utilizará el valor por defecto.</p><p><span
style="font-family: courier new,courier;">$ ./GeoCoderSimple.exe</span></p><pre>I found 2 places!
* LUGAR: Manizales
 Nombre: Manizales
 Departamento: Caldas
 Latitud: 5.07
 Longitud: -75.52056
 País: Colombia (CO)
 Población: 357814 habitantes
 País: Colombia (CO)
 Características: P/PPLA&gt; city, village,... (seat of a first-order administrative division)
* LUGAR: Manizales
 Nombre: Manizales
 Departamento: Caldas
 Latitud: 5.08333
 Longitud: -75.5
 País: Colombia (CO)
 Población:  habitantes
 País: Colombia (CO)
 Características: A/ADM2&gt; country, state, region,... (second-order administrative division)
</pre><h2>Enlaces.</h2><ul><li>Geonames.<br
/> <a
href="http://www.geonames.org/" target="_blank">http://www.geonames.org/</a></p><ul><li>Search Web Service.<br
/> <a
href="http://www.geonames.org/export/geonames-search.html" target="_blank">http://www.geonames.org/export/geonames-search.html</a></li></ul></li><li>Código fuente de la aplicación de ejemplo (C#/Mono/MonoDevelop).<br
/> <a
href="http://demo.jorgeivanmeza.com/NET/GeonamesSearchRaw/" target="_blank">http://demo.jorgeivanmeza.com/NET/GeonamesSearchRaw/</a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2010/10/georreferenciando-de-manera-facil-y-simple-con-geonames-utilizando-cmono/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Instalar el ambiente de desarrollo básico C/C++ en GNU Linux Ubuntu 10.04 y ArchLinux 2010.05</title><link>http://blog.jorgeivanmeza.com/2010/08/instalar-el-ambiente-de-desarrollo-basico-cc-en-gnu-linux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=instalar-el-ambiente-de-desarrollo-basico-cc-en-gnu-linux</link> <comments>http://blog.jorgeivanmeza.com/2010/08/instalar-el-ambiente-de-desarrollo-basico-cc-en-gnu-linux/#comments</comments> <pubDate>Mon, 02 Aug 2010 17:24:52 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Linux/Solaris/BSD]]></category> <category><![CDATA[ArchLinux]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[gcc]]></category> <category><![CDATA[Hipergalaxia]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[Ubuntu]]></category> <guid
isPermaLink="false">http://blog.jorgeivanmeza.com/?p=6824</guid> <description><![CDATA[Ubuntu. $ sudo aptitude install build-essential ArchLinux. # pacman -S base-devel]]></description> <content:encoded><![CDATA[<h2>Ubuntu.</h2><p><span
style="font-family: courier new,courier;">$ sudo aptitude install build-essential</span></p><h2>ArchLinux.</h2><p><span
style="font-family: courier new,courier;"># pacman -S base-devel</span></p> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2010/08/instalar-el-ambiente-de-desarrollo-basico-cc-en-gnu-linux/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Aprendiendo punteros con Binky</title><link>http://blog.jorgeivanmeza.com/2009/01/aprendiendo-punteros-con-binky/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=aprendiendo-punteros-con-binky</link> <comments>http://blog.jorgeivanmeza.com/2009/01/aprendiendo-punteros-con-binky/#comments</comments> <pubDate>Mon, 19 Jan 2009 05:30:54 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[Pointers]]></category> <guid
isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1148</guid> <description><![CDATA[]]></description> <content:encoded><![CDATA[<p
style="text-align: center;"><object
width="512" height="322" data="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash"><param
name="allowFullScreen" value="true" /><param
name="AllowScriptAccess" value="always" /><param
name="bgcolor" value="#000000" /><param
name="flashVars" value="id=2387613&amp;vid=409141&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/i/us/sch/cn/v/v1/w175/409141_400_300.jpeg&amp;embed=1" /><param
name="src" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param
name="flashvars" value="id=2387613&amp;vid=409141&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/i/us/sch/cn/v/v1/w175/409141_400_300.jpeg&amp;embed=1" /><param
name="allowfullscreen" value="true" /></object></p> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2009/01/aprendiendo-punteros-con-binky/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Utilizando el Wiimote con C#:  parte II</title><link>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=utilizando-el-wiimote-con-c-parte-ii</link> <comments>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/#comments</comments> <pubDate>Sat, 13 Dec 2008 19:44:15 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[Wiimote]]></category> <category><![CDATA[WiimoteLib]]></category> <guid
isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1052</guid> <description><![CDATA[Introducción. Antes de publicar el código fuente del HelloWii, decidí hacer un poco de refactory obteniendo los siguientes productos y conclusiones. La clase WiiController que es un recubrimiento (wrapper) de la librería WiimoteLib y que simplifica su acceso.  Está desarrollada &#8230; <a
href="http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<h3><p><div
id="attachment_1053" class="wp-caption aligncenter" style="width: 886px"><a
href="http://blog.jorgeivanmeza.com/wp-content/uploads/2008/12/hellowiiscreenshot.png"><img
class="size-full wp-image-1053" title="hellowiiscreenshot" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2008/12/hellowiiscreenshot.png" alt="HelloWii 0.1 screenshot" width="876" height="548" /></a><p
class="wp-caption-text">HelloWii 0.1 screenshot</p></div></h3><h3>Introducción.</h3><p>Antes de publicar el código fuente del <a
href="http://blog.jorgeivanmeza.com/2008/12/11/utilizando-el-wiimote-con-csharp/" target="_blank">HelloWii</a>, decidí hacer un poco de <em>refactory</em> obteniendo los siguientes productos y conclusiones.</p><ul><li>La clase <span
style="font-family: courier new,courier;">WiiController</span> que es un recubrimiento (<em>wrapper</em>) de la librería <a
href="http://www.wiimotelib.org/" target="_blank">WiimoteLib</a> y que simplifica su acceso.  Está desarrollada en C#.</li><li>Se utilizó el patrón observador (interfaz <span
style="font-family: courier new,courier;">WiiControllerObserver</span>) para permitirle a los interesados registrarse con el control para ser notificados de sus cambios de estado.  De igual manera es posible obtener información de este por demanda.</li><li>Si el observador es el mismo componente de UI (<span
style="font-family: courier new,courier;">Form</span> por ejemplo) es recomendable remover el registro del observador (<span
style="font-family: courier new,courier;">unregisterObserver</span>) antes de cerrar/destruír la componente/aplicación y evitar así excepciones generadas durante intentos de actualización mientras se cierra el componente.</li><li>Se adaptó la aplicación de demostración para utilizar a un objeto <span
style="font-family: courier new,courier;">WiiController</span> como interfaz en lugar de utilizar a la librería directamente.</li><li>Con el rediseño se esperaba evitar el problema del <em>cross-threading</em> pero no fue posible.</li></ul><p>Como se mencionó no fue posible obviar la situación generada por la ejecución de instrucciones entre distintos hilos: la interfaz de usuario y la librería de acceso al wiimote que genera los problemas y <a
href="http://www.yoda.arachsys.com/csharp/threads/winforms.shtml" target="_blank">explicación</a> ya fueron expuestos.  Sin embargo, revisando el <a
href="http://www.wiimoteproject.com/wiimote-and-bluetooth-connectivity/i-cant-get-my-*insert-johnnys-app-name-here*-to-connect-help!/" target="_blank">foro de WiimoteProject</a> encontré que es posible indicarle al componente visual de .NET que se encuentre accediendo a la librería (inclusive indirectamente a través de <span
style="font-family: courier new,courier;">WiiController</span>) que ignore este tipo de accesos ilegales entre hilo al evitando su revisión, esto se logra agregando la siguiente instrucción al constructor del componente.</p><pre name='code' class='csharp'>CheckForIllegalCrossThreadCalls = false;</pre><h3>API de la clase WiiController.</h3><p>La clase <span
style="font-family: courier new,courier;">WiiController</span> cuenta con los siguientes métodos.</p><ul><li>public void <strong>connect</strong>() &#8211; Creates the conexion with the wiimote.</li><li>public void <strong>disconnect</strong>() &#8211; Makes the disconnection of the wiimote..</li><li>public bool <strong>isConnected</strong>() &#8211; Checks if the wiimote has been already connected..</li></ul><ul><li>public void <strong>refreshStatus</strong>(WiimoteState source) &#8211; Updates the references to the internal information of the wiimote.</li><li>public void <strong>setReportType</strong>(WiimoteLib.InputReport type) &#8211; Selects the the type of information report that is expected from the controller.</li></ul><ul><li>public float <strong>getBattery</strong>() &#8211; Gets the battery level of the wiimote.</li></ul><ul><li>public String <strong>getId</strong>() &#8211; Gets the ID of the controller.</li></ul><ul><li>public bool[] <strong>getAllButtonsStatus</strong>() &#8211; State of all buttons of the wiimote.</li><li>public bool <strong>getButtonStatus</strong>(String name) &#8211; The status of a button on the wiimote.</li></ul><ul><li>public bool[] <strong>getAllLedsStatus</strong>() &#8211; The status of all leds of the wiimote.</li><li>public bool <strong>getLedStatus</strong>(int id) &#8211; The status of an individual led.</li><li>public void <strong>setLeds</strong>(bool l1, bool l2, bool l3, bool l4) &#8211; Change the state of the wiimote's leds.</li><li>public void <strong>setLeds</strong>(bool[] leds) &#8211; Change the state of the wiimote's leds.</li><li>public void <strong>turnLed</strong>(int index, bool status) &#8211; Change the state of an individual led.</li></ul><ul><li>public int[] <strong>getAcceleration</strong>() &#8211; Obtains the acceleration of the wiimote.</li><li>public int <strong>getAcceleration</strong>(String axis) &#8211; Obtains the acceleration of the wiimote.</li></ul><ul><li>public bool <strong>isRumbling</strong>() &#8211; Checks if the rumbling device is active.</li><li>public void <strong>rumble</strong>(bool status) &#8211; Change the state of the wiimote's rumbling device.</li></ul><ul><li>public bool <strong>isObserver</strong>(WiiControllerObserver observer) &#8211; Checks if an observer is already registered.</li><li>public bool <strong>registerObserver</strong>(WiiControllerObserver observer) &#8211; Register a new observer on the controller.</li><li>public bool <strong>unregisterObserver</strong>(WiiControllerObserver observer) &#8211; Unregister an observer from the controller.</li></ul><ul><li>public bool <strong>isExtensionConnected</strong>() &#8211; Checks if a wiimote's extension is connected.</li><li>public String <strong>getExtensionTypeConnected</strong>() &#8211; Get the type name of the connected extension.</li></ul><ul><li>public int[] <strong>getNunchukAcceleration</strong>() &#8211; Get the acceleration of the nunchuk extension.</li><li>public int <strong>getNunchukAcceleration</strong>(String axis) &#8211; Get the acceleration of the nunchuk extension.</li></ul><ul><li>public bool[] <strong>getAllNunchukButtonsStatus</strong>() &#8211; Get the state of the buttons on the nunchuk extension.</li><li>public bool <strong>getNunchukButtonStatus</strong>(String name) &#8211; Get the state of a button on the nunchuk extension.</li></ul><ul><li>public int[] <strong>getNunchukJoystick</strong>() &#8211; Get the joystick state on the nunchuk extension.</li><li>public int <strong>getNunchukJoystick</strong>(String axis) &#8211; Get the joystick value on a selected axis from the nunchuk extension.</li></ul><p>Para mas información acerca del API de la clase y de su respectiva utilización consulte la documentación del código fuente inmersa en el archivo <span
style="font-family: courier new,courier;">WiiController.cs </span>y en <span
style="font-family: courier new,courier;">WiiForm.cs</span> (aplicación de demostración).</p><h3>Registrar observadores.</h3><p>Para registrarse como observador de eventos del wiimote la clase debe implementar la interfaz <span
style="font-family: courier new,courier;">jimezam.wii.controller.WiiControllerObserver</span>.  Esta interfaz obliga a que se implementen los siguientes métodos.</p><ul><li>void <strong>update</strong>() &#8211; Invoked when the status of the wiimote is changed.</li><li>void <strong>updateExtension</strong>() -Invoked when an extension is connected/disconnected to the wiimote.</li></ul><p>La manipulación del registro de un observador se realiza utilizando los métodos <span
style="font-family: courier new,courier;"><strong>registerObserver </strong></span>y <span
style="font-family: courier new,courier;"><strong>unregisterObserver </strong></span>de la clase <span
style="font-family: courier new,courier;">WiiController </span>descritos anteriormente.</p><h3>Enlaces.</h3><ul><li>Fuentes y binarios de la clase <span
style="font-family: courier new,courier;">WiiController </span>y la aplicación de demostración HelloWii.<a
href="http://demo.jorgeivanmeza.com/NET/WiiController/" target="_blank"><p>http://demo.jorgeivanmeza.com/NET/WiiController/</a></li></ul> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Selección de Debug/Release en Visual C# Express 2008</title><link>http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=seleccion-de-debugrelease-en-visual-c-express-2008</link> <comments>http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/#comments</comments> <pubDate>Sat, 13 Dec 2008 03:25:08 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[Visual Studio Express]]></category> <guid
isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1047</guid> <description><![CDATA[Esta semana, gracias a las pruebas con el Wiimote he vuelto a trabajar con C#, esta vez con utilizando el Visual C# Express 2008.  Encontré un problema, cuando quise generar la versión final de la aplicación no pude encontrar la &#8230; <a
href="http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>Esta semana, gracias a las pruebas con el Wiimote he vuelto a trabajar con C#, esta vez con utilizando el Visual C# Express 2008.  Encontré un problema, cuando quise generar la versión final de la aplicación no pude encontrar la opción que me permitiera elegir entre las presentaciones <em>Debug</em>/<em>Release</em> del ejecutable generado.</p><p>Buscando en Internet encontré que hay dos formas de hacerlo.</p><ol><li>Presionando <strong>F5</strong> se construye el ejecutable en modo <strong><em>Debug</em></strong>, presionando <strong>CTRL+F5</strong> se construye el ejecutable en modo <strong><em>Release</em></strong>.</li><li>Si realmente se desea tener visible el menú que le permita seleccionar el modo del ejecutable y la CPU objetivo realice los siguientes pasos.</li></ol><blockquote><ul><li>Elija el menú <strong>Tools </strong>&gt; <strong>Options</strong>.</li><li>Seleccione la casilla de verificación <strong>Show all settings</strong> en la parte inferior izquierda.</li><li>Seleccione la rama <strong>Projects and solutions</strong> &gt; <strong>General</strong>.</li><li>Selecciona la casilla de verificación <strong>Show advanced build configurations</strong>.</li><li>Presione el botón <strong>OK</strong> para aceptar los cambios.</li></ul></blockquote><p><a
href="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/debug-release-bar.png"><img
class="aligncenter size-full wp-image-1048" title="debug-release-bar" src="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/debug-release-bar.png" alt="debug-release-bar" width="279" height="27" /></a></p> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Utilizando el Wiimote con C#</title><link>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=utilizando-el-wiimote-con-csharp</link> <comments>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/#comments</comments> <pubDate>Thu, 11 Dec 2008 15:34:14 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[Wiimote]]></category> <category><![CDATA[WiimoteLib]]></category> <guid
isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1031</guid> <description><![CDATA[Introducción. Hace unos dias me prestaron un control de Wii (que si funcionaba) y tuve un par de noches para jugar con el.  Hice una aplicación muy sencilla para experimentar como acceder a la información provista por el control y &#8230; <a
href="http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<div
id="attachment_1032" class="wp-caption alignleft" style="width: 210px"><img
class="size-full wp-image-1032 " title="wiimoteaxis" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2008/12/wiimoteaxis.gif" alt="Ejes del Wiimote - tomado de http://wiimotecommande.sf.net/" width="200" height="168" /><p
class="wp-caption-text">Ejes del Wiimote - tomado de http://wiimotecommande.sf.net/</p></div><h3>Introducción.</h3><p>Hace unos dias me prestaron un control de Wii (que si funcionaba) y tuve un par de noches para jugar con el.  Hice una aplicación muy sencilla para experimentar como acceder a la información provista por el control y como utilizar algunos de sus recursos.</p><p>La aplicación de demostración se realizó utilizando la librería <a
href="http://www.wiimotelib.org/" target="_blank">WiimoteLib</a> de <a
href="http://www.brianpeek.com/" target="_blank">Brian Peek</a> y <a
href="http://www.microsoft.com/express/vcsharp/" target="_blank">Visual C# Express</a> bajo Windows Vista (utilizando la pila de <a
href="http://en.wikipedia.org/wiki/Bluetooth" target="_blank">Bluetooth</a> del sistema operativo).</p><h3>Implementación.</h3><h4>Instalación de la librería.</h4><ul><li>Descargar WiimoteLib (se utilizó la versión 1.6) desde su <a
href="http://www.codeplex.com/WiimoteLib/Release/ProjectReleases.aspx" target="_blank">repositorio en CodePlex</a>.</li><li>Se debe descomprimir el paquete y ubicar el archivo <span
style="font-family: courier new,courier;">WiimoteLib.dll</span> en un sitio conocido.</li><li>Al proyecto o solución en Visual Studio se le debe agregar la referencia a este archivo.<ul><li>En el explorador de soluciones hacer clic derecho sobre el proyecto.</li><li>Seleccionar la opción <span
style="font-family: courier new,courier;">Agregar referencia &#8230;</span>.</li><li>Seleccionar la etiqueta <span
style="font-family: courier new,courier;">Examinar</span>.</li><li>Buscar el archivo <span
style="font-family: courier new,courier;">Wiimote.dll</span> y presionar el botón <span
style="font-family: courier new,courier;">Aceptar</span>.</li></ul></li></ul><h4>Inclusión del espacio de nombres.</h4><p>Para utilizar cualquiera de las clases de la librería dinámica es necesario incluír en el código fuente al espacio de nombres apropiado.</p><pre class="csharp">using WiimoteLib;</pre><h4>Referencia al Wiimote.</h4><p>El acceso a la información del control se realizará a través de esta referencia, motivo por el cual la utilizo como atributo de la instancia.</p><pre class="C#">private Wiimote wm;</pre><h4>Instanciación de referencia con el Wiimote.</h4><p>Para que la creación de la instancia y posterior conexión sean exitosas es necesario que el control se encuentre ya asociado al equipo a través del emparentamiento Bluetooth.  El procedimiento para realizar esta conexión puede consultarse en <a
href="http://www.ohmybug.com/2008/11/introduccion-a-las-librerias-de-wiimote-para-c-i/" target="_blank">este sitio</a> (<a
href="http://www.youtube.com/watch?v=4_pQSGYzfKU" target="_blank">video</a>) utilizando las herramientas nativas de Windows Vista o en este <a
href="http://www.wiiprojects.org/bluetooth.html" target="_blank">otro sitio</a> utilizando la pila de Bluesoleil.</p><pre class="C#">            try
            {
                wm = new Wiimote();
            }
            catch (System.IO.IOException ioe)
            {
                Console.WriteLine("No es posible ejecutar la aplicación: " + ioe.Message);
            }</pre><h4>Registro de eventos.</h4><p>Se establecen métodos para manejar dos tipos de eventos del control:</p><ul><li>Eventos generados por el control mismo: <span
style="font-family: courier new,courier;">wm_WiimoteChanged</span>.</li><li>Eventos generados por la conexión/desconexión de extensiones: <span
style="font-family: courier new,courier;">wm_WiimoteExtensionChanged</span>.</li></ul><pre class="C#">            wm.WiimoteChanged += wm_WiimoteChanged;
            wm.WiimoteExtensionChanged += wm_WiimoteExtensionChanged;</pre><h4>Establecimiento de la conexión.</h4><pre class="C#">            try
            {
                wm.Connect();
            }
            catch (Exception wnfe)
            {
                Console.WriteLine("No es posible ejecutar la aplicación: " + wnfe.Message);
            }</pre><h4>Establecimiento del nivel de reporte.</h4><p>Determina que tipo de información (informes) estamos interesados en tomar del Wiimote.</p><pre class="C#">            wm.SetReportType(InputReport.IRExtensionAccel, true);</pre><p>Los diferentes tipos de reportes son las siguientes constantes definidas en <span
style="font-family: courier new,courier;">InputReport</span>.</p><ul><li><strong>Status</strong>.  Estado general.</li><li><strong>ReadData.</strong> Datos de la memoria interna.</li><li><strong>Buttons.</strong> Botones pulsados</li><li><strong>ButtonsAccel.</strong> Botones y acelerómetro.</li><li><strong>IRAccel.</strong> Botones, acelerómetro e infrarrojo.</li><li><strong>ButtonsExtension.</strong> Botones y extensiones conectadas (como el Nunchuk, el control convencional, la guitarra, etc.)</li><li><strong>ExtensionAccel.</strong> Botones, acelerómetro y extensiones.</li><li><strong>IRExtensionAccel.</strong> Botones, acelerómetro, infrarrojos y extensiones.</li></ul><h4>Manejo de eventos en conexión de extensiones.</h4><p>El método <span
style="font-family: courier new,courier;">wm_WiimoteExtensionChanged</span> es invocado cuando suceden cambios de conexión entre el Wiimote y sus extensiones.  La verificación de conexión se realiza con la propiedad <span
style="font-family: courier new,courier;">args.Inserted</span>.</p><pre class="C#">        void wm_WiimoteExtensionChanged(object sender, WiimoteExtensionChangedEventArgs args)
        {
            if (args.Inserted)
                wm.SetReportType(InputReport.IRExtensionAccel, true);    // return extension data
            else
                wm.SetReportType(InputReport.IRAccel, true);             // back to original mode
        }</pre><h4>Manejo de eventos ante cambios en el Wiimote.</h4><p>El método <span
style="font-family: courier new,courier;">wm_WiimoteChanged</span> es invocado cuando sucede un cambio en las variables del control (el acelerómetro detectó movimiento, se presionó un botón, etc.).</p><pre class="C#">        void wm_WiimoteChanged(object sender, WiimoteChangedEventArgs args)
        {
              // ...
        }</pre><p>Este es el punto ideal para realizar las consultas actualizadas acerca del estado del control.</p><h4>Consulta del estado del control.</h4><p>La información del estdo del control se almacena entre diferentes propieades del Wiimote.</p><ul><li>Estado general del Wiimote.</li><li>Estado de los botones.</li><li>Estado de los leds.</li><li>Estado del acelerómetro.</li></ul><pre class="C#">WiimoteState ws = args.WiimoteState;
WiimoteLib.ButtonState bs = ws.ButtonState;
LEDState ls = ws.LEDState;
AccelState at = ws.AccelState;</pre><h4>Consulta de la batería.</h4><pre class="C#">int battery = (int) ws.Battery;</pre><h4>Consulta del estado de los botones del Wiimote.</h4><pre class="C#">            bool[] bStatus =
            {
                bs.Up, bs.Down, bs.Left, bs.Right,
                bs.A, bs.B,
                bs.Minus, bs.Home, bs.Plus,
                bs.One, bs.Two
            };</pre><p>Cada una de las constantes corresponde con los botones etiquetados de igual manera en el control:</p><ul><li>Control de dirección: <span
style="font-family: courier new,courier;">Up</span>, <span
style="font-family: courier new,courier;">Down</span>, <span
style="font-family: courier new,courier;">Left</span>, <span
style="font-family: courier new,courier;">Right</span>.</li><li>Botones superiores: <span
style="font-family: courier new,courier;">A</span> y <span
style="font-family: courier new,courier;">B</span>.</li><li>Botones medios: <span
style="font-family: courier new,courier;">Minus</span> (-), <span
style="font-family: courier new,courier;">Home</span> (casita) y <span
style="font-family: courier new,courier;">Plus</span> (+).</li><li>Botones inferiores: <span
style="font-family: courier new,courier;">One</span> (1) y <span
style="font-family: courier new,courier;">Two</span> (2).</li></ul><p>Las propiedades son booleanas y serán <span
style="font-family: courier new,courier;">true</span> si el botón se encuentra presionado, <span
style="font-family: courier new,courier;">false</span> de lo contrario.</p><h4>Manipulación del estado de los leds.</h4><p>Su información se puede acceder de manera similar a lo realizado anteriormente con los botones.</p><pre class="C#">            bLed = new bool[4]
            {
                ls.LED1, ls.LED2, ls.LED3, ls.LED4
            };</pre><p>El dispositivo cuenta con cuatro leds.  Su estado puede modificarse de la siguiente manera.</p><pre class="C#">            wm.SetLEDs(bLed[0], bLed[1], bLed[2], bLed[3]);</pre><p>Donde cada parámetro corresponde a cada uno de los leds y el valor enviado deberá ser <span
style="font-family: courier new,courier;">true</span> para encenderlo o <span
style="font-family: courier new,courier;">false</span> para apagarlo.</p><h4>Información del acelerómetro.</h4><p>Como su nombre lo indica, provee información acerca de la aceleración del movimiento del control en sus tres ejes (consultar gráfica inicial).  Sus valores son enteros y pertenecen al rango entre 0 y 255.</p><pre class="C#">            int rx = (int)at.RawValues.X;
            int ry = (int)at.RawValues.Y;
            int rz = (int)at.RawValues.Z;</pre><h4>Manipulación del vibrador.</h4><p>Con la siguiente instrucción es posible verificar si el dispositivo vibrador del control se encuentra activo o no, retorna <span
style="font-family: courier new,courier;">true</span> o <span
style="font-family: courier new,courier;">false</span> según corresponda.</p><pre class="C#">            wm.WiimoteState.Rumble;</pre><p>De igual manera es posible encender o apagar al dispositivo vibrador según se requiera, esto se realiza de la siguiente manera.</p><pre class="C#">            wm.SetRumble(state);</pre><p>Donde state es <span
style="font-family: courier new,courier;">true</span> o <span
style="font-family: courier new,courier;">false</span> según se desee encender o apagar.</p><h4>Información de las extensiones &#8211; Nunchuk.</h4><p>Verificar si se encuentra o no alguna extensión conectada al Wiimote.</p><pre class="C#">            bool ext = ws.Extension;</pre><p>Verificar si la extensión conectada es el Nunchuk.</p><pre class="C#">            if (ws.ExtensionType.ToString() == "Nunchuk")
            {
                 ...
            }</pre><h4>Estado del joystick del Nunchuk.</h4><pre class="C#">            WiimoteLib.Point joystick = ws.NunchukState.RawJoystick;
            int joyX = joystick.X;
            int joyY = joystick.Y;</pre><h4>Estado de los botones del Nunchuk.</h4><pre class="C#">            bool bCn = ws.NunchukState.C;
            bool bZn = ws.NunchukState.Z;</pre><h4>Información del acelerómetro del Nunchuk.</h4><pre class="C#">            Point3 nAccel = ws.NunchukState.AccelState.RawValues;
            int rnx = nAccel.X;
            int rny = nAccel.Y
            int rnz = nAccel.Z;</pre><p>De manera similar a la información acelerómetro del Wiimote, sus valores van entre 0 y 255.</p><h3>Problemas con el acceso entre hilos de C#.</h3><p>En la implementación de la aplicación de demostración me encontré con un problema del lenguaje C#/.NET.  Al parecer cuando se ejecuta el código de la librería (código nativo me imagino) se ejecuta (por seguridad, me imagino nuevamente) en un hilo diferente, así que cuando intentaba realizar una actualización de la interfaz de usuario a partir de un valor obtenido del Wiimote se lanzaba una excepción.</p><p>Con este problema la siguiente instrucción, que actualiza el valor de un <span
style="font-family: courier new,courier;">Label</span> con la aceleración en X del Nunchuk es problemática.</p><pre class="C#">           this.lnaXValue.Text = ws.NunchukState.AccelState.RawValues.X.ToString();</pre><p>Por suerte encontré en <a
href="http://www.yoda.arachsys.com/csharp/threads/winforms.shtml" target="_blank">Threading in Windows Forms</a> una buena descripción del problema y la estrategia para encontrar una solución, no muy elegante para mi gusto, para solventar el problema por lo menos de manera temporal y continuar con el experimento del Wiimote.</p><p>Para ejecutar la instrucción problemática tuve que implementar un método actualizador de <span
style="font-family: courier new,courier;">Label</span>s y llamarlo a través de un delegado.</p><pre class="C#">        delegate void updateLabelInformationDelegate(Label l, String value);
        public void updateLabelInformation(Label l, String value)
        {
            l.Text = value;
        }</pre><p>La invocación se realiza entonces de la siguiente manera.</p><pre class="C#">        if (InvokeRequired)
        {
             BeginInvoke(new updateLabelInformationDelegate(updateLabelInformation),
                         new object[] {
                                       this.lnaXValue,
                                       ws.NunchukState.AccelState.RawValues.X.ToString()
                         });
        }</pre><h3>Aplicación de demostración.</h3><div
id="attachment_1033" class="wp-caption aligncenter" style="width: 310px"><img
class="size-medium wp-image-1033" title="hellowii-screenshot" src="http://blog.jorgeivanmeza.com/wp-content/uploads/2008/12/hellowii-screenshot-300x188.png" alt="HelloWii 0.1" width="300" height="188" /><p
class="wp-caption-text">HelloWii 0.1</p></div><p>HelloWii 0.1 es la aplicación de prueba que implementé utilizando la librería y operaciones descritas anteriormente.  La funcionalidad de esta aplicación es la siguiente.</p><p>Wiimote.</p><ul><li>Estado del <a
href="http://en.wikipedia.org/wiki/D-pad" target="_blank">d-pad</a>.</li><li>Estado de los botones.</li><li>Estado de los leds.</li><li>Encender/apagar los leds haciendo clic sobre ellos.</li><li>Estado de la batería.</li><li>Número del <a
href="http://en.wikipedia.org/wiki/Human_interface_device" target="_blank">HID</a>.</li><li>Valores de aceleración en sus tres ejes.</li><li>Estado del vibrador.</li><li>Encender/apagar el vibrador seleccionado o removiendo la casilla de verificación.</li><li>Estado de la extensión: presente o ausente.</li></ul><p>Nunchuk (si está presente).</p><ul><li>Dirección del joystick.</li><li>Estado de los botones.</li><li>Valores de aceleración en sus tres ejes.</li></ul><p>Esta aplicación y su código fuente pueden descargarse de manera libre.</p><h3>Conclusiones.</h3><p>La implementación de aplicaciones que interactúan con el Wiimote utilizando C#/WiimoteLib es muy sencillo, obviando el problema de comunicación entre hilos, no se presentó ningún inconveniente.  El API de la librería se encuentra bien documentado en un CHM que viene incluído en su distribución.</p><p>Habiendo probado ya su funcionamiento y documentado su implementación es necesario continuar con algunas pruebas un poco mas elaboradas y estructuras que en lo posible, eviten la necesidad de los delegados y permitan integrar su código con aplicaciones mas complejas y otras librerías de terceros.  También es necesario realizar pruebas con el lector infrarrojo del control y con el parlante, que según creo aún no tiene soporte por esta librería.</p><p>De igual manera planeo realizar pruebas similares utilizando Java.</p><h3>Enlaces.</h3><ul><li><a
href="http://www.wiimotelib.org/" target="_blank">Sitio web de WiimoteLib</a>.</li><li><a
href="http://www.brianpeek.com/" target="_blank">Sitio web de Brian Peek</a>.</li><li><a
href="http://blogs.msdn.com/coding4fun/archive/2007/03/14/1879033.aspx" target="_blank">Artículo de WiimoteLib en Coding4Fun</a>.</li><li><a
href="http://www.brianpeek.com/blog/pages/net-based-wiimote-applications.aspx" target="_blank">Aplicaciones .NET basdas en el Wiimote</a>.</li><li>Introducción a WiimoteLib en OhMyBug! (partes <a
href="http://www.ohmybug.com/2008/11/introduccion-a-las-librerias-de-wiimote-para-c-i/" target="_blank">1</a>, <a
href="http://www.ohmybug.com/2008/11/introduccion-a-las-librerias-de-wiimote-para-c-ii/" target="_blank">2</a> y <a
href="http://www.ohmybug.com/2008/12/introduccion-a-las-librerias-de-wiimote-para-c-iii/" target="_blank">3</a>).</li><li><a
href="http://www.yoda.arachsys.com/csharp/threads/winforms.shtml" target="_blank">Threading in Windows forms</a>.</li></ul><p>Para consultar el código fuente de la aplicación de demostración acceda al enlace de la <a
href="http://blog.jorgeivanmeza.com/2008/12/13/utilizando-el-wiimote-con-c-parte-ii/">segunda parte</a> de este artículo.</p> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>Probando Firebird Embedded con C#</title><link>http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=probando-firebird-embedded-con-c</link> <comments>http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/#comments</comments> <pubDate>Tue, 14 Oct 2008 05:32:26 +0000</pubDate> <dc:creator>jimezam</dc:creator> <category><![CDATA[Bases de datos]]></category> <category><![CDATA[Desarrollo de software]]></category> <category><![CDATA[Windows]]></category> <category><![CDATA[.NET]]></category> <category><![CDATA[C#]]></category> <category><![CDATA[Embedded]]></category> <category><![CDATA[Firebird]]></category> <guid
isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=809</guid> <description><![CDATA[Desde hace mucho tiempo tengo planeado desarrollar una aplicación cuya versión 0.1 desarrollé hace ya varios años en C++ y Fox Toolkit, perdida ya en el museo del olvido. La aplicación es muy sencilla.  Inicialmente son dos módulos pero la &#8230; <a
href="http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/">Continue reading <span
class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>Desde hace mucho tiempo tengo planeado desarrollar una aplicación cuya versión 0.1 desarrollé hace ya varios años en C++ y <a
href="http://www.fox-toolkit.org/" target="_blank">Fox Toolkit</a>, perdida ya en el museo del olvido.</p><p>La aplicación es muy sencilla.  Inicialmente son dos módulos pero la idea es agregarle después algunos otros.  El problema es que cada vez que me siento a pensar en ella termino haciendo un diseño complejo y lleno de cositas que me pondrían a estudiar.  Esto no sería malo sino fuera porque de esta manera se va a terminar cuando el tiempo tienda a infinito.</p><p>Por esto he cambiado mi plan.  Voy a hacer una aplicación pequeña y la voy a ir hacer creciendo, aunque esto signifique que alguna versión deba volverla a hacer desde <em>scratch</em> (cero).</p><p>Con respecto al lenguaje de programación había elegido Java para retomar mi estudio pero en medio de la <em>moda </em>local y temporal de .NET he decidido empezar a implementar en C#.</p><p>El primer reto a resolver es la escogencia de un <em>motor</em> de base de datos ya que la aplicación va a ser pequeña, me interesa que se pueda ejecutar en equipos no necesariamente robustos, no quiero despilfarrar recursos y quiero que la instalación y copia de seguridad sean fáciles: sólo copiar archivos.  Por esto he pensado en utilizar una base de datos basada en archivos o <em>embedded</em>.</p><p>Para Java hay varias de donde escoger, pero para .NET la oferta, al parecer, no es tan amplia.  Encontré <a
href="http://www.sqlite.org/" target="_blank">SQLite</a> (ya lo he utilizado varias veces pero he tenido problemas con bloqueos) <a
href="http://www.vistadb.net/" target="_blank">VistaDB</a> (comercial, no me sirve) y a <a
href="http://www.codeplex.com/sharphsql" target="_blank">SharpHSQL</a> hermanita de <a
href="http://hsqldb.org/" target="_blank">HSQL</a> (Java) para .NET, sin embargo no estoy seguro de cuan activo está ese proyecto.  Las mejores opciones por ahora parecen ser <a
href="http://www.firebirdsql.org/manual/fbmetasecur-embedded.html" target="_blank">FireBird Embedded</a> y <a
href="http://www.microsoft.com/sqlserver/2008/en/us/compact.aspx" target="_blank">SQL Server Compact</a>, ambas prometen muchas cosas, incluyendo un bajo <em>footprint</em> ~ 2MB.</p><p>Para la primera prueba elegí a <a
href="http://firebirdsql.org/" target="_blank">FireBird</a> ya que esa fue la primera base de datos que utilicé en un proyecto después de graduado como ingeniero y me unen a ella emotivos recuerdos <img
src='http://blog.jorgeivanmeza.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p><h3>Instalación.</h3><p>Para desarrollar una aplicación con FireBird inmerso se requieren dos recursos.</p><ul><li>La <a
href="http://firebirdsql.org/index.php?op=files" target="_blank">distribución <em>embed</em></a>.  Para este caso particular estoy utilizando la versión <span
style="font-family: courier new,courier;">2.1.1.17910-0_Win32</span>.</li><li>El <a
href="http://firebirdsql.org/dotnetfirebird/download/index.html" target="_blank">FirebirdClient for .NET</a> que es el <em>Data Provider</em>.  Para esta prueba, la versión <span
style="font-family: courier new,courier;">2.0.1</span>.</li></ul><p>El FirebirdClient se instala como cualquier aplicación Windows sin ninguna opción específica.  Me imagino que habrá que instalarlo también en los clientes cuando se haga el despliegue (por confirmar).</p><p>La distribución se debe descomprimir y mover los siguientes archivo al mismo directorio donde se encontrará el archivo ejecutable de la aplicación: <span
style="font-family: courier new,courier;">&lt;ruta&gt;\bin\Debug</span> (desarrollo) o <span
style="font-family: courier new,courier;">&lt;ruta&gt;\bin\Release</span> (producción).</p><ul><li><span
style="text-decoration: underline;"><strong><span
style="font-family: courier new,courier;">fbembed.dll</span></strong></span></li><li><span
style="text-decoration: underline;"><strong><span
style="font-family: courier new,courier;">icudt30.dll</span></strong></span></li><li><span
style="font-family: courier new,courier;">icuin30.dll</span></li><li><span
style="font-family: courier new,courier;">icuuc30.dll</span></li><li><span
style="font-family: courier new,courier;">firebird.conf</span></li><li><span
style="font-family: courier new,courier;">firebird.msg</span></li></ul><p>Para la implementación del proyecto estoy utilizando Visual C# Express 2008 y en él es necesario incluír la referencia a <span
style="font-family: courier new,courier;">FirebirdSql.Data.FirebirdClient</span> instalada con el <em>Data Provider</em>.</p><h3>Creación de la cadena de conexión.</h3><p>Es fácil construír la <em>ConnectionString</em> con la ayuda del <span
style="font-family: courier new,courier;">FbConnectionStringBuilder</span> de la siguiente manera.</p><pre>            FbConnectionStringBuilder csb = new FbConnectionStringBuilder();
            csb.ServerType = FbServerType.Embedded;
            csb.UserID     = "SYSDBA";
            csb.Password   = "masterkey";
            csb.Dialect    = 3;
            csb.Database   = @"data\database.fdb";
            csb.Charset    = "UTF8";</pre><p>Sólo los parámetros ServerType y Database son obligatorios, los demás son opcionales y puede encontrarse mayor información sobre ellos en <a
href="http://www.firebirdsql.org/dotnetfirebird/connection-string-parameters.html" target="_blank">ConectionStringParameters</a>, también se puede encontrar mayor información acerca de los <span
style="font-family: courier new,courier;">Charset</span> disponibles en <a
href="http://www.destructor.de/firebird/charsets.htm" target="_blank">Firebird Character Sets and Collations</a>.</p><p>La ubicación de la base de datos (parámetro <span
style="font-family: courier new,courier;">Database</span>) es relativo a la ubicación del archivo <span
style="font-family: courier new,courier;">fembed.dll</span>, es decir, al ejecutable de la aplicación.</p><h3>Creación de la base de datos.</h3><p>Desde la misma aplicación es posible crear la base de datos (manera <a
href="http://www.rae2.es/programatica" target="_blank">programática</a>) a la cual hace referencia la cadena de conexión.</p><pre>           FbConnection.CreateDatabase(csb.ToString());</pre><p>Debe tenerse en cuenta que la ruta de directorios bajo la cual se ubicará la base de datos ya debe existir previa la creación del archivo de datos, de lo contrario la creación fallará.</p><h3>Conexión a la base de datos.</h3><pre>          con = new FbConnection(csb.ToString());
          con.Open();</pre><h3>Verificación del estado de la conexión.</h3><pre>            if (con.State == System.Data.ConnectionState.Open)
                Console.WriteLine("Established");
            else
                Console.WriteLine("NOT established");</pre><p>Otros posibles estados definidos por <span
style="font-family: courier new,courier;">ConnectionState </span>son <span
style="font-family: courier new,courier;">Broken</span>, <span
style="font-family: courier new,courier;">Closed</span>, <span
style="font-family: courier new,courier;">Connecting</span>, <span
style="font-family: courier new,courier;">Executing </span>y <span
style="font-family: courier new,courier;">Fetching</span>.</p><h3>Verificación de la existencia de una tabla.</h3><pre>            FbCommand cmd = new FbCommand("SELECT COUNT(RDB$RELATION_NAME)" +
                                          "FROM RDB$RELATIONS WHERE (RDB$RELATION_NAME = 'users')" +
                                          "AND RDB$VIEW_SOURCE IS NULL", con);
            int tableCount = (int)cmd.ExecuteScalar();
            if (tableCount == 0)
                Console.WriteLine("No");
            else
                Console.WriteLine("Yes");</pre><p>Verifica la existencia o no de la tabla <span
style="font-family: courier new,courier;">users</span> en la base de datos conectada.</p><h3>Ejecución de un INSERT.</h3><pre>            String sql = "INSERT INTO \"users\" VALUES ('" + user[0] + "', '" + user[1] + "')";
            cmd = new FbCommand(sql, con);
            cmd.ExecuteNonQuery();</pre><h3>Ejecución de una consulta de datos.</h3><pre>            String select = "SELECT username, name FROM \"users\"";
            cmd = new FbCommand(select, con);
            FbDataReader reader = cmd.ExecuteReader();
            try
            {
                while (reader.Read())
                {
                    String username = reader.GetString(0).Trim();
                    String name = reader.GetString(1).Trim();
                    Console.WriteLine("\t{'" + username + "', '" + name + "'}");
                }
            }
            finally
            {
                reader.Close();
            }</pre><h3>Finalización de la conexión.</h3><pre>            con.Close();</pre><h3>Conclusiones.</h3><p>Esta primera aproximación fue sencilla, práctica y funcional.  Se encuentra buena documentación del motor de base de datos y movimiento en los foros en su respecto.  A pesar de que, al menos por estas latitudes, no es muy utilizada Firebird parece ser que en otras partes si lo es.</p><p>Los archivos requeridos (<em>dlls</em>) ocupan 2.87MB mientras que todos los archivos, incluyendo los opcionales, ocupan 4.94MB.</p><p>Voy a revisar también cuan viable es utilizar el SQL Server Compact, sin embargo en los últimos días que hemos tenido un poco de contacto con SQL Server han aparecido con él algunos detalles desagradables que desde mi punto de vista de conocer poco acerca de este motor, me desaniman de utilizarlo.  Ya veremos.</p><p>Enlace: <a
href="http://demo.jorgeivanmeza.com/NET/FirebirdEmbeddedDemo/0.1/FirebirdEmbeddedDemo1.zip" target="_blank">Aplicación de prueba &#8211; Firebird Embedded Demo 0.1</a>.</p> ]]></content:encoded> <wfw:commentRss>http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> </channel> </rss>
