Si diseñas aplicaciones de escritorio (Windows Forms) con .NET y te limitas a colocar controles sobre los formularios, al final obtendrás ventanas aburridas y con aspecto anticuado, ya que por defecto los estilos visuales de Windows XP no están soportados en éstos.
Desde luego si la aplicación se va a ajecutar en Windows XP es una verdadera pena que no se aproveche de ese aspecto tan potente y actual que le dan los temas y estilos del sistema. Por ejemplo, la figura sigueinte muestra la diferencia abismal que existe entre una misma ventana cuando carece de los los estilos de XP o los está utilizando.
 Pulsa para aumentar
En Visual Studio .NET 2002 era bastante tedioso conseguir esto ya que había que hacer, como con cualquier ejecutable, un archivo manifest que se debía copiar en la misma carpeta que el ejecutable de la aplicación. Sin embargo en Visual Studio .NET 2003 (o sea, en la versión 1.1 de la plataforma) es de lo más sencillo conseguirlo.
Lo único que hay que hacer es poner la propiedad FlatStyle de todos los controles (que dispongan de ella, claro) con el valor 'System'. Luego en la primera línea del método Main() de tu aplicación hay que escribir simplemente:
Application.EnableVisualStyles();
¡Ya está!. A partir de ese instante las aplicaciones sacarán provecho a la estética de windows XP, como en la segunda captura de la figura anterior.
En las tres anteriores entregas de esta serie sobre SOAP con herramientas clásicas hemos visto cómo crear y consumir servicios Web con Visual Basic y código de Script. Consulta el histórico del Blog para leer estos artículos.
Los componentes que hemos creado y consumido hasta ahora eran objetos sin estado. Esto es, si disponemos de una DLL escrita en VB que contiene una clase que debe mantener información entre llamadas no funcionará correctamente ya que cada llamada realziada a través de SOAP es independiente de las demás y se realiza sobre un objeto diferente en el servidor.
Por ejemplo, consideremos la siguiente clase 'PruebaSOAP2.Persona' que dispone de dos métodos: uno para anotar e nombre de una persona y el otro para saludarla:
Private mNombre As String Public Sub AnotaNombre(sNombre As String) mNombre = sNombre End Sub Public Function DimeNombre() As String DimeNombre = mNombre End Function
El método 'AnotaNombre' de esta clase almacena la cadena que se le pase como parámetro en una variable privada de la clase. el método 'DimeNombre', port el contrario, la recupera. Es obvio que para que esta clase funcione como es debido se debe poder realziar llamadas sucesivas sobre una misma instancia de ésta o el estado interno de la variable 'mNombre' se perdería.
Vamos a probar a consumirla mediante SOAP directamente. Compile la clase y expógala como unobjeto SOAP tal y como hemos aprendido. Ahora intente ejecutar este código:
Dim o Set o = GetObject("soap:wsdl=http://dilbert/personaws/PruebaSOAP2.Persona.soap?WSDL") o.AnotaNombre "Jose" MsgBox o.DimeNombre
En el mensaje final debería aparecer la palabra "Jose". Sin embargo vemos que en realidad se muestra en blanco. Ello se debe a lo que comentaba antes: cada llamada al servicio Web es atendida por un objeto diferente y nuevo en el servidor. Está claro que esto limita bastante la capacidad de reutilizar como servicios Web algunos componentes con estado heredados.
Por suerte, como casi todo, esto también tiene solución. Y para colmo es casi igual de fácil que todo lo visto hasta ahora. Lo primero que debemos hacer es exportar nuestra aplicación COM+ desde la consola de administración de servicios de componentes. en el diálogo que aparece seleccione la opción 'Proxy de aplicación' y escoja una ruta en la que crear un paquete de instalación MSI.
Pulse para aumentar
Ahora dispone de un paquete de instalación que podrá instalar en cualquier equipo con Windows XP o Windows 2003 Server. Hágalo. Tenga en cuenta que para poder probarlo deberá instalar el proxy en otro equipo diferente al que contiene el servicio Web. Una vez instalado en otro equipo podrá comenzar a utilizar el objeto con el siguiente código:
Dim o Set o = WScript.CreateObject("PruebaSOAP2.Persona") o.AnotaNombre "Jose" MsgBox o.DimeNombre
Este código funcionará ahora perfectamente, devolviendo en el cuadro de diálogo el valor del nombre fijado en la llamada anterior, es decir, manteniendo el estado entre llamados.
"¡Eh!, ¡un momento!, pero ¿qué es esto?. ¡No estoy utilizando SOAP!". Tranquilo, todo tiene una explicación. En realidad sí está utilizando SOAP y las llamadas se están realizando a través de HTTP al servidor en el que está instalando el componente original. La diferencia respecto a lo que hemos visto hasta ahora es que estamos utilizando un Proxy .NET Remoting generado de forma automática por COM+ durante la exportación y expuesto como un objeto COM regular durante la importación. Es éste el que nos aisla de las complejidades de SOAP y nos permite utilizar el servicio Web remoto como si fuese un componente local. Como ya me he acostumbrado a decir durante toda esta serie de artículos: ¡impresionante!.
En la carpeta 'C:\WINDOWS\system32\Com\SOAPAssembly' del sistema cliente podemos encontrar el archivo '.config' que controla el funcionamiento del proxy. Podemos modificarlo o añadirle nuevos nodos sin problema para modificar el comportamiento del Proxy.
Con este artículo termino la serie comenzada hace unos días sobre servicios Web con herramientas tradicionales que creo que le resultará interesante a todo el mundo. Lo cierto es que apenas hay información disponible sobre estos temas y creo que ha resultado intersante mostrar aquí los resultados de mis investigaciones al respecto. las posibilidades de estas técnicas son casi ilimitadas para muchos escenarios de soporte e integración de código heredado, accesibilidad de componentes a través de redes de comunicaciones sin preocuparnos de cortafuegos, etc, etc..
¡Qué lo disfrutes!
En las entregas anteriores de esta mini-serie vimos cómo crear un servicio Web con Visual Basic 6 sin necesidad de hacer nada especial, sólo crear una DLL normal y corriente.
Una vez suplida esta necesidad todavía nos queda otra: poder consumir servicios Web en Windows sin necesidad de programar en .NET.
Sorprendentemente se trata de un tarea muy sencilla, si bien tiene sus limitaciones al intentar usarlo con servicios Web complejos que constan de varios componentes o espacios de nombres.
La técnica consiste en el uso de la conocida función GetObject, si bien usando una sintaxis algo especial. Este función está disponible en Visual Basic, VBScript, Windows Scripting Host, etc… por lo que podemos hacer uso de ella universalmente.
Por ejemplo, el siguiente código de WSH (guárdalo con cualquier nombre y extensión ‘.vbs’ o incluso úsalo desde una página HTML), utiliza el servicio Web de información horaria que creamos en la anterior entrega para devolver la hora en el servidor:
Dim oHora set oHora = GetObject("soap:wsdl=http://localhost/horaws/PruebaSOAP.Hora.soap?WSDL") msgbox oHora.HoraLocal
¡Facilísimo!. Lo único que hay que hacer es colocar la URL del descriptor del servicio Web (archivo WSDL) como parámetro de GetObject, precediéndolo con la expresión 'soap:wsdl'. Se creará automáticamente un objeto COM con los métodos expuestos por el servicio Web que podremos usar como si fuera local. ¡Impresionante!.
Al igual que antes, lo que ocurre por detrás es que se genera automáticamente código .NET Remoting que se compila en una DLL .NET que es la que hace el trabajo por detrás para comunicarse con el servicio Web. La primera vez que se hace una llamada al servicio Web ésta tarda un par de segundos mientras se compila el componente, pero todas las sucesivas llamadas, al existir ya el Proxy, se realizan a toda velocidad, por lo que sólo dependeremos de la velocidad de nuestra conexión.
La DLL generada (y el archivo de código fuente a partir del cual se generó) la podemos encontrar en la carpeta 'C:\WINDOWS\system32\Com\SOAPAssembly', por lo que incluso la podremos utilizar tal cual o recompilarla en nuestros desarrollos .NET también.
Pero todavía falta lo mejor: esta técnica funciona para cualquier servicio Web, no sólo para los generados con el sistema que hemos aprendido. Si disponemos de un servicio Web creado con .NET, Java, Gluecode o cualquier otro sistema compatible con SOAP, podemos consumirlo a través de GetObject. Esto es así en la mayor parte de las ocasiones, ya que existen ciertas limitaciones si el servicio expuesto es muy complejo.
Por ejemplo, si copias el siguiente código a un archivo ‘.vbs’ dispondrás de un programa que te permite verificar la disponibilidad de un dominio ‘.com’, ‘.org’ o ‘.net’ utilizando el servicio Web gratuito que tiene para esta tarea XMethods:
Dim sDominio sDominio = InputBox("Dominio a verificar (sin 'wwww')", "Verificador de dominios") If sDominio <> "" Then Dim oDC set oDC = GetObject("soap:wsdl=http://services.xmethods.net/soap/urn:xmethods-DomainChecker.wsdl") MsgBox oDC.checkDomain(sDominio) End If
Este código te pregunta un nombre de dominio (por ejemplo, JASoft.org) y devuelve la cadena "Available" o "Unavailable" en función de su disponibilidad. Más sencillo imposible.
Sigue sintonizado a esta miniserie. Todavía me quedan unas cuantas cosas por explicar al respecto. Por ejemplo, ¿cómo podemos hacer que los objetos COM que exponemos mediante SOAP se comporten como objetos sin estado o con estado para conservar la conexión con los clientes?
Ayer, con Visual Basic 6, construimos una clase muy sencilla con un método que se encargaba de devolver la hora del servidor. Nuestra intención es convertirla en un servicio Web para que pueda servir la hora a cualquier cliente SOAP. Y todo ello sin programar nada especial para conseguirlo.
Ahora es en donde entra en juego la magia de COM+ y de .NET Remoting. Recuerda que debes tener instalado IIS sobre Windows XP o Windows 2003 Server.
En las herramientas administrativas ejecuta la consola de administración de Servicios de componentes (o sea, COM+). Crea una nueva aplicación COM+ y agrégale la DLL que acabas de compilar. En las propiedades de la aplicación COM+ vete a la pestaña Activación y marca la opción Usa SOAP. En el campo de texto inferior escribe el nombre que quieras darle al directorio de IIS en el que se publicará tu servicio Web, por ejemplo, HoraWS, como en la figura.
 Pulsa para ampliar
Ya está. A partir de ahora tienes disponible un servicio Web en ese directorio virtual de tu servidor y todo ello sin escribir una sola línea de código.
¿No me crees? Pruébalo. Escribe en tu navegador lo siguiente:
http://localhost/HoraWS/
Aparecerá una página que contiene un enlace al WSDL del servicio Web, es decir, a la definición de éste para que los clientes SOAP puedan utilizarlo sin problemas. Si pulsas este enlace verás el XML que forma parte de dicha descripción.
Lo que ha ocurrido es que, de forma automática, COM+ ha generado una DLL .NET que encapsula toda la funcionalidad de nuestro servidor COM y la expone a través de .NET Remoting encauzado a través de HTTP y SOAP, o sea: un servicio Web.
La página que acabas de consultar y la correspondiente DLL que he mencionado las puedes encontrar en “C:\WINDOWS\system32\Com\SOAPVRoots\HoraWS”. Por supuesto puedes tocar el archivo web.config para modificar el comportamiento del componente y adecuarlo a tus necesidades, o directamente llevártelo todo y reutilizarlo en otro lugar junto con la DLL ActiveX (si bien para esto es mejor utilizar la capacidad de exportación/importación de COM+).
Impresionante ¿verdad?
De todos modos no desconectes todavía de este hilo porque, en breve publicaré más cosas interesantes sobre este asunto.
Por ejemplo, ¿Quieres saber cómo utilizar nuestro flamante servicio Web (y cualquier otro) con sólo una línea de código y desde VBScript?
Pues sigue atento y pronto lo sabrás.
Parece que hoy en día no hay nada que esté más de moda que los servicios Web ¿verdad?
Crear un servicio Web con la plataforma .NET es algo sencillo si no nos metemos en profundidades. Puedes leer al respecto una introducción a los servicios Web y un ejemplo de cómo crearlos en Visual Studio en mis artículos de los números 185 (¿Qué son los servicios Web?) y 186 (Implementación sencilla de servicios Web con Visual Studio .NET) de PC World (por desgracia no tengo enlaces a los que se pueda acceder gratuitamente).
Los programadores de otros lenguajes más antiguos, como por ejemplo Visual Basic 6, parece que están fuera de onda automáticamente. En realidad se pueden crear servicios Web con Visual Basic 6 y otros lenguajes antiguos de Microsoft (hasta directamente en ASP, nosotros en Krasis lo hemos hecho) gracias al SOAP Toolkit 3.0 de Microsoft. De todos modos hay que programar bastante y, antes de nada, hay que leer bien y aprenderse la documentación que trae el Toolkit.
¿Qué te parece si te cuento que puedes crear y consumir servicios Web con Visual Basic 6 sin necesidad de aprender nada nuevo ni apenas tocar tus aplicaciones? Lo único que necesitarás es Visual Basic 6, Windows XP o Windows 2003 Server y la plataforma .NET instalada (OJO, no Visual Studio .NET, sólo la plataforma).
Sigue leyendo…
Vamos a crear un servicio Web que devolverá una cadena con la hora en el servidor. Una cosa muy sencilla pero suficiente para ilustrar la técnica.
Ejecuta Visual Basic 6 y crea un nuevo proyecto de tipo DLL ActiveX. En las propiedades del proyecto otórgale el nombre PruebaSOAP y marca las opciones 'ejecución desatendida' y 'Conservado en memoria'.
A la clase que se crea por defecto cámbiale el nombre y llámale 'Hora.cls'. Crea un nuevo método de la clase con el código siguiente:
Public Function HoraLocal() As String HoraLocal = Format(Time, "h:m:s") End Function
Compila la DLL. El entorno de VB6 ya se encarga de registrarla automáticamente en el sistema.
Te lo creas o no ya casi hemos terminado.
Mañana publicaré cómo convertiremos en medio minuto esta flamante DLL en un servicio Web de alta disponibilidad y con todas las de la ley. ¡Permanece atento a este canal! ;-)
Cuando en un formulario Web tenemos un campo de texto (INPUT, type=text), que se utiliza para que los usuarios introduzcan números (por ejemplo su edad, un número de factura...) lo habitual es verificar su contenido con la función parseInt de JavaScript.
Imaginemos por ejemplo que hay que verificar que un campo de este tipo no sobre pase un determinado valor. Normalmente escribiríamos una condición similar a esta:
if ( parseInt(micampo.value) > valorMax ) alert("Se ha sobrepasado el máximo");
Un código sencillo, directo y, en apariencia, sin problemas. Pero, ¿qué pasaría si por ejemplo el usuario introduce el número '034', es decir, incluye el dígito cero precediendo al número?.
Respuesta: que parseInt en lugar de devolver el número 34 que es sin duda el que esperábamos devolverá un 28.
El motivo es que la función parseInt interpreta los textos que comienzan con un cero como números en base octal y no decimal, por lo que 034 se interpreta como el número 28 en base octal. Por lo tanto la comparación hecha en el condicional puede fallar.
SOLUCIÓN: mi consejo es que siempre se explicite la base con la que deseamos trabajar cuando usemos la función parseInt (y similares) en JavaScript. En el caso más habitual la base numérica con la que trabajamos es la decimal, por lo que al indicarla la expresión condicional anterior quedaría como sigue:
if ( parseInt(micampo.value, 10) > valorMax ) alert("Se ha sobrepasado el máximo");
Así evitaremos problemas.
Cuña publicitaria ;-)
¿Estás interesado en JavaScript?. Pues échale un vistazo a mi libro sobre el tema pulsando aquí. Este libro ha sido uno de los veinte más vendidos del mundo sobre JavaScript en Amazon.com (en todos los idiomas), ha tenido una edición especial para EE.UU. y es libro recomendado en la bibliografía de multitud de universidades y centros de estudios. Si te interesa aprender JavaScript ¡cómpratelo!. :-)
Me ha llamado mucho la atención esta utilísima herramienta basada enWeb que ha escrito Francesco Balena.
Se trata de un visor de ensamblados .NET basado en Web, accesible públicamente y que trabaja con .NET 2.0. Te permite navegar por cualquier ensamblado y, utilizando reflexión, visualizar sus clases, miembros, interfaces, etc... pudiendo ahondar en ellos. Marca las novedades y diferencias entre .NET 2.0 y versiones anteriores.
Una de las cosas que más interesantes me han parecido es que en cualquier miembro puedes averiguar qué tipos derivan de él, qué miembros devuelven el tipo seleccionado y cuáles lo usan bien como parámetro o como valor de retorno.
Se pueden utilizar URLs directas para llegar a determinados tipos, lo cual es muy útil para referenciarlos en textos o mensajes a foros, por ejemplo.
¿Qué es la subclasificación?
El sistema operativo Windows efectúa la comunicación entre los diversos objetos de la interfaz de usuario utilizando mensajes. Todo lo que ocurre en la interfaz requiere mensajes para ocurrir. Por ejemplo, cuando pulsas con el ratón sobre una ventana se envía un mensaje para indicar en dónde has pulsado y cómo. Si haces clic en el aspa de cerrar una ventana Windows envía un mensaje a ésta para que se cierre. Etc, etc...
Otra cuestión a tener en cuenta en este contexto es que, en contra de lo que pueda parecer, muchos objetos aparte de las propias ventanas son también ventanas. Por ejemplo, un cuadro de texto, un botón o una rejilla son ventanas (sólo que de otros tipos) y por consiguiente reciben mensajes del sistema operativo para indicarles cómo deben comportarse.
Cuando un proceso intercepta y (opcionalmente) modifica los mensajes que se envían a una ventana se dice que la ventana ha sido subclasificada.
Pero, ¿para qué puede nos puede valer esto?. En realidad para multitud de cosas.
Lo más obvio es poder engañar a un control o ventana para que se comporte como nosotros queremos en lugar de cómo le dicen que debe hacerlo. Por ejemplo podemos capturar el mensaje que le indica a una ventana que se debe maximizar, modificarlo y así impedir que lo haga. De acuerdo, hay formas más fáciles de hacer esto, pero nos da una idea ¿verdad?. Luego veremos un caso más útil.
Otra utilidad es la que nos permite responder a acciones que normalmente no podríamos detectar porque no se exponen mediante evento alguno en nuestro lenguaje de programación favorito. Por ejemplo, cuando se introduce un CD en la unidad lectora de nuestro ordenador se notifica a las ventanas con un mensaje que podemos capturar. Esta es la única forma que tendremos de hacerlo.
¿Cómo se lleva a cabo la subclasificasificación en .NET y Windows Forms?
Antes de .NET la subclasificación era bastanbte tediosa de implementar, sobre todo si en lugar de C/C++ usábamos Visual Basic. Por fortuna en .NET es un proceso muy fácil de realizar. Todos los controles de Windows Forms que derivan de la clase base Control (incluyendo el objeto Form que representa a las ventanas de una aplicación) poseen un método llamado WndProc que es el que se encarga de gestionar los mensajes que recibe el control (o, dicho con más propiedad, la ventana). Para interceptar estos mensajes sólo tenemos que sobreescribir esta función por una propia que la sustituya. En ésta podremos obtener toda la inforamción sobre cada mensaje a través del parámetro del tipo System.Windows.Forms.Message que se le pasa automáticamente como argumento. Con esta información y sabiendo qué mensajes podemos interceptar así como su significado es muy fácil conseguir infinidad de efectos.
Por ejemplo, en el archivo que puedes descargar desde aquí (23 KB), he escrito un sencillo ejemplo que efectúa dos tareas subclasificando una ventana. Primeramente engaña a la ventana para que cuando se pulse sobre su área cliente (sobre cualquier sitio en el que no haya un control colocado), ésta piense que se ha pulsando en realidad sobre la barra de títulos. Con esto lo que conseguimos es que la ventana se mueva arrastrándola por su área cliente. Por otra parte, como ejemplo adicional, he dejado la propiedad FormBorderStyle con el valor Sizable, es decir, que se puede cambiar su tamaño arrastrando los bordes. Sin embargo he capturado el correspondiente mensaje para impedir que se pueda modificar las dimensiones de la ventana.
Todo el código necesario para conseguirlo es el siguiente:
private const int WM_NCHITTEST = 0x84; private const int HTCAPTION = 2; private const int HTCLIENT = 1; private const int WM_SYSCOMMAND = 0x112; private const int SC_SIZE = 0xF000;
protected override void WndProc(ref System.Windows.Forms.Message m) {
if (m.Msg == WM_SYSCOMMAND && (((int) m.WParam) & 0xFFF0) == SC_SIZE)
{
m.Result = new System.IntPtr(0); return;
}
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST && m.Result.ToInt32() == HTCLIENT)
{
m.Result = new IntPtr(HTCAPTION);
}
}
No lo explico con detalle. Te dejo como ejercicio interpretarlo ;-). En el ZIP adjunto encontrarás algunas explicaciones como comentarios al código.
Te recomiendo que leas el artículo de MSDN "Windows procedures" para aprender sobre la gestión de mensajes en ventanas. En MSDN encontrarás también información sobre todos los mensajes de Windows, su significado y cómo se gestionan. Busca las constantes del código anterior para comprenderlo bien.
A partir del 1 de Octubre de 2004, entra en vigor el nuevo Código Penal con el que se puede incurrir en penas de cárcel simplemente por descargar música en Internet.
La nueva ley orgánica 15/2003, con la que se reforma de manera extensa el vigente Código Penal, incorpora una serie de medidas que deben hacer temblar a cualquier internauta habituado a los "usos" típicos de Internet hoy en día. Asimismo deben temblar aquellos padres que tienen a sus hijos navegando tranquilamente en la habitación, pues sin hacer nada "malo" podrían acabar llevándoles a la cárcel o al pago de una multa bastante cuantiosa.
Desde el próximo 1 de Octubre de 2004, en España será delito penado con seis meses a dos años de cárcel y multa de 12 a 24 meses, bajarse una canción de Internet sin permisos del propietario de los derechos de autor (Art. 270, ap. 2).
De igual modo se penaliza al que fabrique distribuya o simplemente tenga en su ordenador software capaz de suprimir o neutralizar herramientas de protección de información de autor, como por ejemplo los archiconocidos "cracks", "key generators" o software de generación de claves de registro de software, programas para duplicar CD’s de música protegidos, etc…
Por otra parte cualquier actividad ya sea informar, vender equipos o proporcionar servicios relacionados con desbloquear un móvil, saltarse una contraseña de acceso a un servicio de pago o compartir el propio acceso a Internet vía WiFi estarán penadas con seis meses a dos años y multa de seis a 24 meses (Artículo 286).
A la primera de cambio puedes ir 6 meses a la carcel... Puede que la cosa no sea para tanto si lees las referencias que vienen en el artículo original del boletín de Krasis sobre el sector TIC, BECK, que es de donde se ha sacado esta noticia.

Hace unos meses me encontré con este interesante servicio y hoy, por cuestiones que no vienen al caso, me he acordado de él. Se trata de, Mailinator.net, un servicio de correo electrónico temporal y anónimo. ¿Qué quiere decir esto?. Lo mejor es que lo explique con un ejemplo...
Imagínate el típico portal de Internet que tiene uno o dos archivos interesantes que te interesa bajarte pero que, para ello, debes registrarte antes en la página. Además sabes que a la hora de registrarte deberás proporcionar una dirección de correo válida puesto que te enviarán a ella una clave de acceso. El problema es que si realmente proporcionas una dirección tuya en el futuro te van a machacar con correo electrónico y no está el horno para bollos ¿verdad?. ¿No sería estupendo disponer de una cuenta que funcionase lo justo para que te escriban a ella y luego que te pudieras desentender de la misma?
Pues esto precisamente es lo que hace Mailinator. Tú invéntate una cuenta cualquiera dentro del dominio mailinator.com, por ejemplo, pepe_lopez@mailinator.com. Ahora puedes dar esa cuenta a quien quieras ya que mailinator recibirá en ella lo que le manden. No es necesario darla de alta en ningún sitio no hacer nada, sólo inventártela y dársela a alguien... Ahora basta con pasarte por www.mailinator.net y en su página principal meter la cuenta inventada para verificar su contenido. Si hay correo te lo aguantarán en esa cuenta durante unas horas, lo suficiente para consultarlo.
¿No es interesante? Sin registros, sin datos, sin rastro. Espero que lo disfrutes :-)
Cuando colocamos un objeto de conexión a un origen de datos sobre un formulario Windows Forms de Visual Studio .NET, éste aparece en la parte inferior del diseñador correspondiente y podemos editar sus propiedades desde la ventana de propiedades del entorno.
La propiedad más importante de este objeto es, sin duda, ConnectionString. Normalmente la ajustamos desde la propia ventana de propiedades, y mucha gente la deja simplemente ahí, sin añadir forma alguna de modificarla de forma externa a la aplicación. Esto tiene varios problemas, pero los principales son:
· Si queremos actualizar la cadena deberemos cambiar la propiedad desde el diseñador y recompilar la aplicación · Si alguien rastrea o descompila el código puede leer en claro la cadena (con contraseñas de acceso y otra información confidencial).
Para evitar el primero de estos problemas es obvio que lo más sencillo es llevar esta cadena de conexion (entera o por partes) a algún archivo externo de configuración que leeremos desde nuestro código para ajustar la cadena en tiempo de ejecución.
Un truco interesante para obtener esta característica sin esfuerzo es el siguiente.
En la ventana de propiedades del objeto Connection, aparte de la propiedad ConnectionString clásica, existe una propiedad dinámica con el mismo nombre (dentro de la sección DynamicProperties). Si editamos su valor aparece un diálogo que nos pregunta si queremos obtener la cadena de ocnexión desde un archivo externo. Si marcamos esa opción el componente genera automáticamente el codigo necesario en nuestro formulario para que en tiempo de ejecución ese valor se obtenga desde un archivo de configuración externo.

El código automático se incluye dentro del método InitializeComponent del formulario, y tiene el siguiente aspecto (he incluido sólo el que se refiere a esta característica):
System.Configuration.AppSettingsReader configurationAppSettings = new System.Configuration.AppSettingsReader(); this.sqlConnection1 = new System.Data.SqlClient.SqlConnection(); this.label1 = new System.Windows.Forms.Label(); this.sqlConnection1.ConnectionString = ((string)(configurationAppSettings.GetValue("sqlConnection1.ConnectionString", typeof(string))));
Como vemos se utiliza la clase AppSettingsReader, obteniéndose los datos de la conexión desde el archivo .config de la aplicación. Este archivo XML se generará de manera automática al compilar el programa e incluirá un nodo con el nombre especificado (en el ejemplo, sqlConnection1.ConnectionString) que podemos modificar para cambiar la cadena de conexión sin tener que recompilar. Como se puede comprobar es algo muy cómodo.
Ahora el problema que tenemos es cómo proteger el contenido de esa cadena de conexión, por defecto guardada en claro, para que no la pueda leer cualquiera que simplemente abra el archivo .config. Esto, sin embargo es un tema peliagudo que dejaré para una próxima ocasión.
Se ha anunciado una vulnerabilidad en Mozilla y Firefox que permitiría a sitios web maliciosos falsificar el interfaz de usuario, lo que puede inducir al usuario a creer que se encuentra en un sitio diferente y ser empleado para realizar ataques de phishing (robo de información bancaria, cuentas de acceso, etc).
El problema, que parece ser el mismo que el identificado como 244965 en Mozilla, reside en que estos productos no restringen a los sitios web la inclusión de archivos XUL remotos (XML User Interface Language) de tal manera que se puede "secuestrar" la mayor parte del interfaz, incluyendo la barra de herramientas, los diálogos de certificados SSL, barra de direcciones, etc. Esto es importante debido a que el interfaz de Mozilla está construida a base de archivos XUL.
Hay que señalar que no se trata de un problema nuevo, ya que el mencionado bug fue mencionado por primera vez en 1999, pero fue marcado como confidencial durante 5 años, hasta que el pasado día 21 un desarrollador independiente publicó el aviso.
Se tiene constancia de la existencia de código de prueba de concepto que hace creer al usuario que se está utilizando un certificado válido de PayPal.
Este problema ha sido confirmado en Mozilla 1.7 para Linux y 1.7.1 para Windows, Firefox 0.9.1 para Linux y 0.9.2 para Windows. Aunque teniendo en cuenta la fecha del aviso original, en versiones anteriores también se encuentra presente.
A la espera de una actualización que corrija este problema, se recomienda como de costumbre no seguir enlaces de lugares que no sean de confianza.
Más información:
Firefox spoof demostration http://www.nd.edu/~jsmith30/xul/test/spoof.html
Noticia obtenida de: http://www.hispasec.com/unaaldia/2107/
Como es bien sabido la clase DataSet de .NET (dentro del espacio de nombres System.Data), permite utilizar de manera sencilla y potente un pequeño gestor de datos en memoria, sin necesidad de haber obtenido por fuerza los datos a partir de un gestor de datos convencional. El objeto DataSet puede haber sido creado dinámicamente por nosotros o se puede haber generado para trabajar en memoria con tablas y relaciones obtenidos de una fuente de datos relacional, por ejemplo.
Un DataSet contiene, entre otras cosas, una colección de objetos DataTable que, como puede imaginar, son equivalentes conceptualmente a las tablas o relaciones en una base de datos relacional. No voy a entrar aquí a explicar todas las características de este tipo de objetos, pero sí me gustaría recordar que generan dos eventos con el fin de notificar de los cambios que sufren. Estos eventos son RowChanged y RowDeleted, y se lanzan cuando se cambia algún valor o cuando se elimina una fila de la tabla respectivamente.
Aprovechando esta coyuntura es bastante fácil construir una clase que se ocupe de registrar automáticamente todos los cambios que se realicen sobre una tabla en memoria (DataTable). Basta con almacenarlos en una pila y mediante un método 'Undo' o similar ir deshaciéndolos uno a uno hasta dejarla como estaba en el momento en que nuestra clase comenzó a controlar sus cambios. Esto contrasta por ejemplo con el uso del método RejectChanges del DataTable, que deshace todos los cambios sufridos por la tabla, pero no permite dejarla en un punto intermedio.
En este enlace he dejado un archivo (10 KB) con el código fuente completo en C# y la DLL ya compilada de una clase llamada DataTableLogger que consigue precisamente esto que he descrito: controla de forma automática todos los cambios que sufre un DataTable que se le pase en su constructor, permitiendo posteriormente ir deshaciéndolos desde el final a través de un método Undo.
Así, para comenzar a controlar los cambios sufridos por una tabla sólo habría que escribir:
DataTableLogger DLogger = new DataTableLogger(DataTableAControlar);
Si luego quisiésemos deshacer el último cambio sufrido sólo habría que escribir:
DLogger.Undo();
que además devuelve el número de cambios que quedan por deshacer. Existe también una propiedad llamada ChangesCount que indica este mismo valor pero sin necesidad de llamar a Undo. Con este valor (obtenido mediante cualquiera de las dos formas) se puede escribir fácilmente un bucle que deshaga todos los cambios, uno a uno.
La clase se puede heredar para aprovechar su funcionalidad en otras clases más potentes que permitan controlar, por ejemplo, un DataSet completo, guardando los cambios de todas las tablas que éste contenga, aunque esto se deja como ejercicio para el lector ;-)
OJO: hay una pequeña pega con esta clase. Si una determinada fila sufre dos cambios diferentes, cuando se llame al método Undo para restablecer el último, en realidad como podrás comprobar en el código, se estarán restableciendo todos a la vez (el segundo y el primero). Eso es porque se usa el método RejectChanges de la fila que la restablece a su valor original cuando se llama. Es relativamente sencillo (aunque tedioso) ampliar el código de la clase para que tenga en cuenta esta eventualidad. Bastaría con interceptar el evento ColumChanged de la tabla y almacenar el valor orginal del campo que se cambia junto con la referencia a la fila dentro de la pila de deshacer de la clase. Si alguien lo implementa por su cuenta o incluso alguien crea una clase similar para controlar un DataSet completo le agradeceré que me haga llegar el código ampliado.
|
|
Copyright © 2010 José Manuel Alarcón Aguín. All rights reserved.
|
|