Entrevista a Jim Gray Entrevista a Jim Gray

Transcripción

Entrevista a Jim Gray Entrevista a Jim Gray
nº12 febrero 2005 • 6,00 € (España)
Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET Framework • Windows Server System
dotNetManía
www.dotnetmania.com
Dedicada a los profesionales de la plataforma .NET
Entrevista a Jim Gray
Investigador de Microsoft Research y premio A.M. Turing
Subclasificación de ventanas
Ampliando la capacidad de los controles y ventanas mediante técnicas de subclasificación
Creación y utilización de servicios Web
desde ASP.NET • Redes de mensajería y .NET
(y II) • Sistemas distribuidos en .NET con
Remoting (I) • SQL Server Analysis Services.
¡Hola cubo! (III) • Interoperabilidad
no administrada y migración
(I) • Acceso a datos en
Delphi 2005
ToDotNet Q&A
¿Está seguro con ASP.NET?
Laboratorio
Raptier, rápido por naturaleza
opinión
Cine y desarrollo de software
dnm.editorial
dotNetManía
Dedicada a los profesionales de la plataforma .NET
Vol. II •Número 12 • Febrero 2005
Precio: 6€ (España)
dotNetManía CD Vol. 1
Editor
Paco Marín
([email protected])
Asesor Técnico/Coordinación
Marino Posadas
([email protected])
Redactores
Antonio Quirós, Dino Esposito, Guillermo
'guille' Som, Jorge Serrano, José Manuel
Alarcón, Luis Miguel Blanco, Manuel Imaz y
Pedro Pozo.
Colaboradores habituales
Ángel Esteban, Braulio Díez, Eladio Rincón,
Erich Bühler, Fernando Nogueras, Jorge
Crespo Cano, José Miguel Torres, Miguel
Egea, Miguel Katrib Mora (Grupo Weboo),
Octavio Hernández, Pablo Abbate, Pepe
Hevia y Salvador Ramos.
Además colabora en este número
Rodrigo Corral
Edición y Suscripciones
.netalia
c/ Robledal, 135
28529 Rivas-Vaciamadrid (Madrid)
Tf. (34) 91 666 74 77
Fax (34) 91 499 13 64
Publicidad
Mediadev
Sophie Mancini ([email protected])
Tf. 93 426 22 57 - 670 99 74 64
Fax. 93 423 11 40
Imprime
Gráficas Vallehermoso
www.graficasvallehermoso.com
ISSN
1698-5451
Depósito Legal
M-3.075-2004
<<
dotNetManía ha cumplido un año, un
difícil año en el que hemos apostado por contenidos técnicos enfocados claramente a los
profesionales o a los estudiosos de la plataforma .NET. Es momento de agradecimientos:
a vosotros, los lectores, por estar ahí (fueron
muchos los que dijeron que no estaríais); a las
personas de Microsoft por facilitarnos continuamente la labor, dejándonos trabajar con
independencia en una muestra de respeto a
vosotros, los lectores; a los autores, por su
impagable esfuerzo y por las muchas horas
dedicadas para elaborar contenidos que estuviesen a la altura de nuestros lectores y por
dejar que fuésemos nosotros quienes los trasmitiésemos; y por último, a los patrocinadores, pocos pero fieles, quienes han apostado
especialmente por vosotros.
Todo este esfuerzo se recopila en el primer dotNetManía CD Volumen 1, un CD
con los primeros 11 números en formato PDF
de alta calidad, organizado por documentos
con las revistas completas y también separados por artículos para una mejor localización
de la información. Todos los suscriptores tendrán la posibilidad de llevárselo gratuitamente al renovar su suscripción.
En cuanto a las noticias de este mes, si hay
una que realmente atañe directamente a los
desarrolladores de .NET, ésa es el lanzamiento de la campaña de formación y certificación
de MCAD de Microsoft, por la cual regalarán
una XBox más 2 juegos y una suscripción a
dotNetManía por 3 números (si ya está sus-
crito, su suscripción se incrementará en 3
números) a todos los que se certifiquen como
MCAD entre el 15 de enero y el 30 de abril.
Si estaba pensando en certificarse, éste puede
ser el momento idóneo.
Y en cuanto al contenido de este mes, tenemos una estupenda entrevista con Jim Gray,
investigador de Microsoft Research y nada
menos que premio A.M. Turing (algo así como
el Nobel de Informática). Todo un ilustre que
nos recibió con la sencillez propia de los más
grandes. En nuestro nombre y en el de nuestros lectores, muchas gracias señor Gray.
Y estrenamos una nueva columna,
ToDotNet Q&A, que escribirá nada más y
nada menos que el gran Dino Esposito, quien
recibirá y contestará vuestras dudas sobre la
plataforma .NET. Dino es de esas personas
que explica de forma sencilla los temas más
difíciles, que sabe dar con los problemas clave y con las soluciones más elegantes. Es para
nosotros todo un lujo contar con él, por lo que
quiero mostrar mi público agradecimiento a
Dino por colaborar con nosotros.
Quisiera, por último, dar la bienvenida a
Rodrigo Corral como colaborador de
dotNetManía. Comienza con una serie de 3
artículos bien fundamentados sobre aplicaciones distribuidas con .NET Remoting.
Después de esto, lo demás parece poca
cosa (no todos los días se entrevista a todo un
Premio Turing o se inaugura una columna que
dirijirá uno de los mejores comunicadores del
mundo), pero hay más, mucho más...
<<dotNetManía
Administración
Pilar Pérez
([email protected])
3
12
dnm.sumario
Cine y desarrollo de software
8-9
Eran los turbios años de la mafia en América. La familia Corleone copaba una buena
parte del control sobre determinados negocios. Alguien ofrece a Don Vito Corleone entrar
en el mundo de la droga. Pero es un caballero de la mafia, un idealista que aún no quiere
bajar a pozos tan profundos. Se niega… y ahí se desencadena la historia.
Entrevista a Jim Gray
10-12
Entrevista con Jim Gray, premio A.M. Turing por sus trabajos sobre sistemas de
almacenamiento de información. Como suele suceder con los auténticamente grandes,
Jim Gray nos recibió de forma sencilla en el pasado Tech-Ed de Ámsterdam.
Creación y utilización de servicios Web desde ASP.NET
13-16
En este artículo lo que se pretende es mostrar paso a paso, y de forma práctica, el
proceso de creación y utilización de un servicio Web desde una aplicación Web de ASP
.NET utilizando para ello el lenguaje Visual Basic .NET y la herramienta de
desarrollo Visual Studio .NET.
Redes de mensajería y .NET (y II)
18-22
En la primera parte de esta serie, vimos cómo iniciar una sesión con Messenger
(autentificándonos con éxito) y chequear nuestra lista de contactos. En esta segunda parte
vamos a ver como “chatear” con ellos.
dnm.sumario
Ampliando la capacidad de los controles y ventanas mediante
técnicas de subclasificación
23-28
La subclasificación de ventanas es una técnica específica de la plataforma Windows
que permite ampliar las capacidades de la mayoría de los controles y formularios de
Windows Forms. Con su uso se consiguen características poco frecuentes pero muy
útiles. Veremos en este artículo cómo sacarle partido.
Sistemas distribuidos en .NET con Remoting (I)
29-35
En esta serie de tres artículos veremos como .NET Remoting permite desarrollar, desplegar
y configurar con facilidad aplicaciones distribuidas sin los quebraderos de cabeza y las
limitaciones que presentaban anteriores soluciones.
SQL Server Analysis Services. ¡Hola Cubo! (III)
36-39
Con este artículo concluiremos la creación de nuestra primera base de datos multidimensional,
en la que tendremos un cubo compuesto por dos medidas y cinco dimensiones, que ya
quedará listo para su explotación con las herramientas cliente.
Interoperabilidad no administrada y migración (I)
40-45
Esta serie de tres artículos nos ayudará a conocer las ventajas y posibilidades tanto de COM
Interop como de la interoperabilidad con código no adminsitrado en general, lo que nos
permitirá no sólo extender el alcance de nuestras apliciones sino replantearnos los escenarios
de migración.
Acceso a datos en Delphi 2005
46-50
Delphi 2005 ofrece la posibilidad de desarrollar para la plataforma .NET utilizando dos
vías diferentes para el acceso a datos: a través de los recursos que ofrece la VCL.NET, una
librería de compatibilidad desarrollada por Borland; o a través de ADO.NET, la tecnología
de acceso a datos “nativa” de la plataforma .NET.
dnm.todotnet.qa
52-53
¿Está seguro con ASP.NET?
dnm.laboratorio
54-55
Raptier, rápido por naturaleza
dnm.biblioteca.net
57
OOP: Building Reusable Components with Microsoft® Visual Basic® .NET (Ken
Spencer, Tom Eberhard, y John Alexander).
C# for Java Developers (Allen Jones y Adam Freeman).
dnm.desvan
58
dnm.noticias
6
noticias.noticias.noticias.noticias.noticias.noticias
<< dotNetManía
<<
dnm.noticias
Campaña de formación y certificación de MCAD
sobre Visual Studio .NET
Microsoft Ibérica,conjuntamente con los CPLS (Certified Partner for Learning
solutions),lanza esta campaña con el objetivo de animar a los desarrolladores
MCAD (Microsoft Certified Application
Developer) es la certificación para avalar los conocimientos de los desarrolladores de aplicaciones Windows y
aplicaciones Web y servicios de Web en
la plataforma .NET. Es también el primer
paso para conseguir la certificación MCSD
(Microsoft Certified Solution Developer) que
es la certificación que además avala sus
habilidades como diseñador de software.
Todas aquellas personas que consigan la certificación MCAD entre el 15 de enero y el 30 de abril, aparte de poseer una de las certificaciones en desarrollo de
aplicaciones más demandadas del mercado, recibirán
completamente gratis:
• Consola Xbox + 2 juegos1
• Suscripción gratuita por 3 meses a a dotNetManía2
Tan solo existen 3 condiciones para poder beneficiarse de todos estos regalos:
IV Jornadas del Programador
Madrid, 7, 8 y 9 de febrero
Enfocadas a Visual Studio 2005 y
SQL Server 2005.
Recomendaciones para la
escritura de código seguro
Implementación de seguridad en las
aplicaciones con Microsoft .NET
Framework
Madrid y Barcelona, 15 de febrero
Recomendaciones de seguridad para
todas las etapas del desarrollo.
MSDN Talleres:WSE 2.0
Madrid, 18 de febrero
Introducción a las nuevas especificaciones estándares WS-* recogidas en Microsoft WSE 2.0.
ASP.NET 2.0 Tour
Madrid, 21 de febrero
Para los desarrolladores profesionales de ASP.NET. Este even-
• Obtener la certificación MCAD
completa antes del 30 de abril de
2005, es decir, tener superados los
3 exámenes de certificación
requeridos (70-305, 70-306 y
70-310).
• Asistir al menos a 1 curso presencial
MOC en cualquiera de los centros que
están adheridos a la campaña.
• Registrarse en la página web que se indica
para poder hacer el envío de los regalos.
Para más información: www.microsoft.com/spain/
formacion/oferta/formacion.mspx o en www.alhambraeidos.com ([email protected])
Además, las 15 primeras personas que se certifiquen, recibirán
la Xbox junto con 2 meses gratis de conexión a Xbox live
2
Si ya es suscriptor a esta revista,su suscripción se incrementará
en 3 ejemplares más.
1
to es parte de un tour europeo
de Microsoft que contará con
ponentes de primer nivel.
Puede ver más información en
http://www.microsoft.com/emea/ms
dn/aspontour para el tour europeo o en http://www.microsoft.com
/spanish/msdn/Spain/eventos/talleres/asptour_2005.asp para el
evento español.
¡Recomendable!
TechNet Security Day
Cómo tener más segura la información de sus servidores
Barcelona, 17 de febrero
Madrid, 21 de febrero
Se tratarán los temas más pedidos por los usuarios: Fortificación
de servidores, gestion de políticas
de seguridad y seguridad wireless.
Una pena que en Madrid coincida con el ASP.NET 2.0 Tour.
Más información en www.microsoft.com/spain/tec hnet/SecurityDay.
Gira TechNet de Seguridad
Protección contra Hackers.
Seguridad en VPNs.
Gira por once ciudades españolas
que comienza el 25 de enero. Más
información en http://www.microsoft.com/spain/technet/jornadas/gira.
SQL Server Reporting
Services
Madrid, 1 de febrero
Barcelona, 3 de febrero
Webcast, 16 de febrero
Parte de una serie de jornadas tecnológícas genéricamente llamadas
“Potencia tu SQL”, en la que se
están estudiando diferentes escenarios técnicos de uso de SQL
Server 2000 y algunas de las nuevas características de SQL Server
2005. Más información en:
http://www.microsoft.com/spain/technet/potenciatusql/sql_200502.mspx.
eventos.microsoft
www.microsoft.com/spain/eventos
<< dnm.noticias
Compuware lanza nuevos productos
DevPartner
Noticias breves
DevPartner Fault Simulator y DevPartner SecurityChecker
analizan y asesoran en las emergentes áreas de la
calidad del software
Altova DiffDog™ 2005 es una herramienta de
sincronización que facilita la comparación y fusión
de ficheros, carpetas y directorios para desarrolladores de aplicaciones y usuarios avanzados.
DiffDog™ 2005 simplifica los procesos de reconcilicación a través de su sencillo entorno visual,
de modo que incrementa la productividad y maximiza los resultados. Permite a los usuarios comparar rápidamente ficheros de código fuente,
ficheros HTM L y es capaz de fusionar los cambios de cualquier fichero de texto con un solo clic.
Más información en: www.altova.com.
Compuware DevPartner Fault Simulator 1.0
DevPartner Fault Simulator chequea y
depura el código de gestión de errores en
código administrado .NET y en código
nativo, sin desestabilizar el entorno de operación o depuración de la aplicación, a través de la inyección segura de fallos simulados dentro del código de la aplicación.
El simulador “engaña” a la aplicación destinataria en la creencia de que un fallo ha
ocurrido de modo que la reacción puede
ser monitorizada sin afectar a otras aplicaciones que se estén ejecutando o a un
proceso del sistema operativo.
Compuware DevPartner SecurityChecker 1.0
DevPartner SecurityChecker es una
potente herramienta de análisis que permite a los desarrolladores localizar y reparar rápidamente vulnerabilidades de seguridad en aplicaciones ASP.NET.
DevPartner SecurityChecker usa tres modelos distintos para proveer al desarrollador
con un análisis profundo sin par en la
industria actualmente:
• Análisis en tiempo de compilación.
DevPartner SecurityChecker inspecciona los ensamblados de .NET y determina si existen asuntos de seguridad a
través del examen de los metadatos,
código IL, archivos ASPX y el
WEB.CONFIG. Ejemplos de vulnerabilidades detectables a través del análisis en tiempo de compilación incluyen amenazas heredadas, depuración
activada, seguridad débil en las passwords y constructores estáticos desprotegidos.
• Análisis en tiempo de ejecución.
Gracias a la capacidad para mirar dentro de la aplicación mientra se ejecuta, DevPartner SecurityChecker puede
detectar errores de seguridad tal como
ocurren. Ejemplos de vulnerabilidades
detectables a través del análisis en
tiempo de ejecución incluyen el uso
del API con privilegios, uso de cuentas con privilegios, excesivos accesos a
ficheros y al registro, excepciones no
manejadas y fallos de suplantación.
• Análisis de integridad. DevPartner
SecurityChecker puede simular un ataque externo a través de la ejecución de
una sesión basada en HTTP y modificar algunas de las entradas para chequear vulnerabilidades. Los análisis
de integridad chequean vulnerabilidades a ataques de scripting, ataques de
injección de código SQL, buffer overflows, inyección de comandos y falsificación de parámetros.
DevPartner SecurityChecker es el único producto del mercado que llama a
cada uno de estos tipos de análisis para
encontrar vulnerabilidades de seguridad,
dando como resultado aplicaciones más
seguras que pueden ser creadas a través
de la integridad de análisis aislados.
Puede encontrar más información
sobre seguridad en ASP.NET en la sección ToDotNet Q&A de este mes.
Más información sobre estos productos en: www.compuware.com/products/devpartner/default.htm
ComponentOne® lanza Studio
EnterpriseTM 2005 v1
ComponentOne, uno de los más importantes fabricantes de herramientas de terceros, ha
anunciado Studio Enterprise 2005 v1. La nueva
versión añade alrededor de 45 actualizaciones de
las herramientas de .NET y ASP.NET. Si es usted
suscriptor a las actualizaciones de Studio
Enterprise con esta entrega obtendrá ya acceso a
componentes para las versiones Alpha y Beta de
Visual Studio 2005.
Más información en: www.componentone.com.
Nuevas versiones CTP de
Visual Studio 2005 e Indigo
para febrero
Según Ford McKinstry (Indigo Program
Manager), Microsoft lanzará una versión CTP de
Indigo después del VSLive de San Francisco, no
en el 8 de febrero, en el Indigo Day como se preveía. Igualmente en febrero se presentará la última versión CTP de Visual Studio 2005, según él
mismo comentaba (microsoft.public.windows.developer.winfx.indigo) antes de la aparición de la Beta
2, que según indicaba Somasegar, vicepresidente
de Microsoft Corp. de Developer Division en su weblog
estará a finales del primer cuarto de este año
(weblogs.asp.net/somasegar/archive/2004/12/22/
329673.aspx#343547).
MVP Global Summit
El evento anual más importante para
MVPs ya tiene fecha. Tendrá lugar entre el
28 de septiembre y el 1 de octubre en
Redmond. Contará con ponentes de la talla
de Steve Ballmer, Jim Allchin y Kevin
Johnson.
dnm.noticias
<< dotNetManía
Compuware ha anunciado –antes de
o esperado– la disponibilidad de dos nuevos productos DevPartner: Compuware
Fault Simulator y Compuware DePartner
SecurityChecker.
Compuware comunicó en noviembre
del año pasado su estrategia para el entorno de desarrollo de Microsoft (ver número 9). Dentro de dicha estrategia estaba la
aparición de estos dos productos, si bien
las informaciones eran que aparecerían
inmediatamente después de que Visual
Studio 2005 estuviese disponible.
Estos nuevos productos extienden significativamente la capacidad de asesorameinto de los productos de DevPartner,
para dar una amplia y profunda visión en
materia de calidad de las aplicaciones, permitiendo a los equipos de proyectos establecer las mejores prácticas para construir
software de calidad a lo largo de todo el
ciclo de vida del desarrollo de aplicaciones.
Nuevo Altova DiffDog 2005
7
dnm.opinion
Antonio Quirós
Cine y desarrollo de software
Eran los turbios años de la mafia en América. La familia Corleone copaba una buena
parte del control sobre determinados negocios.Alguien ofrece a Don Vito Corleone
entrar en el mundo de la droga. Pero es un caballero de la mafia, un idealista que aún
no quiere bajar a pozos tan profundos. Se niega… y ahí se desencadena la historia.
<< Entonces el Don sufre un atentado que casi le hace per-
<<dotNetManía
Antonio Quirós
es redactor de dotNetManía.
Co-fundador de las revistas
clippeRManía, FOXManía y
Algoritmo.Actualmente es
General Area Manager en
Alhambra-Eidos
8
der la vida. Su hijo mayor, Santino Corleone, deseaba derramar un mar de sangre con las familias enemigas que habían intentado matar a su padre. Sin
embargo, es Michele, el hijo pequeño, mucho más
frío y, en principio, menos aficionado a las cosas de
la mafia, quien termina vengando el intento de matar
a su padre. Para ocultarse y evitar la vendetta opuesta marcha a la vieja, soleada y romántica Sicilia. Es
entonces cuando la mano maestra de Ford Coppola
comienza a mostrarnos las bucólicas escenas del
campo siciliano mientras la magistral música de
Nino Rotta pone en nuestros oídos esa fantástica
melodía que todos conocemos. Michele se enamora de la joven Appolonia que muere en un nuevo
atentado y marca ya el futuro del gángster, que pasa
de ser el joven vástago, alejado del asunto mafioso,
a convertirse en el frío criminal que conducirá a la
familia Corleone tras la muerte del viejo Vito. La
suerte está echada y la tragedia va labrando el destino de sus personajes.
Es el cine, el fantástico cine, que es capaz de presentarnos la épica de algo tan deleznable como la
mafia; que saca poesía hasta de lo más turbiamente
humano.
Pero ¿y qué hay de los desarrolladores de software? Hay que tener en cuenta que, en nuestro mundo,
el cine contribuye de un modo insólito a fijar la imagen que la sociedad tiene de los distintos colectivos
que la componen. Tenemos excelentes películas sobre
médicos, policías, mafiosos, soldados, políticos, revolucionarios, etc. Pero ¿qué tenemos sobre desarrolladores de software? El resumen no es demasiado bueno y, por tanto, la imagen que la sociedad tiene de los
desarrolladores tampoco lo es. Veamos algunos ejemplos. ¿Quién no recuerda, por ejemplo, al gordinflón
desarrollador del sistema informático que controlaba
el parque en “Parque Jurásico” de Steven Spielberg?.
El típico zampabollos aprovechado y sin escrúpulos
que no dudaba en cargarse todo el sistema con tal de
ganar unos cuantos duros. Qué decir de la alucinada
Angela Bennet - Sandra Bullock en “La Red” de Irwin
Winkler, sin amigos, sólo relacionándose a través de
Internet y con habilidades supremas a la hora de descerrajar sistemas informáticos. La perspectiva de negocio podemos obtenerla, por ejemplo, en “Acoso” de
Barry Levinson, donde una ejecutiva come hombres
(Demi Moore) le siega la hierba bajo los pies a un
Michael Douglas, experto en software, pero que no
transmite más que la típica imagen del triunfador americano medio que se sobrepone a la adversidad y triunfa en ese mundo idílico donde los buenos (rubios, coloradotes y sanos) siempre vencen a los malos (morenos, pálidos y delgaduchos).
Y vayamos a lo hispano. No quiero ya recordar
cuando en “Laberinto de Pasiones” de Almodóvar,
una de las protagonistas le dice a su novio Usebio
(Eusebio pronunciado a la manchega) que lo que tiene que hacer es dejar la música para estudiar informática que es lo que tiene futuro realmente. Esto, por
supuesto, salvando las distancias de nuestro estupendo Almodóvar con los directores mencionados en el
párrafo que no sirven ni para atarle los zapatos a nuestro manchego universal.
Mención aparte merece la trilogía “Matrix” de los
hermanos Wachowski que, aunque no tienen desarrolladores de software en su entramado narrativo, nos presenta un mundo creado y mantenido por un sistema de
software y por un gran arquitecto que no deja de representar al dios-creador-desarrollador del mundo. Al fin y al
cabo ¿quién es dios sino el desarrollador que liberó la
versión del mundo que hoy conocemos?. Por cierto que
este dios es casi tan malo como la mayoría de nosotros,
ya que dejó un sistema lleno de agujeros de seguridad
<< dnm.opinion
que la toque otra vez, sino que revise el
programa de seguridad de la puerta que
la ha dejado pasar?
Tenemos excelentes películas sobre médicos, policías,
mafiosos, soldados, políticos, revolucionarios, etc. Pero
¿qué tenemos sobre desarrolladores de software?
Marginados sociales con carencias
hasta en el don de la palabra, piratas,
ejecutivos arribistas, etc. Estos son los
caracteres principales que el cine ha tratado hasta ahora de los desarrolladores
de software y, sin embargo, no somos
así. Entre nosotros hay grandezas y
miserias al igual que entre cualquier otra
profesión las hay. Habrá que esperar esa
novela, esa genial obra cinematográfica
que eleve al rango del arte la figura de
algún protagonista, de profesión desarrollador, que sin acartonamientos ni
falsos clichés busque la identificación
del lector o del espectador. Cuando eso
suceda, nuestra autoimagen y aquella
que los demás tienen de nosotros habrá
Nuestra imagen sólo ha sido tratada en el cine actual a
la moda americana, carente de poesía, de compromiso
que no busca identificarse con el espectador sino alienarlo un poco más de lo que ya está.
de lo que ya está. La diferencia entre “El
padrino” y “La red”, por ejemplo, es
obvia. ¿Busca el Padrino fijar roles sociales que puedan ser seguidos por la juventud? ¡No, claro que no! ¡Quien va a querer ser como Michele Corleone, frío asesino inmisericorde! No, claro que no, el
buen cine busca el arte, la transmisión de
sensaciones y sentimientos. En “La red”,
como prototipo de película donde aparecen desarrolladores de software, como
mucho hay adocenamiento intelectual.
Todo el arte de dicha película se centra
en la belleza y simpatía de Sandra Bullock
que esa sí que no es de menospreciar ni
mucho menos
Esperaremos, pues, esperanzados.
Esperaremos a nuestro Scorsese, a nuestro Coppola, a nuestro Amenábar para
que vengan a sacarnos del fango en que
nos hallamos, para que escriban y/o dirijan esa obra magistral que nos muestre
tal como somos; con eso será suficiente para que podamos ingresar en el universo del cine que hasta ahora sólo nos
ha maltratado. Michele Corleone y
Yehuda Ben Hur nos esperan en su universo intemporal y proteico, no debemos tardar en llegar a la cita.
<<dotNetManía
por los que se cuelan tsunamis, guerras,
odio, destrucción y una buena colección
de bugs adicionales. Que me perdonen los
creyentes, no tengo ni la más mínima animadversión hacia ellos, pero hay que reconocer que a dios le falló el control de calidad en la versión del universo donde nos
ha tocado movernos. Quizá en otras
dimensiones, en otras eras, con otro despliegue diferente de nuestros sistemas, la
cosa esté yendo un poco mejor.
En fin, fantasías aparte, lo que podemos concluir es que apenas si hay ni épica ni lírica alrededor de nuestra profesión. Esto hace que al mundo en general le caiga mejor que nosotros un taxista, el dependiente de un Seven Eleven o
un sexador de pollos. Falta la obra que
enfatice las virtudes del creador de sistemas informáticos, que escarbe en la
poesía de las noches sin sueño buscando la solución a una rutina inacabada,
que muestre el placer de sentirse autor
de complicadas soluciones que facilitan
la vida a millones de ciudadanos en
nuestro sofisticado mundo actual.
¿Dónde está nuestro Michele Corleone?
¿Vivirá ya en la cabeza de algún guionista ese Rick, sorprendido por la visita de Ingrid Bergman en su café del norte de África, mientras le dice a Sam, no
cambiado notoriamente y ello contribuirá a mejorar tanto nuestra autosatisfacción, como la consideración social
que sobre nosotros tenga la media de
los mortales. En definitiva, nosotros nos
sentiremos mejor, trabajaremos más
cómodos y, por tanto, nuestros sistemas
serán mucho más eficaces.
Y es que quizá aún no se ha realizado esa obra genial que tiene entre sus
protagonistas a un desarrollador de software. Casi todas las mencionadas son
mediocres, vulgares. Nuestra imagen sólo
ha sido tratada en el cine actual a la moda
americana, carente de poesía, de compromiso, que no busca identificarse con
el espectador sino alienarlo un poco más
9
dnm.directo.entrevistas
Marino Posadas
Entrevista a Jim Gray
Como suele suceder con los auténticamente grandes, Jim Gray nos recibió
de forma sencilla en el pasado Tech-Ed 2004 en Ámsterdam, en esta entrevista que contó también con la presencia de Iván González, de la Universidade
de A Coruña.
<< La Informática es,
<<dotNetManía
Marino Posadas es
asesor técnico y
redactor de
dotNetManía, MVP de
C# y formador de
Alhambra-Eidos
10
junto a las Matemáticas, una de las disciplinas científicas en las que los méritos de sus
practicantes nunca podrán recompensarse con un
Premio Nobel. Afortunadamente, y para paliar esta
situación, algunas instituciones crearon sus equivalentes, tanto en lo económico como en lo prestigioso. En el primer caso, la Medalla Fields, establecida por John Charles Fields en 1932 (curiosamente, para matemáticos menores de 40 años) y
de la que han sido receptores hombres de la talla
de René Thom, Michael Francis Atiyah, o
Edward Witten. En el segundo, el Premio A.M.
Turing, en honor a al padre de la informática, Alan
Mathison Turing, de la que han sido perceptores
figuras de la talla de Marvin Minsky (el padre de
la Robótica actual) Herbert Simon (también Premio
Nobel de Economía), Ken Thompson y Dennis M.
Ritchie (creadores del S.O. Unix), y nuestro entrevistado de hoy, James Gray, por sus trabajos sobre
sistemas de almacenamiento de información. En la
actualidad trabaja sobre grandes sistemas de almacenamiento y transferencia de información en
Microsoft Research.
Gracias por recibirnos, ante todo. A lo largo
de este año Microsoft ha estado implicado en una
serie de actividades de divulgación académica por
todas las universidades españolas. ¿Crees que es
una de las mejores formas de popularizar lo que
se hace en los distintos departamentos de investigación en Microsoft?
Sí. Nosotros normalmente presentamos los resultados de nuestras investigaciones en conferencias internacionales. Y en realidad, no sólo nosotros sino otras
compañías como Oracle o IBM hacen lo mismo. Hay
otra forma de divulgación, por ejemplo, yendo a
España dentro del entorno de las grandes corporaciones a participar en eventos como el que hace dos
años tuvo lugar en Barcelona.
Precisamente en el ambiente universitario, a
priori hostil a Microsoft, he podido comprobar
que –una vez que se conoce la tecnología y sus
valores– lo de menos es su procedencia. ¿Tienes
tú la misma sensación?
Absolutamente. Eso sucede también en EE.UU, tanto en las grandes corporaciones como en las universidades. Pero la tecnología triunfa finalmente, a pesar de
todo. Y cuando nos conocen, esa hostilidad se convierte en interés por lo que estás presentando.
Tú perteneces al Scaleable Servers Research
Group. ¿Puedes explicarnos algo más acerca de tu
<< dnm.directo.entrevistas
mente almacenamos tantas cosas que
no recordamos siquiera que están en
nuestro equipo.
Así que –en este sentido– esas innovaciones son beneficiosas para todo el
mundo. Tenemos, sin embargo otras
líneas de trabajo que van más encaminadas a lo que genéricamente llamamos
“Sociedad Digital”. Aquí la labor de los
servicios Web será más y más crítica,
permitiendo producir y compartir información con los demás.
Hasta ahora transferimos sin mucho conocimiento
previo, ni seguridad de la información. Pero, en el futuro,
la gente va a querer que el almacenamiento y la
transferencia de información conlleven un significado
asociado con ellos, unos metadatos, en suma
¿Y qué sucede con la transferencia misma de la información y su
recuperación, en términos de rendimiento? ¿Piensas que el futuro será
algo similar a Internet-2?
No creo que el futuro se quede
–sólo– en la mejora de la velocidad.
Hasta ahora transferimos sin mucho
conocimiento previo, ni seguridad de
la información. Pero, en el futuro, la
gente va a querer que el almacenamiento y la transferencia de información conlleven un significado asociado con ellos, unos metadatos, en suma.
Metadatos que incluirán firmas digitales que garanticen la identidad, y
cosas más básicas, en realidad, las que
buscamos para ese estándar: por ejemplo, cada mensaje debería contener una
cabecera y un cuerpo.
Y una vez que esto se establezca o incluso hasta que eso ocurra,
¿cuál es el principal problema de
esta arquitectura: almacenamiento, transmisión o acceso a la información?
Acceso a la información. Porque
el acceso es el beneficio que obtenemos de la información almacenada. La
transmisión no es un problema en
absoluto, la tecnología está ya ahí. Y
el almacenamiento, no es un proble-
<<dotNetManía
trabajo y líneas de investigación
actual que estás siguiendo?
Nuestro interés principal son las
aplicaciones a gran escala. Aplicaciones
como TerraServer o SkyServer. Los
proyectos han seguido evolucionando
de formas a veces inesperadas. Por
ejemplo, TerraServer ha reducido su
tamaño a unos pocos Terabytes (sic),
gracias a los adelantos en sistemas de
almacenamiento. En el otro grupo, en
el que trabajo en la actualidad, el Media
Presence Group, intentamos facilitar el
almacenaje y la operatividad con la
cada vez mayor cantidad de información que almacenamos en nuestros
ordenadores personales, para que pueda ser organizada de forma que sea
fácil su acceso y su búsqueda, aportando la mayor utilidad posible a la
propia información. De tal forma que
el software hace el seguimiento de las
llamadas que has realizado o recibido,
de tus correos, de las películas que has
visto, de los documentos que has leído, de modo que, la próxima vez que
quieras buscar algo, la aplicación –de
forma preactiva– pueda ser capaz de
anticiparse de alguna forma a tus deseos minimizando las necesidades de
búsqueda, por ejemplo.
¿Piensas, por tanto, que esa labor
de investigación que realizáis tiene
consecuencias inmediatas para el
común de los usuarios?
Por supuesto, especialmente, el
proyecto llamado MyLifeBits (ver
www.research.microsoft.com/barc/Media
Presence/MyLifeBits.aspx) , que he
comentado anteriormente. Todo el
mundo se beneficia de estas innovaciones, en especial las personas con
problemas de memoria o que simple-
estoy hablando de la vida cotidiana,
desde una comunicación de un padre
al profesor de su hijo, hasta una transferencia bancaria.
Eso significa que das una gran
importancia a los estándares, y en
especial a los estándares desarrollados en torno a los servicios
Web…
Por supuesto, a todos ellos. En la
actualidad estamos también trabajando en lo que sería una definición
estándar de lo que un documento
debería de contener. Es sorprendente que, a pesar de todos los documentos que circulan y se manejan digitalmente, los intentos de estandarizar,
como PDF, RTF y otros no han conseguido aún el consenso universal que
buscamos.
Lo mismo sucede con las otras gramáticas universalmente aceptadas en el
mundo de los servicios Web, que siguen
evolucionando en busca de la especificación final (nunca definitiva, pero sí
aceptada por la inmensa mayoría). Son
11
<< dnm.directo.entrevistas
ma en términos de bytes, pero si pensamos en términos de organización de
la información, de la comprensión de
lo que la información es (desde el punto de vista de sus esquemas) entonces
es un gran problema. Al objeto de
suministrar un buen acceso, tienes que
haber organizado previamente la
información.
En el futuro la mayor parte de la
información no será vista por seres
humanos, sino por ordenadores. Eso
sucede ya en muchos ámbitos. La gente sólo quiere la información que le
interesa, y no toda. El reto, en el futuro, es la capacidad de resumir la información mostrando sólo la que es interesante, y en el nivel de detalle que se
necesite. Lo que probablemente necesitará el usuario es poder preguntar
cosas inteligentes, y obtener respuestas
inteligentes. Eso no sucede en la actualidad con lenguajes como SQL. No hay
resumen, no hay más que lo que se le
pide exactamente.
ve el papel. Siempre obtienen la información de Internet, porque la obtienen
antes y les permite comunicarse. Por
supuesto en el caso de las tesis, hace falta ese trozo de papel, para firmarlo, y
pasarlo al tribunal, pero probablemente, ese tribunal ya ha leído la tesis en formato digital. Lo único que resulta crítico, es la calidad de la fuente de información.
Y esto nos lleva de nuevo al tema
del almacenamiento a gran escala.
Hace 3 años leí unos trabajos de
Bruster Khale, un informático millonario (creador de Alexa) que está
haciendo literalmente copias de
seguridad de Internet. ¿Es ése el nuevo almacén de la historia? ¿Podemos
considerar esas copias como improntas de cómo era la humanidad en un
instante dado?
Conozco su trabajo. En la actualidad, está llevando copias de Internet
a muy distintos países (acaba de depositar copias en Egipto y aquí en Áms-
<<dotNetManía
En esencia, se pretende incluir inteligencia en cualquier
dispositivo, desde los teclados o los ratones hasta las
pantallas, o los dispositivos de red
12
¿Eso quiere decir que la red va
a albergar más y más información
y de mayor calidad cada vez, y que
por lo tanto, sería de esperar que,
utilizando los filtros adecuados, por poner un ejemplo- una universidad pudiese aceptar una tesis doctoral cuya única fuente de información fuese la red?
Veamos. Pensemos en la investigación en el campo de la Astronomía. Los
astrónomos obtienen toda la información de Internet. Muchos de los que
están haciendo investigaciones, jamás
ven el telescopio. Su entrada de datos
es Internet. Mucha de la información
que manejan viene de astro-ph que es un
sitio Web. Nadie va ya a las librerías, ni
terdam). Porque la historia y las librerías pueden ser destruidas por los
gobiernos. De esa forma garantiza que
existan copias en países con sistemas
políticos totalmente distintos, y siempre podamos estar seguros de que hay
copias sin manipular.
De forma que el nuevo paradigma pasa por la información selectiva
y la manera que podemos acceder y
filtrar esa información…
Hasta tal punto que, por ejemplo,
en EE.UU. tenemos un sistema llamado TiVo , que consiste en un montón de ordenadores que se dedican a
ver televisión. El servicio permite que
los usuarios seleccionen previamente
o a posteriori cualquier cosa que se
haya emitido en las últimas 3 semanas
o vaya a emitirse, y solicite su grabación para una visión posterior, pudiendo almacenarlo en disco o DVD directamente.
Estamos ante una avalancha de
información, y necesitamos algo que
filtre y condense esa información, y la
presente a nuestra conveniencia.
¿Tiene esto que ver con algo
que he leído acerca de los dispositivos inteligentes de almacenamiento? ¿Cómo serían esos dispositivos?
Si te fijas en el interior de uno de
los discos duros actuales, verás que
disponen de circuitos integrados y
puertos de comunicación. Y llevan un
procesador y su propia memoria y una
interfaz con el exterior. Pero algún día,
ese procesador será un superordenador. De hecho, ahora mismo tienen
más potencia que los “mainframes” de
1960. Y en unos pocos años, tendrá
más potencia que la máquina más
potente que podemos tener hoy. Los
modelos de hoy ya disponen de 8/16
Mb de memoria y procesadores de
100/200 Mhz. Esas características
superan con creces lo que teníamos
hace 10 años, y son parte de un simple disco duro. En 10 años serán capaces que ejecutar lo que un ordenador
actual: una base de datos o un servidor Web. Y el propio disco tendrá una
imponente capacidad de almacenamiento, probablemente, entre 2 y 10
Terabytes. Por tanto, optimización de
acceso e inclusión de inteligencia en
el dispositivo, serán dos factores clave para suministrar esto que estamos
hablando: acceso inteligente a la información, y capacidad de síntesis de esa
información.
En esencia, se pretende incluir
inteligencia en cualquier dispositivo,
desde los teclados o los ratones hasta
las pantallas, o los dispositivos de red.
Eso minimizará los problemas de instalación gracias a la propia comunicación entre dispositivos.
Pues esto es todo lo que nos
deja el tiempo disponible. Muchas
gracias por tus comentarios.
Gracias a vosotros y espero un
ejemplar de la revista en cuanto esté
publicada.
dnm.asp.net
Ángel Esteban
Creación y utilización de servicios
Web desde ASP.NET
En este artículo lo que se pretende es mostrar paso a paso, y de forma práctica, el proceso de creación y utilización de un servicio Web desde una aplicación
Web de ASP .NET utilizando para ello el lenguaje Visual Basic .NET y la herramienta de desarrollo Visual Studio .NET.
Ángel Esteban
Colaboradora habitualmente con
dotNetManía. Ingeniero Técnico
Informácito, MCSD, MCAD y
MCT. Es Software Architect en
Alhambra-Eidos
un servicio Web, sino que se va a explicar cómo se
crea uno desde un proyecto Web de ASP.NET dentro de Visual Studio .NET, y cómo se va a utilizar
desde una página ASP.NET.
Aún así vamos a realizar una breve introducción
y definición de lo que se entiende por servicio Web.
La plataforma .NET posibilita la extensión del concepto de aplicaciones distribuidas mediante la construcción de servicios Web, que básicamente van a ser
funciones albergadas en un sitio Web a las que se puede llamar desde otra página remota (u otro tipo de
cliente). Además el .NET Framework posibilita su
fácil programación y manejo tal como veremos en
este artículo. Al fin y al cabo un servicio Web va a ser
un tipo de software publicado en un servidor y que
va a ser distribuido como un servicio.
Desde un punto de vista lógico, podemos pensar en
un servicio Web como en un componente, o caja negra,
que suministra algún servicio útil a los clientes, o consumidores. A diferencia de DCOM, RMI, IIOP, o cualquier otro modelo de objetos común de uso específico,
un consumidor accede a un servicio Web usando un
protocolo estándar, aceptado, y bien conocido, como es
HTTP, y un formato de datos basado en XML.
El punto de vista del consumidor del servicio
Web es el de una interfaz que expone un número de
métodos bien definidos. Todo lo que necesita el consumidor es llamar a esos métodos usando los protocolos estándares de Internet, pasando parámetros
en formato XML y recibiendo respuestas también
en formato XML.
Ya no vamos a entrar en más detalles en cuanto
a funcionamiento interno de los servicios Web, sino
que vamos a pasar a crear nuestro servicio Web desde Visual Studio .NET.
Creación de servicios Web. Servicio
Web:“Hola Mundo”
Partimos del supuesto de que ya hemos creado
una aplicación ASP.NET desde el explorador de
soluciones de Visual Studio .NET pulsamos con el
botón derecho del ratón sobre el proyecto y seleccionamos del menú la opción “Agregar/Agregar servicio Web”. Con esto agregaremos a nuestro proyecto un fichero especial que tiene la extensión
ASMX.
Este fichero es el que va a contener la definición
de nuestro servicio Web. En el fuente 1 se aprecia
el contenido que tiene la clase asociada a este fichero nada más ser creado por Visual Studio .NET.
Desde Visual Studio .NET ni siquiera tenemos
la posibilidad de ver el contenido del fichero ASMX
que se corresponde con el servicio Web que acaba-
[ ]
Podemos decir que los servicios Web son la
extensión natural del concepto de componente
que nos ofrece la plataforma .NET. Después veremos que ASP .NET ofrece soporte para construir servicios Web a través de ficheros con la
extensión .ASMX. Los servicios Web se pueden
considerar como el sistema de publicación de
componentes del .NET Framework.
<< dotNetManía
<< No se persigue realizar una definición exhaustiva de lo que es
13
<< dnm.asp.net
Imports System.Web.Services
<System.Web.Services.WebService(Namespace:=”http://tempuri.org/Art/Service1”)> _
Public Class Service1
Inherits System.Web.Services.WebService
#Region “ Código generado por el Diseñador de servicios Web “
Public Sub New()
MyBase.New()
‘El Diseñador de servicios Web requiere esta llamada.
InitializeComponent()
‘Agregar su propio código de inicialización después de
‘llamar a InitializeComponent()
End Sub
‘Requerido por el Diseñador de servicios Web
Private components As System.ComponentModel.IContainer
‘NOTE: el Diseñador de servicios Web requiere el siguiente procedimiento
‘Puede modificarse utilizando el Diseñador de servicios Web.
‘No lo modifique con el editor de código.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
components = New System.ComponentModel.Container
End Sub
servicio Web o bien de forma separada dentro de un assembly.
• Language : Este otro atributo es
opcional y nos permite indicar el
lenguaje que se va a utilizar para
compilar el servicio Web. Su valor
por defecto es VB, es decir, se utiliza el lenguaje Visual Basic .NET.
Para empezar vamos a crear un sencillo método; realizaremos para nuestro
primer contacto con los servicios Web
el famoso ejemplo “Hola Mundo”. Para
ello debemos utilizar el atributo
WebMethod. El código fuente resultante
sería así de sencillo (fuente 3):
<WebMethod(Description:=_
"el clásico Hola Mundo")> _
Public Function HolaMundo() As String
HolaMundo = "Hola Mundo"
End Function
Fuente 3
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
‘CODEGEN: el Diseñador de servicios Web requiere este procedimiento
‘No lo modifique con el editor de código.
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
Utilización de los servicios
Web
#End Region
‘EJEMPLO DE SERVICIO WEB
‘El servicio de ejemplo HelloWorld() devuelve la cadena Hello World.
‘Para generar, quite los comentarios de las siguientes líneas y, a continuación,
‘guarde y genere el proyecto.
‘Para probar este servicio Web, compruebe que la página de inicio es el archivo .asmx
‘ y presione F5.
‘
‘<WebMethod()> Public Function HelloWorld() As String
‘
HelloWorld = “Hello World”
‘ End Function
End Class
Ahora añadimos a nuestro proyecto
un formulario Web, es decir, la página
ASP .NET desde la que se hará uso del
servicio Web.
Si fuera necesario agregar una referencia Web a nuestro proyecto debemos pulsar con el botón derecho del
ratón sobre la carpeta References dentro del explorador de soluciones de
Visual Studio .NET y seleccionar la
opción de menú “Agregar referencia
Web”; en este punto aparece una pantalla como la de la figura 1 en la que
debemos indicar la URL del servicio
Web que vamos a utilizar.
Fuente 1
<%@ WebService Language="vb" Codebehind="ServicioWeb.asmx.vb" Class="Art.ServicioWeb" %>
Fuente 2
mos de crear, pero si lo visualizamos con
otro editor de texto veremos un código
similar al que se muestra en el fuente 2.
<<dotNetManía
La directiva @WebService
14
La directiva @WebService únicamente se puede utilizar en ficheros .ASMX,
ya se va a utilizar para indicar la clase en
la que se encuentra la implementación
del servicio Web. Esta directiva posee
dos atributos:
• Class: Este atributo es obligatorio y
vamos a utilizarlo para indicar el
nombre del la clase que implementa el servicio Web. La clase del servicio Web se puede encontrar definida en el propio fichero ASMX del
Figura 1
Una vez indicada la URL del servicio Web pulsamos el botón “Ir” y ya está
<< dnm.asp.net
localizado el servicio Web; ahora ya sólo
nos queda pulsar el botón etiquetado
como “Agregar referencia”. De esta forma la referencia Web estará añadida a
nuestro proyecto y podremos utilizar
sin problemas el servicio Web.
Realizado este paréntesis volvemos
a nuestro ejemplo de formulario Web
que va a hacer uso del servicio Web
recién creado.
Nuestra página ASP.NET va a ser
muy sencilla, va a contener un botón que
al ser pulsado va a realizar una llamada a
nuestro servicio Web para que muestra el
mensaje de “Hola Mundo” dentro de una
etiqueta. En el fuente 4 se puede observar el código fuente de esta sencilla página ASP.NET y su clase asociada (fuente
5) y una figura con el resultado de su ejecución (figura 2).
<WebMethod(Description:="devuelve el nombre de la máquina del servidor")> _
Public Function NombreServidor() As String
Return Server.MachineName
End Function
<WebMethod(Description:="devuelve la hora del servidor")> _
Public Function HoraServidor() As String
Return Context.Timestamp.TimeOfDay.ToString()
End Function
Fuente 6
Ahora vamos a añadir un par de
métodos más a nuestro servicio Web
(fuente 6); uno de ellos nos va a devolver el nombre del servidor en el que se
está ejecutando y otro la hora del mismo. Los métodos de nuestro servicio
Web son muy sencillos, pero son exactamente lo que necesitamos para mostrar de forma sencilla y práctica la cre-
Es el momento de modificar nuestra página ASP.NET para hacer uso de
estos dos nuevos métodos que hemos
incorporado al servicio Web. Podemos
añadir un botón más para que invoque
a estos métodos y el resultado de la ejecución de los mismos los mostrará en
otra etiqueta. El código resultante sería
de la siguiente manera (fuente 7).
Private Sub btnDatosServidor_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnDatosServidor.Click
lbDatosServidor.Text = MiServicio.NombreServidor() & "-----"& MiServicio.HoraServidor()
End Sub
Fuente 7
<%@ Page Language=”vb” AutoEventWireup=”false” Codebehind=”WebForm1.aspx.vb”
Inherits=”Art.WebForm1”%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name=”GENERATOR” content=”Microsoft Visual Studio .NET 7.1”>
<meta name=”CODE_LANGUAGE” content=”Visual Basic .NET 7.1”>
<meta name=”vs_defaultClientScript” content=”JavaScript”>
<meta name=”vs_targetSchema” content=”http://schemas.microsoft.com/intellisense/ie5”>
</HEAD>
<body MS_POSITIONING=”GridLayout”>
<form id=”Form1” method=”post” runat=”server”>
<asp:Button id=”btnHolaMundo” style=”Z-INDEX: 101; LEFT: 48px;
POSITION: absolute; TOP: 32px”
runat=”server” Text=”Hola Mundo” Width=”104px” Height=”24px”></asp:Button>
<asp:Label id=”lbHolaMundo” style=”Z-INDEX: 102; LEFT: 48px;
POSITION: absolute; TOP: 72px”
runat=”server” Width=”96px”></asp:Label>
</form>
</body>
</HTML>
Fuente 4
Public Class WebForm1
Inherits System.Web.UI.Page
Dim MiServicio As New ServicioWeb
Private Sub btnHolaMundo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnHolaMundo.Click
lbHolaMundo.Text = MiServicio.HolaMundo()
End Sub
End Class
Fuente 5
También se pueden pasar todos los
parámetros que sean necesarios a
nuestros servicios Web. Por ejemplo
podemos añadir un método que calcule el cubo del entero que le pasamos
por parámetro. El método sería así
(fuente 8):
<WebMethod(Description:="devuelve el “ &_
“cubo de un entero")> _
Public Function Cubo(ByVal valor As _
Integer) As Double
Return Math.Pow(valor, 3)
End Function
Fuente 8
Este nuevo método lo podemos utilizar desde la página ASP .NET, desde
la que le pasamos el valor de una caja de
texto para que calcule el valor al cubo
correspondiente. A continuación se puede observar el fragmento de código de
la clase de la página (fuente 9).
Private Sub btnCubo_Click(_
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnCubo.Click
lbResultado.Text = _
MiServicio.Cubo(txtValor.Text)
End Sub
Fuente 9
<<dotNetManía
Figura 2
ación y utilización de servicios Web.
Más adelante veremos cómo complicar
un poco nuestro servicio Web.
15
<< dnm.asp.net
Imports System.Data
Imports System.Data.SqlClient
Public Class Clase
Public Function DevuelveEmpleados() As DataSet
Dim conexion As SqlConnection = New SqlConnection( _
"server=(local);database=northwind;uid=sa;pwd=xxx")
Dim adapterEmpleados As SqlDataAdapter = New SqlDataAdapter( _
"select firstname, lastname from Employees", conexion)
Dim ds As DataSet = New DataSet
conexion.Open()
adapterEmpleados.Fill(ds, "Empleados")
conexion.Close()
Return ds
End Function
End Class
Fuente 10
<WebMethod(Description:="devuelve a través de un clase un DataSet de empleados")> _
Public Function DevuelveEmpleados() As DataSet
Dim MiObjeto As New Clase
Return MiObjeto.DevuelveEmpleados()
End Function
Fuente 11
<%@ Page Language=”vb” AutoEventWireup=”false” Codebehind=”WebForm1.aspx.vb”
Inherits=”Art.WebForm1”%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name=”GENERATOR” content=”Microsoft Visual Studio .NET 7.1”>
<meta name=”CODE_LANGUAGE” content=”Visual Basic .NET 7.1”>
<meta name=”vs_defaultClientScript” content=”JavaScript”>
<meta name=”vs_targetSchema” content=”http://schemas.microsoft.com/intellisense/ie5”>
</HEAD>
<body MS_POSITIONING=”GridLayout”>
<form id=”Form1” method=”post” runat=”server”>
<asp:Button id=”btnSQL” style=”Z-INDEX: 105; LEFT: 32px; POSITION: absolute;
TOP: 24px” runat=”server” Text=”Datos SQL”></asp:Button>
<asp:DataGrid id=”dgDatos” style=”Z-INDEX: 106; LEFT: 144px; POSITION: absolute;
TOP: 24px” runat=”server”></asp:DataGrid>
</form>
</body>
</HTML>
de datos; para realizar esta función utilizará una clase que vamos a agregar a
nuestro proyecto de Visual Studio
.NET, esto es tan fácil como pulsar con
el botón derecho del ratón sobre nuestro proyecto y seleccionar del menú la
opción de “Agregar clase”.
El contenido del fichero VB en el
que se define la clase va a ser el del fuente 10. Tiene un método que nos va a
devolver en un objeto DataSet el contenido de la tabla de empleados.
Desde el servicio Web podemos utilizar directamente la clase recién creada,
es tan sencillo como instanciar un objeto de la clase y realizar la llamada al método correspondiente. En el siguiente código se puede apreciar la implementación
del método del servicio Web que hace
uso de esta clase (fuente 11).
En todo este proceso ahora nos queda únicamente realizar la llamada al servicio Web desde la página ASP.NET. El
código resultante sería el siguiente: primero aparece el código de la página
(fuente 12) y luego el fragmento de código de la clase (fuente 13), también
adjuntamos una figura en la que se
muestra un ejemplo de ejecución de esta
página (figura 3):
Fuente 12
Private Sub btnSQL_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)_
Handles btnSQL.Click
dgDatos.DataSource = MiServicio.DevuelveEmpleados()
dgDatos.DataBind()
End Sub
Fuente 13
<<dotNetManía
Servicios Web y acceso a datos
16
En algunos casos los servicios Web
dentro de aplicaciones ASP.NET se utilizan como una capa intermedia de acceso a datos, en una arquitectura de una
aplicación Web determinada pueden contener únicamente los métodos que hacen
uso de clases de .NET que serán las
encargadas de acceder a los datos.
Vamos a realizar para nuestro servicio Web del ejemplo un método un poco
más complicado que los anteriores. Este
método nos va a devolver el contenido
de una tabla de empleados de una base
Figura 3
Ésta suele ser la forma más común
de utilizar los servicios Web dentro de
un entorno real de una aplicación Web
de ASP.NET. El servicio Web es una
capa intermedia entre las páginas
ASP.NET y un conjunto de clases que
van a realizar las operaciones sobre las
bases de datos.
Ahora animo a los lectores a que
empiecen a hacer uso de los servicios
Web dentro de sus proyectos de aplicaciones Web; como se ha podido observar es algo muy sencillo.
dnm.comunicaciones
Braulio Díez
Redes de mensajería y .NET (y II)
En la primera parte de esta serie, vimos cómo iniciar una sesión con Messenger
(autentificándonos con éxito) y chequear nuestra lista de contactos. En esta segunda parte vamos a ver como “chatear” con ellos.
<< Servidores SwitchBoard
Si los servidores de notificación nos sirven para
dar a conocer nuestro estado y sincronizar nuestra
lista de contactos, los Switchboard (que llamaremos
también servidores de charla) sirven como salas en
las que podemos establecer charlas con uno o varios
compañeros.
Hay dos formas de entrar en una charla:
• Pasiva: Alguien nos invita a que participemos
en una conversación (el mensaje que recibimos para ello, es muy descriptivo RNG…
¡Ring!).
• Activa: Reservamos una sala de charla en un
Switchboard server, y le comunicamos a
alguien de nuestra lista que queremos hablar
con él.
<< dotNetManía
Entrar en charla de forma pasiva
18
Cuando un contacto de nuestra agenda quiere
hablar con nosotros, reserva una sala de charla, y
nos envía un mensaje en el que nos indica en qué
dirección IP está dicha sala (el servidor switchboard), la secuencia de pasos sería la siguiente:
1. Recibimos un mensaje RNG indicándonos que
uno de nuestros contactos quiere establecer una
sesión de charla con nosotros (este comando
nos da la dirección IP del servidor de charla al
que nos debemos conectar) así como un valor
que usaremos para autentificarnos.
2a. Establecemos una conexión con el servidor de
charla que se indicó en el mensaje previo y confirmamos nuestra presencia enviando un mensaje ANS (en el que indicamos como parámetro el ID de sesión y el valor de autentificación
que obtuvimos en el paso previo).
2b El servidor nos contesta dándonos una lista con
los usuarios que pertenecen a esa charla. Para
ello nos envía una serie de mensajes IR0 en los
que se incluye el nombre de cada participante,
y da por terminada la lista enviándonos un mensaje ANS.
Cliente
Messenger
1. << Mensaje RNG, alguien quiere
hablar con nosotros
Servidor de
notificación
2. >> Conexión con el servidor de charla
enviando un mensaje ANS
2. << Lista de usuarios que pertenecen a
esa charla, IR0
Servidor de
charla
Ya estamos preparados para enviar y recibir mensajes de “chateo”
Figura 1. Un contacto de nuestra agenda quiere hablar con nosotros.
En la figura 1 puede ver un esquema de cómo
se realiza ese diálogo y en la tabla 1 la secuencia de
mensajes al detalle.
Entrar en charla de forma activa
Si somos nosotros los que queremos iniciar una
conversación, esto implica un poco más de trabajo
que en el apartado anterior: Pedimos una sala de charla libre al servidor de notificación, conectamos con
Braulio Díez
colabora habitualmente con
dotNetManía. Es MCSD en
programación distribuida
con Visual C++.
Es Solutions Developer
de Avanade.
<< dnm.comunicaciones
PASO 1. Recibimos del servidor de notificación un mensaje RNG en el que alguien nos indica que quiere hablar con nosotros (para ello, el mensaje
nos da la dirección IP del servidor de charla al que nos tenemos que conectar y el identificador de la sala que nos ha reservado esa
persona).
//
//
//
//
<<
Recibimos del servidor de notificación una petición de charla. Los parámetros que tiene el mensaje son:
ID de sesión de charla (podemos decir que es la sala), dirección IP del servidor de charla (switchboard server),
algoritmo que se usa para la autentificación (siempre CKI), token que se usa para autentificarnos, dirección de
correo y nombre de la persona que nos quiere contactar.
RNG 11752013 207.46.108.38:1863 CKI 849102291.520491113 [email protected] Example%20Name\r\n
PASO 2. Nos conectamos a la direccion del servidor de charla que obtuvimos en el paso anterior, le enviamos un mensaje ANS para confirmarle que
queremos entrar en la sesión de charla, y el servidor de charla nos contesta dándonos una lista de los participantes de la misma.
// ¡OJO!, al servidor de notificación no le respondemos nada, NOS CONECTAMOS AL SERVIDOR DE CHARLA
// QUE OBTUVIMOS EN EL MENSAJE ANTERIOR.
//
//
//
>>
El comando ANS tiene cuatro parámetros: La secuencia del mensaje (es un contador que vamos llevando nosotros,
ver primera parte del artículo para más información), nuestra cuenta de pasaporte, el token de autentificación y el
identificador de sesión de charla.
ANS 1 [email protected] 849102291.520491113 11752013\r\n
//
//
//
<<
<<
El servidor nos informa de que participantes están en la conversación; el primer parámetro es el numero de
secuencia del mensaje, el segundo la posición del participante en la lista de IR0's, el tercero es el número total
de participantes que hay en esa lista, el cuarto es la cuenta passport del participante y el quinto su nombre.
IRO 1 1 2 [email protected] Mike\r\n
IRO 1 2 2 [email protected] My%20Name\r\n
// Cuando se han enviado toda la lista de participantes, el servidor nos lo notifica con un mensaje ANS, con el mismo
// número de secuencia que el ANS original que enviamos.
<< ANS 1 OK\r\n
Tabla 1. Un contacto de nuestra agenda quiere hablar con nosotros (secuencia de comandos)
cador de sesión que está asociado
a la charla.
3c. Una vez que la persona con la que
queremos hablar le ha confirmado
1. >> Petición de reserva, XFR
Cliente
Messenger
1. << Dirección de servidor de charla e identificador de sesión
Servidor de
notificación
2. >> USR con conexión y autentificación
2. << Confirmación sala reservada
3. >> Petición de llamada a un contacto, CAL
3. << CAL del servidor RINGING, llamando al contacto
Servidor de
charla
3. << Contacto acepta la invitación, JOI
Ya podemos comenzar la charla
Figura 2.Tomamos la iniciativa, y establecemos nosotros la conversación
con uno de nuestros contactos
<<dotNetManía
ella, y a continuación invitamos a las
personas con las que queremos hablar.
La secuencia de pasos es la siguiente:
1a. Enviamos una petición de reserva de
sala de charla (mensaje XFR).
1b. El servidor nos contesta indicándonos a qué servidor de charla nos
podemos conectar, y cuál es nuestro
identificador de sesión de charla.
2a. Establecemos conexión con el servidor de charla y nos autentificamos
enviándole un mensaje USR con el
identificador de sesión que obtuvimos en el paso previo.
2b. El servidor nos contesta informándonos que la sala ha sido reservada
satisfactoriamente.
3a. Le pedimos al servidor de charla que
llame (mensaje CAL) a uno de nuestros contactos.
3b. El servidor nos contesta con otro
CAL que tiene como parámetro la
cadena ”RINGING” , en el que nos
confirma que está llamando a ese
contacto. Otro parámetro que
incluye ese mensaje es el identifi-
19
<< dnm.comunicaciones
PASO 1. Envíamos al servidor de notificación una petición de reserva de sala de charla (XFR), el servidor nos contesta dandonos la dirección IP de
un servidor de charla (Switchboard server).
//
//
//
>>
Enviamos al servidor de notificación una petición de sala de charla, los parámetros que tiene el mensaje son:
número de secuencia del mensaje (ver puntos anteriores) y un segundo parámetro SB que significa
“Switchboard” (pedimos conexión con un servidor de charla).
XFR 15 SB\r\n
//
//
//
<<
El servidor nos contesta dándonos la dirección IP y el puerto del servidor de charla al que nos debemos conectar
(tercer parámetro) y una cadena de autentificación que el servidor de charla nos pedirá cuando nos conectemos
(último parámetro).
XFR 10 SB 207.46.108.37:1863 CKI 17262740.1050826919.32308\r\n
PASO 2. Nos conectamos a la dirección del servidor de charla obtenida y le enviamos un mensaje USR con la cadena de autentificación que recibimos
en el paso anterior, si todo va bien el servidor nos contesta con otro mensaje USR con un parámetro cuyo valor es OK.
//
//
//
>>
NOS CONECTAMOS AL SERVIDOR DE CHARLA QUE OBTUVIMOS EN EL MENSAJE ANTERIOR.
El comando USR tiene tres parámetros: la secuencia del mensaje, nuestra cuenta de pasaporte y la cadena de
autentificación que obtuvimos en el paso anterior.
USR 1 [email protected] 17262740.1050826919.32308\r\n
// Si todo va bien el servidor nos contesta con otro USR, con un parámetro con valor OK.
<< USR 1 OK [email protected] Example%20Name\r\n
PASO 3. Le decimos al servidor de charla que queremos hablar con uno de nuestro contactos, el servidor nos notifica que lo está llamando, por último, si
el contacto ha contestado afirmativamente a la llamada, el servidor nos informa de ello (en este caso ya podemos comenzar a hablar con él).
// El comando CAL sirve para invitar a alguien a una conversación, tiene como parámetros: el número de secuencia
// del mensaje, la cuenta pasaporte del usuario con el que queremos contactar.
>> CAL 2 [email protected]\r\n
// El servidor de charla nos indica que lo está llamando (Ringing) y nos da el identificador de sesión de la charla.
// (último parametro)
<< CAL 2 RINGING 11752013\r\n
// Si el contacto quiere hablar con nosotros, el servidor nos confirma que se ha unido a la charla, enviándonos un
// mensaje JOI (join).
<< JOI [email protected] Name_123\r\n
Tabla 2. Queremos establecer contacto con un miembro de nuestra lista de contactos (secuencia de comandos)
al servidor de charla que quiere establecer comunicación con nosotros,
este nos envía un comando JOI
(join), en el que nos indica que esa
persona ya está metida en la conversación.
<<dotNetManía
En la figura 2 puede ver un esquema de cómo se realiza ese diálogo, y en
la tabla 2 la secuencia de mensajes al
detalle.
20
Chateando…
Una vez que ya tenemos la sala de
charla a punto, para comunicarnos con
[
Firewalls, Proxies…
Para poder conectarnos a Messenger nos hace falta establecer como cliente una conexión TCP a un servidor, pero algunos
administradores de red cortan esa posibilidad por motivos de seguridad. Cuando esto pasa tenemos que cambiarnos a la implementación del protocolo de Messenger via HTTP (bastante más lento
que usando TCP, pero si no hay más remedio…).
Podemos tener otro pequeño problema si tenemos que pasar
por un servidor proxy, ya que esto nos afectará a las peticiones
HTTPS que hagamos para autentificar nuestro pasaporte (las clases de .NET framework que gestionan esto, permiten añadir la
dirección de nuestro proxy).
]
<< dnm.comunicaciones
>>
MSG
Descripción
Vamos sólo a cubrir el caso de un mensaje con texto de un participante:
//
//
//
//
//
//
//
>>
En la cabecera del mensaje le indicamos nuestro número
de secuencia, si queremos que nos confirme que el mensaje
ha llegado y la longitud del cuerpo del mensaje en bytes.
En el cuerpo, podemos ver que el mensaje es de tipo "plain
text" y que el encoding que usa es UTF-8, tambén le
indicamos otros datos como la fuente, el color... y por
supuesto el texto que envíamos al participante... :-).
MSG 4 N 133\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22\r\n
\r\n
Hello! How are you?\r\n
// El servidor nos notifica que el mensaje se recibió satisfactoriamente.
<< ACK 4 0\r\n
<<
MSG
Recibimos texto de un particpante (podríamos recibir otro tipo de información en este mensaje), ejemplo:
// La cabecera del mensaje nos indica la cuenta de pasaporte y
// nombre de la persona que nos envía el mensaje, así como la
// longitud del cuerpo del mensaje.
// El cuerpo del mismo es igual al MSG de salida que hemos
// visto previamente.
<<< MSG [email protected] Mike 133\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=UTF-8\r\n
X-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22\r\n
\r\n
Hello! How are you?\r\n
Tabla 3. Mensajes MSG
los participantes de la misma enviaremos mensajes del tipo MSG, y recibiremos también mensaje de ese tipo
cuando un participante quiera contarnos algo, ¿Simple...? Bueno, estos mensajes son del tipo payload, están compuestos por una línea de texto (que termina con \r\n) y un cuerpo de longitud
variable (longitud indicada por un parámetro en la línea de texto anterior). Esta
segunda parte nos puede indicar acciones como que el participante en concreto está tecleando, o simplemente
recibir en ella el mensaje. En la tabla 3
puede ver la descripción de un mensaje con texto de charla.
Como el contenido de un MSG es
variable, se podrían implementar clientes
que fueran capaces de enviar y recibir contenidos de mensajes con formato HTML
o RTF. Sería interesante, por ejemplo,
desarrollar un messenger para programadores que respetara el formato y colores
del código fuente que enviemos.
Ampliando nuestro ejemplo
en .NET
A nuestro ejemplo de messenger, le
hemos añadido un nuevo namespace, se
llama SwitchboardServer y se encarga de
comunicarse con los servidores de charla. Al haber partes comunes con el
namespace de notificación, he hecho un
poco de refactoring y subido funcionalidad común a clases base que se comparten en el namespace General. Un diagrama con las clases principales lo puede ver en la figura 3.
Las novedades más destacadas que
se han introducido son:
Namespace General
Este incluye funcionalidad común,
hemos añadido algo extra de funcionalidad.
• MixedCharByteReader: Hasta ahora para leer mensajes, usabamos la
clase StreamReader , que nos permite, de una forma muy cómoda,
leer líneas de texto (detecta por
nosotros donde está el salto de
línea) y bloques de texto, pero...
tenemos un pequeño problema, los
mensajes con payload indican la
longitud del cuerpo del mensaje en
Figura 3. Diagrama de clases de nuestra assembly de ejemplos.
<<dotNetManía
Dirección Mensaje
21
<< dnm.comunicaciones
Namespace NotificationServer
Figura 4. Funcionamiento de una charla “pasiva”
<<dotNetManía
bytes, y al estar esto codificado con
UTF-8 (compatible con ASCII),
en cuanto introducimos un caracter especial (como una letra con
una tilde) el número de caracteres
a leer ya no coincide con el número de bytes a leer. Solución: leer
siempre bytes, e implementar una
clase que nos ayude a leer líneas de
texto y bloques de bytes.
22
[
Pocos cambios en este espacio de
nombres, los necesarios para gestionar las
sesiones de charla.
• NotificationServer: Para poder
iniciar una conversación tenemos
que pasar por este servidor. Aquí es
donde se nos asigna una dirección
IP de un servidor de charla (cuando comenzamos una charla de forma activa) y donde recibimos mensajes RNG, que nos indican que un
contacto quiere comenzar una charla con nosotros.
Nota: La aplicación de ejemplo (disponible en www.dotnetmania.com) está realizada para poder “jugar” un poco con la red
messenger; está lejos de ser un código en productivo, para dar este paso habría que añadir un control de errores más exhaustivo,
tapar posibles agujeros, etc.
¿Peer to Peer?
Cuando usamos Messenger no estamos trabajando de “igual a igual”,
en realidad cuando hablamos con alguien, no estamos físicamente conectados a esa persona, sino que ambos nos conectamos a un servidor
Messenger, podemos decir que ese servidor hace de proxy entre nosotros
y las personas con las que hablamos.
]
Namespace SwitchboardServer
Para saber más
Este es nuevo; envuelve toda la
implementación para gestionar las sesiones de charlas (en figura 4 puede ver un
esquema del funcionamiento de una
charla pasiva).
• SwitchboardSession: Esta clase se
encarga de gestionar una sesión de
charla en concreto. Dispone de
una hebra que será la encargada de
escuchar todos los mensajes relacionados con esa charla, así como
de variables miembro que contienen información acerca de los participantes de la charla, cadena de
autentificacion, eventos para notificar la llegada de nuevos mensajes, etc.
• SwitchboardDispatcher: Es un contenedor de objetos. Tiene en una
tabla hash los pares Session ID /
SwitchboardSession, controla su creación y destrucción.
Bueno, nos hemos “logado” a Messenger, hemos mantenido charlas con nuestros contactos, pero... ¡Yo quiero enviar ficheros¡ ¡Yo quiero conectarme con la webcam ¡ ¡Yo quiero...¡, si quiere seguir investigando sobre este interesante tema, aquí
tiene unos links que le pueden ser de ayuda:
Acerca del protocolo
• La web “maestra” sin duda alguna es: http://www.hypothetic.org/docs/msn/ ,
muy completa (allí también encontrará unos apuntes sobre aspectos legales
muy interesantes: http://www.hypothetic.org/docs/msn/phorum/read.php?f=1&i=
2169&t=2169 ).
• Otra, en la que encontrará información acerca de esta y otra redes de mensajería: http://www.chat.solidhouse.com.
• Tratando el tema de la seguridad, este documento es interesante:
http://bofriis.dk/security/securing_msn.pdf.
Implementaciones .NET:
• Una implementación en C# del proceso de “login” la puede encontrar en:
http://www.codeproject.com/csharp/ClientTicket_MSNP9.asp.
• Otra Implementación en C#, esta más completa, de libre uso, pero sin fuentes (sólo el assembly) es: http://members.home.nl/b.geertsema/dotMSN.
dnm.plataforma.net
José M.Alarcón
Ampliando la capacidad de los controles y
ventanas mediante técnicas de subclasificación
La subclasificación de ventanas es una técnica específica de la plataforma Windows
que permite ampliar las capacidades de la mayoría de los controles y formularios
de Windows Forms. Con su uso se consiguen características poco frecuentes
pero muy útiles.Veamos cómo sacarle partido.
José Manuel Alarcón
es redactor de dotNetManía.
es ingeniero industrial y
especialista en consultoría de
empresa. Ha escrito varios libros,
y ha publicado más de d
oscientos artículos sobre
informática e ingeniería en
revistas especializadas.
da desde sus orígenes en la existencia de mensajes que
se envían constantemente a las ventanas. Cualquier cosa
que ocurre en la interfaz está sustentada en el envío de
mensajes. Por ejemplo, cuando pulsamos con el ratón
sobre un botón éste puede responder a nuestra acción
porque el sistema operativo le envía un mensaje indicándole lo que ocurre. Junto con el mensaje se le facilita también toda la información que necesita para gestionar el evento: posición del cursor, qué botón del ratón
se ha usado, las teclas que están pulsadas, etc… Del mismo modo se envían mensajes a las ventanas para indicarles que se maximicen, se muevan, cambien de tamaño o incluso para que redibujen los controles que hay
en su superficie.
Además de hacerlo el propio sistema operativo, otras
aplicaciones también pueden generar y enviar sus propios mensajes. De este modo es factible modificar el
comportamiento de controles y ventanas aunque éstas
no pertenezcan a nuestra aplicación. Existen técnicas
de comunicación entre procesos que utilizan mensajes
para intercambiar información de una forma genérica.
En definitiva, los mensajes constituyen una parte integral del sistema y gracias a ellos se pueden conseguir
multitud de efectos y características avanzadas.
La primera manera de sacarle partido a los mensajes es enviándolos. Gracias a una función de la API de
Windows, que luego estudiaremos, seremos capaces de
enviar mensajes a ventanas y controles para forzarlas a
hacer algo u obtener información sobre ellas.
La otra manera de utilizar en nuestro provecho los mensajes es interceptándolos. Esta es la
base de la subclasificación: interceptar mensajes
dirigidos a una ventana para modificarlos, anularlos o responder a ellos.
Dadas las muchas limitaciones de las que adolecían los formularios de Visual Basic clásico, esta técnica tenía un potencial increíble en aquella época.
Por ejemplo, era indispensable realizar subclasificación para manejar iconos en el área de notificación
o responder a notificaciones de cambios de archivos,
por no mencionar la detección de muchas acciones
que se llevaban a cabo sobre los formularios y para
las que no había eventos. En la actualidad .NET y
Windows Forms ofrecen tanta capacidad “de serie”
que la subclasificación ya no es tan necesaria como
antes. Sin embargo todavía hay muchas ocasiones en
las que nos quitará de apuros.
Para vislumbrar la potencia de estas técnicas
vamos a desarrollar varios ejemplos que nos permitan estudiarla en la práctica, haciéndolo más entretenido. El código se escribirá en C# pero el lector
interesado puede traducirlo a Visual Basic .Net con
mucha facilidad porque es prácticamente idéntico.
En la Web de la revista (www.dotnetmania.com) encontrará un archivo con los ejemplos ya desarrollados
para facilitar su estudio. Le recomiendo que descargue estos ejemplos antes de continuar la lectura o
puede que le resulte difícil seguirla.
Primer ejemplo: engañando a una
ventana
Los formularios de Windows Forms poseen una
propiedad muy interesante llamada TransparencyKey
que sirve para especificar qué color de su superficie
<<dotNetManía
<< La interfaz gráfica del sistema operativo Windows está basa-
23
<< dnm.plataforma.net
<<dotNetManía
Figura 1. Las ventanas transparentes son muy espectaculares y fáciles de crear en .NET. La
mayor dificultad viene a la hora de moverlas por carecer de barra de título. Subclasificando las
pulsaciones del ratón podemos conseguirlo fácilmente.
24
se considerará transparente. De este
modo basta con pintar algo sobre el área
cliente del formulario (o asignar un gráfico cualquiera como fondo) para que
las partes de éste que sean del color indicado en TransparencyKey se vuelvan
transparentes (ver figura 1). Esto permite crear de una forma sencilla y rápida formularios con formas extrañas o
caprichosas. Normalmente estos formularios, al igual que el de la figura,
carecen de barra de título (propiedad
FormBorderStyle con valor None) para
que se parezcan lo menos posible a un
formulario normal. El problema es que,
al hacer esto, no hay forma de moverlas de su sitio ya que les falta la zona
superior por la que normalmente se
arrastran.
¿Cómo solucionamos esta situación?
Muy fácil: engañando al formulario para
que, al pulsar en cualquier parte de él se
piense que en realidad se ha pulsado
sobre la barra de título inexistente. Esta
es una primera aplicación obvia de la
subclasificación.
Al contrario de lo que ocurría con
otros lenguajes antiguos (Visual Basic, C,
C++), poner en marcha esta técnica en
.NET es sorprendentemente fácil. Basta
con sustituir el método WndProc del formulario en cuestión para conseguirlo.
Todas las ventanas de Windows
(sean de .Net o no) disponen de una
rutina especial que es la encargada de
procesar todos los mensajes que se le
envían. Normalmente hay que usar técnicas avanzadas para sustituir este procedimiento por otro propio y poder gestionar nosotros mismos los mensajes.
Sin embargo los diseñadores de Windows Forms pensaron en hacernos la
vida mucho más fácil a los programadores .NET y exponen dicha rutina
como miembro de la clase Form con el
nombre de WndProc. Por lo tanto basta
con sustituirla por una propia para obtener todo el control sobre los mensajes.
debemos procesar para engañar a la ventana.
Cuando se pulsa sobre un lugar
cualquier de una ventana, Windows le
envía a ésta un mensaje de tipo
WM_NCHITTEST. Cada mensaje se define
con un valor numérico que en este caso
es el número 84 en hexadecimal, por
lo que es muy fácil detectarlo en la
rutina de gestión de mensajes. Al
enviar este mensaje, Windows envía
también como información adicional
en qué zona concreta de la ventana se
ha pulsado. Por ejemplo, cuando se
pulsó sobre el área cliente el valor es
HTCLIENT (1), y si se toca la barra de
título el valor es HTCAPTION (2). Todas
estas constantes están definidas en el
archivo winuser.h del SDK de plataforma para C/C++, disponible de
manera gratuita en la Web de MSDN
(http://www.microsoft.com/msdownload/platformsdk/sdkupdate) e incluido
con Visual Studio.
Bien, en resumen, lo que debemos
hacer para mover la ventana por su área
cliente es capturar el mensaje WM_NCHITTEST cuando se pulse sobre el área cliente de la ventana y engañar a ésta diciéndole que en realidad se ha pulsado sobre
la barra de título. Todo el código que
necesitamos es el del fuente 1 dentro del
formulario.
//Constantes de mensajes
private const int WM_NCHITTEST = 0x0084;
private const int HTCLIENT = 1;
private const int HTCAPTION = 2;
protected override void WndProc(ref Message m)
{
base.WndProc (ref m);
if (m.Msg == WM_NCHITTEST)
{
if(m.Result.ToInt32() == HTCLIENT)
m.Result = new IntPtr(HTCAPTION);
}
}
Fuente 1
Una vez que podemos recibir desde
nuestro código todos los mensajes dirigidos a una ventana, podemos decidir
cuáles merecen nuestra atención o no,
procesándolos de la forma más pertinente. Sabiendo esto, para acabar nuestro primer ejemplo, sólo necesitamos
saber una cosa más: el mensaje que
Las primeras líneas definen las constantes que necesitamos. El método
WndProc recibe los mensajes de la ventana por lo que sólo debemos comprobar
cuándo se recibe el que estábamos buscando (WM_NCHITTEST), y cambiamos el
resultado del procesamiento asignándole otro valor.
<< dnm.plataforma.net
Segundo ejemplo: mejorando
los formularios
La mayoría de los eventos de los
formularios y controles de Windows
Forms son en realidad el resultado del
procesamiento de un mensaje.
Minimizar una ventana, cambiarla de
tamaño, activarla, moverla, etc… todas
estas acciones se traducen en mensajes
que es posible capturar. La plataforma
.NET expone infinidad de eventos en
sus controles y formularios que se
corresponden con mensajes de
Windows por lo que la mayoría ya
están contemplados nativamente y no
Los mensajes de ventana forman parte intrínseca y
fundamental de la arquitectura de Windows.
Comprendiendo el uso que el sistema hace de ellos
es posible sacarle mucho partido para mejorar las
características de nuestras aplicaciones Windows Forms
tendremos necesidad de utilizar
técnicas de subclasificación para
gestionarlos desde nuestro código.
De todos modos hay todavía algunos que no se gestionan y que en
determinadas ocasiones pueden
resultarnos de utilidad. Por ejemplo, sería de mucha utilidad que
los formularios dispusieran de un
evento que se notificase cuando
cambie la resolución de la pantalla de modo que pudiéramos adaptar su tamaño o la disposición de
los controles de forma automática. La clase Form no dispone de
nada similar.
He creado un ejemplo que define una nueva clase FormMejorada
heredada de Form que es idéntica a
ésta pero que añade algunas características interesantes mediante subclasificación. La clase FormMejorada
Figura 2. Nuestro formulario ampliado ofrece tres nuevos
añade tres nuevos eventos a los foreventos que le permitirán reaccionar a los cambios de resomularios Windows (figura 2).
lución de pantalla, a modificaciones del tema estético aplica• ResChanged: se notifica este do a las ventanas y a condiciones de falta de memoria libre.
evento cuando cambia la
resolución de la pantalla.
• ThemeChanged: se lanza cuando el
de Form que sobrescribe el método
usuario cambia el tema activo en
WndProc y detecta tres mensajes espeel escritorio desde las propiedaciales que Windows envía a todas las
des de pantalla.
ventanas activas cuando ocurre alguno
• LowMemory: notifica a la aplicación
de estos eventos, y que son: WM_DISPLAYCHANGE, WM_THEMECHANGED y WM_COMque hay poca memoria libre en el
PACTING respectivamente. La figura 3
sistema. Puede resultar de mucha
utilidad en aplicaciones que conmuestra el código del procesamiento de
suman muchos recursos. Al recimensajes. Estudie con detenimiento el
bir este evento podemos liberar
código que puede descargar desde la
recursos cerrando ventanas inneWeb de la revista y verá que no tiene
cesarias, manteniendo menos
mayor complicación.
datos en memoria o con acciones
Para que uno de nuestros formusimilares.
larios pueda hacer uso de este nuevo
tipo de ventana mejorada sólo teneEl código es muy sencillo y consismos que acudir a su código y camte en definir una nueva clase heredada
biarlo para que en lugar de heredar de
<<dotNetManía
El resultado es un puntero a un valor
entero por lo que no debemos asignarle directamente HTCAPTION sino que
encapsulamos antes este valor en una
clase IntPtr que representa el puntero
necesario.
La clase Message ofrece a través de
sus miembros todo lo necesario para
acceder a la información del mensaje de
Windows recibido en cada momento.
La propiedad Msg contiene el valor del
mensaje que se ha recibido. La propiedad Result es un puntero al resultado
del procesamiento del mensaje. Las propiedades WParam y LParam contienen punteros a ciertos valores que se pueden
pasar con el mensaje y que dependen
del tipo de éste, ofreciendo adicionalmente el método GetLParam como un
medio para copiar esta información a las
estructuras con las que se corresponden.
No vamos a profundizar en estos parámetros porque dependen del mensaje
concreto que se procese y vienen profusamente documentadas en el SDK de
plataforma.
Siempre se debe permitir que el procedimiento original de la ventana procese también el mensaje o de otro modo
impediremos que llegue correctamente a su destino y se impedirá el funcionamiento de la ventana, de ahí la llamada de la primera línea que ejecuta el
proceso WndProc original al que estamos
sustituyendo.
Con esto hemos engañado a la ventana. Pruebe el ejemplo adjunto a este
texto y verá cómo arrastrando por cualquier sitio la ventana transparente podrá
moverla sin problemas.
25
<< dnm.plataforma.net
System.Windows.Forms.Form lo haga de
FormMejorada. Sólo con cambiar esto,
<<dotNetManía
los formularios heredan estas interesantes características.
Además de los mencionados eventos, y con la intención de ilustrar el uso
de mensajes propios, nuestros formularios mejorados añaden también una nueva característica. Se trata de una opción
adicional en el menú del sistema (que es
el que aparece al pulsar sobre el icono
de la ventana o sobre el botón correspondiente a ésta en la barra de tareas
(vea la figura 4). En este caso se añade
un separador y una opción “Acerca
de…” como muestra la figura. Al pulsar sobre el nuevo menú, se muestra un
diálogo con información sobre la aplicación.
Para conseguir este efecto debemos recurrir primero a la API de
Windows para agregar la nueva opción
al menú del sistema del formulario.
Estudiar el uso de la API desde .NET
se sale del ámbito de este artículo por
lo que no profundizaremos en ello (el
lector puede ver el código completo
en la descarga), pero mencionaré que
es necesario utilizar dos funciones de
la API en el constructor de la clase
FormMejorada:
• GetSystemMenu : esta función
devuelve el manejador del menú
del sistema del formulario que
se le indique en el primer parámetro.
• AppendMenu : agrega una nueva
opción de menú como hija del
menú que se le indica como primer parámetro.
26
Cuando un usuario pulsa sobre un
menú también se envía un mensaje a
la ventana que lo contiene. El valor
identificador de dicho mensaje dependerá del menú en concreto que se ha
seleccionado, pero en el caso del menú
del sistema dicho valor es estándar y
viene definido por la constante
WM_SYSCOMMAND que es el que debemos
detectar. Este mensaje viene acompañado por un parámetro que indica qué
opción concreta del menú en cuestión
es la que se ha seleccionado. En nuestro caso como la opción la definimos
nosotros mismos podemos elegir el
identificador que deseamos utilizar;
en este caso hemos elegido el entero
1000 , y lo representamos con una
constante de nombre WM_ACERCA_DE. Al
definir la nueva opción de menú indicamos al sistema que debe usar como
texto “Acerca de…” y como identificador del menú WM_ACERCA_DE (vea el
código). Ahora lo único que nos queda es capturar el mensaje correspondiente, lo cual se consigue con sólo
añadir las líneas del fuente 2 a la sentencia switch de la figura 3.
deseemos o incluso interceptar la pulsación de las opciones estándar (minimizar,
maximizar, mover…) para sustituirlas o
modificar su comportamiento.
Tercer ejemplo: un cuadro de
texto un tanto especial
En Windows no sólo los formularios
son tratados como ventanas. En realidad
casi todos los controles con un área de
usuario se tratan exactamente del mismo
case WM_SYSCOMMAND:
if (m.WParam.ToInt32() == WM_ACERCA_DE)
MessageBox.Show("(c) José M. Alarcón Aguín 2004 \n\n www.jasoft.org",
"Acerca de...", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
Fuente 2
Figura 3. Código de gestión de mensajes para generar los eventos de nuestro formulario
extendido.
Es decir, si el mensaje revela una pulsación sobre el menú del sistema, se comprueba además si la opción elegida es la
nuestra, en cuyo caso se muestra un diálogo con el copyright. Usando esta técnica
podemos añadir tantas opciones como
modo y no son más que tipos especiales
de ventanas. Así, los cuadros de texto,
botones, listas desplegables, rejillas,
menús, barras de botones, e infinidad de
controles no son más que tipos especiales
de ventana. Otros controles que se dibu-
<< dnm.plataforma.net
jan mediante código no se tratan como
tales. El ejemplo más evidente es el de las
etiquetas (Label), que no son ventanas.
Normalmente todos los controles que son
ventanas disponen de una propiedad
Handle que permite obtener su manejador
de ventana.
Todos los tipos de ventana funcionan
exactamente igual en lo que se refiere al
tratamiento de mensajes. Por lo tanto es
posible subclasificar también los controles para mejorar sus características. Sólo
Figura 6. Código del cuadro de texto ampliado que gestiona los mensajes del portapapeles,
los anula y sustituye sus acciones asociadas.
es necesario conocer qué mensajes en concreto les afectan y ello está ampliamente
documentado en el SDK de plataforma y
en MSDN.
Para terminar con el artículo vamos a
crear un control de texto mejorado que,
a las características habituales de este tipo
de controles, añade las siguientes:
• No permite pegar texto desde el portapapeles, impidiendo así que se modifiquen sus contenidos a menos que el
usuario los escriba directamente pulsando teclas.
• Cuando un usuario copia o corta texto desde uno de estos cuadros de tex-
Figura 5. Formulario de ejemplo que utiliza dos controles de texto extendidos desarrollados
en el artículo.
to mejorados, se le añade automáticamente información de copyright a los
contenidos que van a pasar al portapapeles.
• Dispone de una propiedad de sólo lectura llamada FirstVisibleLine que nos
permite averiguar cuál es la primera
línea de los contenidos que está visible en el control tras haber realizado
un desplazamiento (scroll) de éstos (ver
figura 5).
• Expone una propiedad LeftMargin que
nos permite indicar o averiguar el margen en píxeles que el cuadro de texto
deja a la izquierda de los contenidos,
en lugar de pegarlos totalmente que
es el comportamiento por defecto.
Las dos primeras características se
consiguen capturando los mensajes que
Windows envía a la hora de utilizar el
portapapeles. Las restantes implican que
sea nuestro código y no el sistema operativo el que envíe ciertos mensajes al
control para que cambie su forma de
actuar o nos proporcione información
como resultado de procesarlos.
Lo primero es crear una clase,
TextBoxEx, que derive de TextBox. En este
caso aunque no es un formulario también
tenemos la oportunidad de sobrescribir el
método WndProc ya que estos controles
son, como se comentó, un tipo más de
ventana. Cuando un usuario copia, corta
o pega texto en un TextBox, éste recibe los
mensajes WM_COPY, WM_CUT y WM_PASTE respectivamente. Sólo hay que capturarlos
tal y como se observa en el código de la
figura 6.
<<dotNetManía
Figura 4. Hemos añadido una opción
“Acerca de” a nuestro formulario ampliado.
Ahora podemos ofrecer información
directamente desde el menú del sistema
asociado a los formularios extendidos.
27
<< dnm.plataforma.net
Nótese que en este caso se llama
también el método WndProc de la clase base, pero se hace al final del procedimiento y no al principio. Se hace
así para tener la oportunidad de cambiar el mensaje antes de que lo procese el control. De este modo lo que
hacemos es anular el mensaje en los
tres casos sustituyendo su código por
un cero, que es lo mismo que no
enviar mensaje alguno, y haciendo el
trabajo nosotros mismos. Como queremos anular la posibilidad de pegar
texto, simplemente se anula el mensaje. Dado que al copiar y pegar queremos incluir un mensaje de copyright
en el portapapeles junto con el contenido original, anulamos el mensaje e
implementamos nosotros mismos
ambas acciones escribiendo directamente en el portapapeles.
Para implementar las propiedades
adicionales de nuestro control mejorado haremos uso de una función de
la API de Windows que nos permite
enviar mensajes mediante código a
cualquier formulario o control. La
definición de la función SendMessage
es la del fuente 3.
A esta función se le pasa como
parámetros un puntero al manejador
de la ventana objetivo del mensaje (un
entero de 32 bits que es una especie
de identificador global de ésta), la
constante que identifica al mensaje
que se envía y los valores de los parámetros adicionales que caracterizan al
mensaje enviado.
Todas las ventanas (y controles que
son ventanas) de Windows disponen
de un identificador llamado manejador de ventana (window handle) que en
.NET se puede obtener a través de su
propiedad Handle.
La función SendMessage, además de
enviar un mensaje, devuelve el resultado del procesamiento de éste por
parte de la ventana objetivo. Ello permite usarla también para obtener
información interesante de los controles.
Por ejemplo, cuando se envía un
mensaje EM_GETFIRSTVISIBLELINE a un
control TextBox, éste tras procesarlo,
devuelve como resultado el número de
línea que actualmente está de primero
en el área visible del control. Ello puede ser útil en controles multilínea cuyo
[DllImport("user32.dll", EntryPoint="SendMessage")]
private static extern int SendMessage( IntPtr hWnd, int wMsg,
int wParam, int lParam);
Fuente 3
public int FirstVisibleLine
{
get
{
return SendMessage(this.Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
}
}
<<dotNetManía
Fuente 4
28
public int LeftMargin
{
get
{
return SendMessage(this.Handle, EM_GETMARGINS, EC_LEFTMARGIN, 0);
}
set
{
SendMessage(this.Handle, EM_SETMARGINS, EC_LEFTMARGIN, value);
}
}
Fuente 5
contenido puede haberse desplazado ya
que no hay ninguna propiedad o método que nos informe de ello. El código
para obtener este dato es, por tanto, así
de sencillo (vea el fuente 4).
El mensaje EM_SETMARGINS sirve
para ajustar los márgenes de los controles de texto. En este caso se debe
especificar con el parámetro WParam
qué margen es el que se fija y con
LParam el número de píxeles que tendrá. Por otra parte existe un mensaje
muy similar, EM_GETMARGINS que funciona de manera parecida y sirve para
obtener el valor actual de los márgenes. Según esto, para crear la propiedad LeftMargin que deseábamos para
el control extendido, debemos escribir el código del fuente 5, que lo que
hace es enviar sendos mensajes para
obtener y ajustar el valor del margen
del control actual, cuyo manejador se
obtiene con la propiedad Handle.
Revise con detenimiento el código
complementario a este artículo para ver
cómo se utiliza el nuevo control en un
formulario común.
En resumen
Los mensajes de ventana forman parte intrínseca y fundamental de la arquitectura de Windows. Comprendiendo el
uso que el sistema hace de ellos es posible sacarle mucho partido para mejorar
las características de nuestras aplicaciones. En este artículo hemos estudiado
como aprovecharlos para ciertas tareas y
hemos visto la forma de extender formularios y controles estándar de
Windows Forms para añadirle nuevas
capacidades.
La documentación del SDK de plataforma es la referencia más importante sobre los mensajes de Windows y le
recomendamos que la estudie si quiere
ampliar conocimientos. La utilidad de
la técnica se ha visto mermada gracias a
la gran cantidad de características incluidas en .NET pero aún así, y como
hemos podido comprobar, todavía se le
puede sacar mucho partido. Aún quedan muchas posibilidades por explorar
en esta técnica. Esperamos que el artículo le haya abierto los ojos a nuevas
formas de hacer las cosas en el sistema
operativo Windows.
dnm.plataforma.net
Rodrigo Corral
Sistemas distribuidos en .NET
con Remoting (I)
Sin duda la gran mayoría de las aplicaciones que se desarrollan actualmente son aplicaciones distribuidas. El framework de .NET nos proporciona un poderoso marco
para el desarrollo de este tipo de aplicaciones.Veremos como .NET remoting permite desarrollar, desplegar y configurar con facilidad aplicaciones distribuidas sin los
quebraderos de cabeza y las limitaciones que presentaban anteriores soluciones.
miento y procesamiento de la información es realizado sobre varias computadoras que permanecen
en contacto entre ellas mediante elementos de
comunicación.
Ventajas de los sistemas distribuidos
Rodrigo Corral
colabora habitualmente con
dotNetManía. Es Microsoft MVP
y analista de Sisteplant, empresa
líder en el sector de las
aplicaciones de gestión industrial
• Compartición de recursos: Un sistema distribuido permite compartir hardware y software.
• Apertura: La apertura de un sistema es el grado al
cual se puede extender agregándole nuevos recursos no propietarios. Los sistemas distribuidos son
sistemas abiertos que incluyen software y hardware de diferentes fabricantes.
• Concurrencia: En un sistema distribuido varios procesos operan al mismo tiempo en diferentes computadoras de la red comunicándose entre ellos si
es necesario.
• Escalabilidad: En un sistema distribuido relativamente sencillo aumentar la capacidad del mismo
añadiendo nuevos elementos al sistema. A menudo esta escalabilidad se ve limitada por el nexo de
unión entre los diferentes equipos, habitualmente el factor limitador es la capacidad de la red.
• Tolerancia a fallos: Disponer de varios equipos trabajando en paralelo permite duplicar aquellos equipos que realizan tareas críticas, de manera que ante
la caída de un equipo no ocurra una pérdida del
servicio proporcionado por el sistema.
• Transparencia: La transparencia consiste en esconder al usuario la arquitectura del sistema. Para el
usuario es indiferente usar un sistema distribuido.
Desventajas de los sistemas distribuidos
• Complejidad: Es evidente que los sistemas distribuidos son más difíciles de diseñar, construir,
depurar y mantener.
• Seguridad: El sistema se puede acceder desde
diferentes lugares, lo que hace que el tráfico
de red pueda estar sujeto a inspecciones no
deseadas.
• Mantenibilidad: Las diversas computadoras de un
sistema pueden ser de diferentes tipos o ejecutar
diferentes sistemas operativos. Los fallos en una
máquina pueden propagarse con consecuencias
impredecibles a priori.
• Impredecibilidad: Como vemos a diario, como usuarios de Internet, los sistemas distribuidos son
impredecibles en su respuesta. Ésta depende de
la carga del sistema, de su estado y de la carga de
la red, lo que hace que el tiempo para atender
peticiones varíe ampliamente.
Tecnologías para el desarrollo de aplicaciones distribuidas
El desarrollo de aplicaciones distribuidas sería
una tarea prácticamente impracticable sin la existencia de diferentes tecnologías o frameworks que hacen
la tarea más llevadera proveyendo una serie de servicios básicos a toda aplicación distribuida.
A lo largo de los últimos tiempos se han desarrollado diferentes de estos frameworks; a menudo
unos son evolución lógica de otros añadiendo una
nueva capa de abstracción y simplicidad.
<<dotNetManía
<< Un sistema distribuido es áquel donde el almacena-
29
<< dnm.plataforma.net
DCE/RPC
Disctributed Computing Environment
(DCE) fue diseñando por la Open
Software Fundation, a principios de
los años 90, en un intento de proveer
una serie de herramientas y servicios
(llamadas a procedimientos remotos,
seguridad, etc...) que facilitasen el desarrollo de sistemas distribuidos.
Sin embargo aunque DCE/RPC ha
sido una tecnología ampliamente usada
y válida, nunca se ha caracterizado por
su facilidad de implementación. Otro
importante problema es que la implementación ha estado restringida a lenguajes diferentes de C/C++. Otra carencia de este entorno es la ausencia total
de orientación a objetos.
A pesar de estos problemas,
DCE/RPC es la base para algunos de
los frameworks más usados como son
COM+ y DCOM. Muchas aplicaciones
distribuidas de amplio uso, también tienen como base DCE/RPC, por ejemplo, MS SQL Server, Exchange Server,
SMB (Server Message Block) y NFS
(Network File System).
<<dotNetManía
CORBA (Common Object Requets
Broker Arquitectura)
30
CORBA es un estándar definido
por el consorcio OMG (Object
Management Group), formado por más
de 800 empresas.
CORBA es solamente una colección
de estándares; la implementación es realizada por todas aquellas terceras compañías que lo deseen. Esto unido a que
partes del estándar son opcionales y a
que a menudo las compañías que implementan el estándar añaden extensiones
propietarias incompatibles con otras
implementaciones, han hecho que el
objetivo de interoperabilidad con el que
nació CORBA no se haya alcanzado de
manera plena.
A pensar de estos problemas, dejando a parte SOAP, CORBA es el único
entorno multiplataforma y multilenguaje para aplicaciones distribuidas.
Existen ORBs (Object Request Brokers)
para la totalidad de sistemas operativos
y librerías para el desarrollo en la mayoría de los lenguajes. También existen
capas para integrar CORBA con otras
tecnologías como COM y EJB.
COM/DCOM (Distributed Component
Object Model)
A veces llamado oRPC (Object
RPC), DCOM es una extensión de
RPC orientada a objetos. COM nace
a raíz de la necesidad de compartir
objetos entre aplicaciones, ya sean
objetos visibles (componentes
ActiveX) o objetos sin parte visual
(librerías ActiveX).
DCOM es una extensión de COM
que permite desplegar los componentes de una aplicación de manera transparente sobre una red para formar un
sistema distribuido.
DCOM presenta problemas en lo
relativo a su uso sobre redes dispersas,
al usar un formato binario (DCE/RPC)
para transmitir la información y realizar la asignación de puertos para comunicaciones de manera dinámica, hace
difícil su uso si hay firewalls de por
medio.
La principal pega de este marco tecnológico es que está íntimamente ligado a sistemas Windows y la dificultad
de una correcta configuración, aunque
ésta no es mayor que la habitual en otros
sistemas distribuidos.
La total integración con los sistemas
Windows es sin duda el punto fuerte de
COM+.
Mencionar por último que .NET
delega en COM+ cuando necesita los
servicios anteriormente citados.
Java EJB
Entrerprise Java Beans (EJB) fue la
respuesta que SUN dio a COM+. EJB
es un estándar pero al contrario que
CORBA, que es sólo un estándar, SUN
proporciona una implementación de
referencia, lo que garantiza que un sistema que corra sobre esta implementación lo hará sobre cualquier otra que
esté de acuerdo al estándar.
Sin duda los servicios Web son el primer entorno que realmente logra una verdadera solución a la integración entre sistemas heterogéneos, gracias al uso de estándares ampliamente
extendidos y ya existentes en la mayoría de las plataformas
Existen implementaciones de
DCOM para Windows y Unix, sin
embargo, su uso está casi restringido a
sistemas Windows donde, con anterioridad a .NET, constituía un marco tecnológico casi omnipresente.
COM+
COM+ fue el primer intento serio
de Microsoft de proveer un servidor de
aplicaciones de nivel empresarial. En
esencia, COM+ es una serie de servicios
(eventos distribuidos, pool de objetos,
transacciones distribuidas, mensajería
entre aplicaciones, eventos bajo suscripción, administración de seguridad,
balanceo de carga, etc...) construidos
sobre DCOM y que extienden sus posibilidades.
EJB ha sido ampliamente aceptado
por la industria informática, de manera
que existen implementaciones del estándar realizadas por numerosas empresas
e incluso implementaciones Open Source
muy dignas (www.jboos.org).
El principal problema con EJB es
que a menudo las empresas implementan contenedores que aportan características más allá del estándar, y si las usamos, nuestro sistema estará ligado a un
contendor determinado. Otro problema es que el despliegue de la aplicación
y la configuración del contendor es un
proceso bastante complicado.
Web Services/SOAP/XML-RPC
Sin duda los servicios Web son el primer entorno que realmente logra una ver-
<< dnm.plataforma.net
¿Qué es .NET Remoting?
Si bien .NET Remoting se basa en tecnologías similares
a las comentadas para los servicios Web, no tiene la
interoperatibilidad como principal meta. Esto permite
que el acceso a objetos remotos se pueda realizar
mediante protocolos más eficientes...
.NET Remoting
Si bien .NET Remoting se basa en
tecnologías similares a las comentadas para
los servicios Web, no tiene la interoperatibilidad como principal meta. Esto permite que el acceso a objetos remotos se
pueda realizar mediante protocolos más
eficientes, lo que unido a la posibilidad de
usar objetos que mantienen su estado
entre llamadas, lo convierten en un candidato ideal para el desarrollo de aplicaciones distribuidas.
.NET Remoting ofrece un marco de
desarrollo de aplicaciones distribuidas muy
flexible y extensible que permite al desarrollador y al administrador elegir el meca-
nismo de transporte, el formato de codificación y la configuración de la seguridad.
El único punto flojo es la necesidad de declarar de manera precisa que
un objeto va a ser usado remotamente en el momento de su codificación;
esto no era necesario con los objetos
DCOM, cualquier objeto podía ser
remoto sin necesidad de hacer cambios en su código. Ésta en cualquier
caso es una pega menor.
.NET Remoting frente a DCOM
•
•
•
•
•
•
•
No es tan transparente como DCOM.
No necesita de los servicios de interoperabilidad (Interop).
Ofrece mayores opciones de despliegue.
No está ligado a un protocolo o formato de comunicación.
Tolera los firewalls.
Delega los servicios empresariales en COM+.
Permite especificar explícitamente que objetos son remotos.
.NET Remoting frente a Web Services
• No requiere Internet Information Server en la parte servidora.
• Gran flexibilidad a la hora de elegir donde “vive” el servidor.
• Provee total orientación a objetos (propiedades, métodos, constructores y
eventos).
• No está ligado a HTTP para el transporte.
• No está ligado a SOAP para la codificación de la comunicación.
• Posibilidad de usar objetos con estado.
• Permite un total control sobre la transmisión de la información y el tiempo
de vida de los objetos.
• Más flexible y más complejo que los Web Services.
• Menor capacidad para interoperar con otros sistemas.
• Más información:
• NET Remoting frente a los servicios Web ASP.NET www.microsoft.com/spanish/msdn/articulos/archivo/221102/voices/bdadotnetarch14.asp.
• ASP.NET Web Services or .NET Remoting: How to Choose:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdadotnetarch16.asp
<<dotNetManía
dadera solución a la integración entre sistemas heterogéneos, gracias al uso de
estándares ampliamente extendidos y ya
existentes en la mayoría de las plataformas. Los servicios Web usan HTTP
POST para realizar llamadas a componentes remotos, usando XML para codificar la información necesaria para realizar la llamada, pasar parámetros y recibir
resultados. SOAP es el protocolo más usado a la hora de codificar la información
necesaria para realizar la llamada.
SOAP (Simple Object Access Protrocol),
WSDL (Web Service Description Language)
y UDDI (Universal Dscription, Discovery
and Integration) constituyen una serie de
estándares basados en XML y HTTP que
forman un marco tecnológico que permite de una manera sencilla la comunicación entre sistemas heterogéneos gracias
a la amplia disponibilidad de HTTP y
XML, únicas tecnologías necesarias para
la implementación de estos estándares.
La principal carencia de los servicios
Web es la imposibilidad de mantener el
estado de los objetos entre llamadas y el
menor rendimiento.
.NET Remoting es la arquitectura nativa para la invocación de objetos remotos en la plataforma .NET.
Más adelante entraremos en detalle de
qué es lo que se considera un objeto
remoto en .NET; de momento basta
con mencionar que un objeto remoto
es el que se crea en un dominio de
aplicación distinto.
.NET Remoting permite la creación, invocación y comunicación entre
objetos a través de los límites de procesos y máquinas. Es totalmente independiente del protocolo de comunicación y el formato en el que se transmite la información.
.NET Remoting es EXTENSIBLE: permite controlar cómo y sobre
qué protocolo se transmite la información. Podemos definir nuestros
propios canales y “formateadores”.
31
<< dnm.plataforma.net
.NET Remoting es FLEXIBLE: se
puede cambiar el despliegue y la configuración de los objetos, sin tener que
realizar cambios en el código, a través
de archivos de configuración.
.NET Remoting surge por la necesidad de atravesar las fuertes fronteras
impuestas por los dominios de aplicación y de máquina. Sin .NET Remoting
es imposible invocar objetos fuera de
nuestro dominio de aplicación o fuera
de nuestra máquina.
<<dotNetManía
¿Qué son los dominios de aplicación?
32
Las aplicaciones .NET se ejecutan
en un proceso físico, no manejado, pero
como sabemos requieren un entorno
manejado para su ejecución. Un dominio de aplicación provee ese entorno
manejado dentro de un proceso no
manejado. Los dominios de aplicación
también permiten la portabilidad pues
son un concepto lógico, no algo físico.
Al contrario que los procesos, los dominios de aplicación no están ligados al
sistema operativo.
Los dominios de aplicación
(Application Domains) son fronteras de
procesamiento utilizadas para aislar aplicaciones. Los dominios de aplicación
proveen una unidad de procesamiento
segura y versátil que el CLR puede usar
para proveer aislamiento entre aplicaciones.
Los assemblies se cargan en un dominio de aplicación de manera que tengan
acceso a los recursos manejados como
son el Garbage Collector, la pila o los servicios de Interop.
Cada proceso puede contener múltiples dominios de aplicación, aunque
habitualmente sólo habrá uno por proceso. Se pueden crear mediante código nuevos dominios de aplicación por
motivos de aislamiento y seguridad.
Diferentes dominios de aplicación pueden tener diferentes privilegios de
seguridad.
Cruzar los límites de un dominio
de aplicación es menos costoso que
cruzar los límites de un proceso, pero
aún así hay un coste. Por ejemplo,
ASP.NET pone cada aplicación en un
dominio de aplicación diferente, sin
embargo, todas comparten proceso.
Figura 1. Esquema de la arquitecutra .NET Remoting
Los motivos para la elección de este
modelo son:
• Nos beneficiamos del aislamiento
sin tener el coste de un nuevo proceso.
• Crear y parar un dominio es más
ligero que crear y parar un proceso.
• Menor consumo de recursos, mantener un dominio es menos costosos que mantener un proceso.
• Las variables estáticas lo son por
dominio.
Arquitectura de .NET
Remoting
Dado que las aplicaciones deben
compartir objetos, es necesario un
mecanismo que permita cruzar los
límites impuestos por los dominios de
aplicación. Uno de estos mecanismos
es .NET Remoting. Cuando cruzamos los límites de un dominio de aplicación es necesario abrir un canal. Los
canales proporcionan un camino para
transportar datos cuando un cliente
llama a un objeto en otro dominio de
aplicación. .NET proporciona dos
canales por defecto HttpCannel y
TcpChannel que usan HTTP y TCP
respectivamente como protocolo de
comunicación.
Una vez que tenemos un canal abierto es necesario formatear los objetos que
queremos mover a través del canal. De
nuevo .NET proporciona dos
“formateadores” por defecto: SOAP y
Binary. SOAP es a menudo usado para
la comunicación entre sistemas heterogéneos mientras que el formato binario
es mucho más eficiente, pero está limitado a la comunicación entre sistemas
.NET.
Los principales elementos en la
arquitectura de .NET Remoting son:
• Mensajes (Messages): Qué comunicamos.
• Canales (Channels): Dónde establecemos la comunicación.
• Formateadores (Formatters): Cómo establecemos la comunicación.
Estos elementos se asocian en una
cadena (Sink Chain), y mediante la
combinación de diferentes mensajes,
canales y formateadores podemos
adaptar la comunicación a nuestras
necesidades.
Mensajes
Los mensajes son objetos que implementan la interfaz IMessage. Esta interfaz simplemente presenta un diccionario de pares de claves y valores.
Existen diferentes tipos de mensajes:
• Según su propósito:
• Mensajes de construcción de
objetos y su respuesta asociada.
• Mensajes de invocación de métodos y su respuesta asociada.
• Según el tipo de invocación
• Síncronos: Invocación de un método con espera a una respuesta
inmediata.
• Asíncronos: Invocación de un
método con una respuesta no
inmediata o sin respuesta.
<< dnm.plataforma.net
Canales
Figura 3. Channel Sink Chain: total control sobre el proceso
La cadena del canal (Channel Sink Chain)
Los diferentes elementos que
hemos visto hasta ahora se combinan
en forma de cadena para formar la
cadena del canal. Como muestra la
figura 3, la cadena del canal esta formada por los diferentes elementos
encargados de la codificación y trans-
Figura 2. Canal: la vía de comunicación
Los canales se pueden personalizar de forma que provean a los desarrolladores de control sobre el propio
mecanismo de transporte de mensajes
a y desde el objeto remoto.
Todos los mensajes se pasan a través de SecuritySink, TransportSink y
FormatterSink antes de que se puedan
transportar a la aplicación remota,
donde fluyen a través de los mismos
receptores en orden inverso.
El framework de .NET provee dos
canales por defecto: el canal TCP y el
canal HTTP.
misión se de los objetos.
También forman parte de esta cadena
los elementos proporcionados por el programador, de manera que se puede variar
el comportamiento del canal, modificando el tipo de elementos que forman la
cadena o incluso interponiendo nuestros
propios elementos (Sinks) en la cadena.
Canal HTTP
El canal HTTP transporta los
mensajes a y desde los objetos remotos utilizando el protocolo SOAP.
Todos los mensajes se pasan a través
del formateador de SOAP, donde el
mensaje se cambia a XML y se pone
en serie; también en esta fase se agregan a la secuencia los encabezados de
SOAP necesarios. Asimismo, se puede especificar el formateador binario,
que resulta en una secuencia de datos
binaria. A continuación, ésta se transporta al URI de destino utilizando
para ello el protocolo HTTP.
Características del canal HTTP:
• System.Runtime.Remoting.Channels.Http.
• Usa el protocolo HTTP 1.1.
• La transmisión se realiza en formato SOAP 1.1 (XML).
• La serialización se realiza en formato SOAP (SoapFormatter).
• Estándar abierto.
• La mejor elección para la comunicación a través de Internet.
• La mejor elección para interoperatibilidad e integración.
Canal TCP
El canal TCP utiliza el formateador
binario para poner en serie todos los
mensajes en una secuencia binaria,
transportando la secuencia al URI de
destino con el protocolo TCP.
Características del canal TCP:
• System.Runtime.Remoting.Channels.Tcp
• Utiliza sockets planos TCP para la
comunicación.
<<dotNetManía
Los canales se utilizan para transportar mensajes a y desde objetos
remotos. Cuando un cliente llama a
un método en un objeto remoto, los
parámetros, así como otros detalles
relacionados con la llamada, se transportan a través del canal al objeto
remoto. Cualquier resultado de la llamada se devuelve al cliente de la misma forma. Un cliente puede seleccionar cualquiera de los canales registrados en el servidor para comunicarse
con el objeto remoto, permitiendo a
los desarrolladores, por tanto, cierta
libertad en cuanto a la selección del
canal que mejor se ajuste a sus necesidades. También se puede personalizar un canal existente, o bien, construir nuevos canales que empleen protocolos de comunicación distintos.
Todos los canales se derivan de
IChannel e implementan IChannelReceiver
o IChannelSender, dependiendo del propósito del propio canal. La mayoría implementan tanto la interfaz del destinatario
como la del remitente, a fin de permitir
que éstos se comuniquen en cualquier
dirección.
33
<< dnm.plataforma.net
• Utiliza el formato binario para la comunicación.
• Por defecto utiliza el formateador BinaryFormatter.
• Es el formato nativo de .NET.
• Es muy rapido y poco pesado.
• Puede utilizar formateadores personalizados.
• Es la mejor elección para comunicaciones en entornos LAN.
• Utiliza conexiones permanentes.
• No recomendado para conexiones a través de
Internet.
Canales personalizados
Los canales personalizados nos permiten usar
nuestros propios protocolos (APPC, IPX, Pipes...)
para la comunicación.También nos permiten seleccionar nuestro propio formato para la transmisión
de la información, podemos usar los formateadores por defecto (SOAP o binario) o nuestro propio formato (IIOP, RMI, ORPC...). Tiene utilidad
sobre todo para la integración de tecnologías.
Figura 4. Proxy: transparencia en la ubicación del objeto
Remoting hosts
Un remoting host, es necesario en la parte servidora para proveer un entorno manejado para el objeto remoto.
El host es el responsable de registrar los tipos
remotos servidos por él, así como los canales que usará para servirlos.
Podemos usar dos tipos de remoting hosts IIS o host
de usuario (generalmente implementados como ejecutables).
IIS como Remoting Host
Formateadores
Los formateadores son los encargados de serializar los objetos en el formato adecuado para su transmisión a través del canal.
Los formateadores son utilizados por el canal de
forma implícita, y se implementan como uno de los elementos de la cadena que forma el canal.
El framework de .NET proporciona dos formateadores por defecto uno para formato SOAP,
generalmente asociado al canal SOAP y otro para
formato binario generalmente asociado al canal
TCP.
• Usar IIS evita tener que escribir el código del
host.
• Provee autenticación y encriptación (SSL).
• Sólo puede servir objetos a través de canales
HTTP.
• Soporta el formateador SOAP y el binario.
• Objetos sin estado pueden ser distribuidos en una
granja de servidores.
• No requiere la instalación del proceso host en el
lado servidor.
Remoting Hosts personalizados
• Prácticamente cualquier ejecutable .NET puede
servir como remoting host.
<<dotNetManía
Proxys
34
Cuando un cliente llama a un método en un
proxy, el marco de servicios remotos intercepta la
llamada y ésta se cambia a mensaje que, a su vez,
se reenvía a la clase RealProxy (o más bien a una
instancia de la clase que implementa RealProxy).
La clase RealProxy reenvía dicho mensaje a un
receptor de mensajes para su procesamiento. El
receptor de mensajes se encarga de establecer la
conexión con el canal registrado por el objeto
remoto y de transportar los mensajes a través del
canal (a otro dominio de aplicación), desde donde
se distribuye al propio objeto remoto.
El proxy está formado por dos elementos: El
transparent proxy, proporcionado por el framework
y que no podemos modificar y el real proxy, que
podemos adecuar a nuestras necesidades, modificando su comportamiento.
using System;
namespace HelloRemoting
{
public class HelloRemotingObject : MarshalByRefObject
{
public HelloRemotingObject()
{
}
public string GetHello()
{
return “Hello from “ + Environment.MachineName;
}
}
}
Fuente 1. HelloRemnoting.cs
<< dnm.plataforma.net
System;
System.Runtime.Remoting;
System.Runtime.Remoting.Channels;
System.Runtime.Remoting.Channels.Tcp;
HelloRemoting;
• Permite total flexibilidad en cuanto a los canales usados.
• Permite total flexibilidad en cuanto a las opciones de despliegue.
• Puede usar canales tanto TCP
como HTTP.
• Puede usar configuración basada en archivos o mediante programa.
• No provee ningún servicio de
autenticación o encriptación.
• El remoting host debe estar
corriendo antes de poder llamar
a los objetos que expone.
namespace HelloRemotingClient
{
class ClientStarup
{
[STAThread]
static void Main(string[] args)
{
//Creamos un nuevo canal
TcpChannel chnl = new TcpChannel();
//Registramos el canal
ChannelServices.RegisterChannel(chnl);
//Obtenemos el objeto remoto
HelloRemotingObject hro =
(HelloRemotingObject)Activator.GetObject(
typeof(HelloRemotingObject),
“tcp://tiron:1234/HelloRemotingObject.TCP”);
//Llamamos a un metodo del objeto remoto y mostramos el resultado
Console.WriteLine(hro.GetHello());
El primer servidor de objetos
remotos
Pasos para escribir un servidor de
objetos remotos
1)
Console.ReadLine();
}
}
}
Fuente 2. HelloRemnotingClient.cs
using
using
using
using
using
System;
System.Runtime.Remoting;
System.Runtime.Remoting.Channels;
System.Runtime.Remoting.Channels.Tcp;
HelloRemoting;
2)
3)
namespace HelloRemotingHost
{
class ServerStartup
{
[STAThread]
static void Main(string[] args)
{
//Creamos un nuevo canal
TcpChannel chnl = new TcpChannel(1234);
//Registramos el canal
ChannelServices.RegisterChannel(chnl);
//Configuramos remoting para exponer el objeto
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(HelloRemoting.HelloRemotingObject),
“HelloRemotingObject.TCP”,
WellKnownObjectMode.SingleCall);
Console.WriteLine(“Presione una tecla para detener el servidor...”);
Console.ReadLine();
}
}
}
Fuente 3. HelloRemnotingHost.cs
Creamos una DLL con los tipos
de objetos remotos que queremos
exponer, podemos ver el código en
HelloRemoting.cs , en nuestro
ejemplo simplemente devolvemos
la cadena ”Hello” seguida del nombre de la máquina.
Elegimos el tipo de host que
vamos a utilizar: Custom host o
IIS; en el ejemplo simplemente
utilizaremos una aplicación de
consola como host.
Escribimos el código necesario
para crear nuestro host, que
podemos ver en HelloRemotingHost.cs
4)
a. Cargamos los tipos.
b. Decidimos qué tipos vamos a
exponer.
c. Configuramos remoting para
exponer esos tipos.
Escribimos un programa cliente,
que podemos ver en HelloRemotingClient.cs.
Ejemplo: HelloRemoting (ver material de apoyo de este artículo en
www.dotnetmania.com)
En la próxima entrega veremos los
diferentes comportamientos que pueden presentar los objetos en .Net
Remoting, cómo el Framework controla
el tiempo de vida de los objetos y como
podemos variar la lógica que controla
el tiempo de vida de los objetos.
<<dotNetManía
using
using
using
using
using
35
dnm.servidores.sql
Salvador Ramos
SQL Server Analysis Services
¡Hola Cubo! (III)
Con este artículo concluiremos la creación de nuestra primera base de datos
multidimensional, en la que tendremos un cubo compuesto por dos medidas
y cinco dimensiones, que ya quedará listo para su explotación con las herramientas cliente.
<< Es el momento de continuar con las tareas que dejamos pendientes en el anterior artículo. Ahora vamos a crear la
dimensión Artículo, esta es una dimensión con “Esquema
de copo de nieve” (snowflake schema). Este tipo de dimensiones se utiliza cuando queremos crear una estructura
jerárquica a partir de diversos campos de una tabla, algunos de ellos son clave externa de otra tabla y suelen agrupar varias filas de elementos.
Procedamos a la creación de la dimensión artículo. Para ello volvemos a crear una nueva dimensión con el asistente, y en este caso indicaremos que
queremos crear la dimensión como “Esquema de
copo de nieve”, que es el que nos permite crear una
dimensión con una jerarquía de niveles basados en
múltiples tablas de dimensiones relacionadas.
<<dotNetManía
Salvador Ramos
colabora habitualmente con
dotNetManía. Es Microsoft SQL
Server MVP y responsable del
sitio HelpDNA.com, formador y
consultor de Inforges, en las
áreas de Bases de datos (SQL
Server, Oracle, DB2/400) y de
tecnologías .NET
36
El siguiente paso es seleccionar las tablas de
dimensiones que vamos a utilizar. En este caso
vamos a crear una dimensión artículo que tiene
dos niveles (Familia y Artículo). La información
para generar estos dos niveles se encuentra en las
tablas dwArtic y dwFamilias de nuestro origen de
datos, que son las que seleccionaremos como se
puede apreciar en la imagen.
Ahora es el momento de indicar la columna o
columnas que nos servirán de enlace entre ambas
tablas, siguiendo las instrucciones que aparecen en
la pantalla. Hay que tener en cuenta que el asistente
intenta realizar las combinaciones que él considera correctas, pero casi siempre tenemos que retocar manualmente estas combinaciones.
En la siguiente pantalla hay que seleccionar las
columnas que formarán los distintos niveles de
nuestra dimensión, en este caso el primer nivel será
la familia del artículo, y dentro de cada familia ten-
<< dnm.servidores.sql
dremos un segundo nivel formado por todos los
artículos de dicha familia.
Nivel Familia
Name
Familia
Member
Name
Column
RTRIM("dbo"."dwFamilias"."nombre")+' [' +
RTRIM(CAST("dbo"."dwFamilias"."codigo"
AS CHAR(3))) + ']'
Order By
Key
(Hay que tener en cuenta que la propiedad Order
By se encuentra en la pestaña “Avanzadas”, mientras
que el resto se encuentran en la pestaña “Básicas”).
Nivel Artículo
Name
Artículo
Member
Name
Column
RTRIM("dbo"."dwArtic"."nombre") + ' [' +
RTRIM(CAST("dbo"."dwArtic"."codigo"
AS CHAR(15))) + ']'
Order By
Key
En la siguiente pantalla, donde debemos especificar
las columnas clave del miembro pulsaremos el botón
“Siguiente”. Hay que resaltar que al finalizar el asistente nos aparecerá el editor de dimensiones donde podremos realizar cualquier modificación que no hayamos
tenido en cuenta durante su creación con el asistente.
En la pantalla de opciones avanzadas tampoco haremos ningún cambio, y pulsaremos el botón “Siguiente”.
Dejaremos para otra ocasión el manejo de las opciones
avanzadas del asistente.
Finalmente nos pide el nombre de la dimensión,
allí escribiremos Artículo, y pulsaremos el botón
“Finalizar”.
Al igual que en los casos anteriores, vamos a realizar
ciertas personalizaciones en las propiedades para que la
dimensión y cada uno de sus niveles presenten la información de la forma más clara posible. Esto por supuesto depende de los gustos y preferencias de cada uno, pero
yo seguiré utilizando las características que expuse anteriormente :-).
Modificaremos las propiedades con los valores que
se indican:
1
Ahora continuaremos montando una dimensión que
prácticamente es necesaria en cualquier cubo que vayamos a realizar, el Tiempo. Casi siempre necesitaremos
contrastar los datos cronológicamente. Para estos casos
el asistente para la creación de dimensiones del Analysis
Manager dispone de una serie de opciones que nos permiten crearla de una forma muy sencilla.
Ejecutaremos de nuevo el asistente para dimensiones, y en este caso seleccionaremos la que también será nuestra tabla de hechos 1, la tabla
Una Tabla de Hechos es la tabla central de un esquema, y es necesario que haya una, y sólo una, por cada cubo que tengamos en nuestra base de datos
multidimensional.Esta tabla contiene medidas numéricas y claves que relacionan los hechos con las tablas de dimensiones.Aquí están los datos de sucesos
específicos de nuestro negocio, como ventas, compras, pagos. Se suelen generar, en muchas ocasiones, a partir de lo que conocemos como tablas de
movimientos, mientras que las tablas de dimensiones se suelen generar a partir de lo que solemos llamar tablas maestras o tablas auxiliares.
<<dotNetManía
Bueno, pues aquí tenéis ya creada una dimensión
jerárquica formada por dos niveles.
37
<< dnm.servidores.sql
dwVentasCabDet, que como comentamos anteriormente es una tabla denormalizada en el DataWarehouse, que contiene información de las tablas normalizadas VentasCab y VentasDet (cabecera y detalle de ventas).
Ahora elegiremos como tipo de
dimensión “Dimensión de tiempo”, y
seleccionaremos la columna de fechas, que
siempre será un campo DateTime o
SmallDateTime; en concreto crearemos la
dimensión por el campo de fecha de venta (FechaMov).
<<dotNetManía
En el siguiente paso debemos elegir
la estructura jerárquica que queremos
que tenga esta dimensión -como veis
nos lo está poniendo bastante fácil el
asistente-. En este caso queremos que
la estructura de la dimensión sea “Año,
trimestre, mes, día”, en la pantalla se
pueden ver las diversas variantes que
tenemos disponibles para la estructura
de esta dimensión.
38
En la siguiente pantalla ya se ven con
detalle los diferentes niveles que acabamos de crear para nuestra dimensión
Tiempo, aquí simplemente pulsaremos el
botón “Siguiente”.
Y como en casos anteriores, y debido
al nivel de iniciación de este artículo, no
haremos ninguna modificación en las
opciones avanzadas, y pulsaremos el botón
“Siguiente”.
Para concluir indicaremos el nombre
de la dimensión, Tiempo en este caso, y pulsaremos el botón “Finalizar”.
Y aquí tenéis el resultado de esta
dimensión y su estructura jerárquica. Os
puede ser útil echar un vistazo a los valores Member Key Column y Member Name
Column de cada uno de los niveles de esta
dimensión.
éstas deben ser siempre datos numéricos. Seleccionaremos las columnas
Cantidad, Precio y Pr Compra.
Una vez seleccionadas las medidas,
elegiremos las dimensiones que formarán nuestro cubo. En este caso, y
puesto que sólo vamos a crear un cubo
y hemos creado expresamente las
dimensiones que necesitamos para este
ejemplo, las seleccionaremos todas.
Aunque lo habitual es que en una base
de datos multidimensional tengamos
muchas más dimensiones compartidas
que serán utilizadas en otros cubos. Por
ejemplo, es habitual tener una dimensión Proveedor que será utilizada en un
cubo de Compras, etc.
Con esto concluimos la creación de
dimensiones compartidas. Ahora vamos a
proceder a la creación de un cubo que utilice estas dimensiones. Para ello pulsaremos el botón secundario del ratón sobre
la carpeta Cubos, y elegiremos la opción
“Nuevo Cubo/Asistente…”, como se
muestra en la imagen.
Nos aparecerá la primera pantalla del
Asistente para cubos que es meramente
informativa, y pulsaremos el botón
“Siguiente”.
Ahora debemos elegir la tabla de
hechos de nuestro cubo, que será
dwVentasCabDet, y pulsaremos el botón
“Siguiente”.
Ahora es el momento de seleccionar
la Medidas que tendrá nuestro cubo;
Ahora va a proceder el asistente a
hacer el recuento de filas de la tabla de
hechos, y nos avisa que este proceso puede tardar en completarse, dependiendo
del número de filas de la tabla. Pulsaremos
“Sí” y esperaremos a que finalice el
recuento.
Una vez finalizado este proceso, lo más
habitual es que el asistente no sea capaz
de combinar automáticamente las columnas de la tabla de hechos con las correspondientes en las tablas de dimensiones, y
nos dará un aviso indicándonos las que no
ha podido combinar. Pulsaremos el botón
“Aceptar”. Finalmente nos mostrará la
<< dnm.servidores.sql
En este momento aparecerá el editor de cubos, donde podremos ver en la parte de la izquierda las dimensiones y medidas que forman nuestro cubo, y debajo de
éstas otra serie de objetos (Miembros calculados, Celdas
calculadas, etc.) que se salen del ámbito de este artículo,
pero que sí que quiero indicar que nos abren un amplio
abanico de posibilidades de cálculo y de obtención de
información para los cubos.
En la parte de la derecha podemos ver un diagrama
de la estructura del cubo, mostrándose en color amarillo siempre la tabla de hechos y en color azul las tablas de
dimensiones. Ahora procederemos a completar las combinaciones de columnas para establecer las relaciones
correctamente y a recolocar las tablas para que nos quede más claro el diseño.
Así es como queda, como se ve es muy similar a
la estructura de nuestro DataWarehouse, pero esto
es porque hemos construido un DataWarehouse
muy pequeño y estamos utilizando todas sus tablas
en nuestro único cubo. Lo habitual es que contenga una gran cantidad de tablas.
Es conveniente realizar unas tareas bastante
sencillas, éstas son la validación de la estructura del
cubo y la optimización del esquema. Las podemos realizar con dos de las opciones disponibles en el menú
“Herramientas” del Editor de Cubos del Analysis
Manager.
Una vez que hemos realizado todos estos pasos,
ya hemos terminado la creación de nuestro cubo, y
es muy importante que procedamos a guardarlo.
Ahora para que realmente podamos acceder a la
información, en primer lugar debemos procesar el
cubo, consiguiendo así alimentarlo con datos procedentes del DataWarehouse. Este proceso será el
que cuando lo ejecutemos la primera vez nos pida
que diseñemos la estructura de almacenamiento, donde indicaremos el número de agregaciones que queremos que el cubo tenga ya calculadas y listas para
mostrarnos. Cuanto mayor sea este número, más
rápidas serán las consultas, ya que accederá directamente a los datos sumados y almacenados, pero en
contraposición, será mayor su tamaño y su tiempo
de proceso. Como en este caso es la primera vez que
procesamos el cubo, debemos indicar las opciones
de almacenamiento. Este proceso, al igual que el resto se hace bastante sencillo al abrirse un asistente
que nos va guiando paso a paso. Como aquí no vamos
a entrar en detalles de optimización del rendimiento, no haremos ningún cambio dejando todos los
valores que aparecen por defecto y pulsando el botón
“Siguiente”.
Como habréis comprobado, hemos utilizado el
tipo de almacenamiento MOLAP explicado en el
primer artículo de esta serie.
Conclusión
Objetivo conseguido, ya tenemos un
cubo cargado de información y listo para
ser accedido desde diversas herramientas cliente para mostrar los datos al usuario. Aunque este tema lo dejaremos para
el siguiente artículo …
Y finalmente, para no dejaros sin ver
los resultados, os diré que si pulsáis el
botón secundario del ratón sobre el cubo, y elegís la opción “Examinar datos” podréis echar un
primer vistazo a los datos del cubo. En el próximo artículo explicaremos con más detalle cómo
utilizar el “Examinador de cubos” y cómo acceder con otras herramientas cliente, como MS Excel
y MS Data Analyzer.
<<dotNetManía
estructura del nuevo cubo, con sus dimensiones y medidas, y nos pedirá el nombre que le queremos asignar,
en este caso le llamaremos Ventas, y pulsaremos el botón
“Finalizar”.
39
dnm.plataforma.net
José Miguel Torres
Interoperabilidad no administrada
y migración (I)
<< Durante los últimos años COM ha sido el modelo de programación de referencia que utilizábamos los desarrolladores cuando teníamos en nuestras manos herramientas Microsoft. Ahora, este modelo de componentes ha cambiado; como suele ocurrir en informática, se está quedando obsoleto.
Prácticamente todos los componentes que tocábamos
en Visual Basic 6.0, entre otros lenguajes, estaban basados en COM, como ADO, SQL DMO, CRXDRT, etcétera. Pues bien, ahora todo ello ha quedado atrás y a la
hora de empezar a desarrollar una aplicación ya empezamos a contar con .NET. Pero, ¿qué hacemos con componentes propios que funcionan perfectamente? Pues bien
ésta y otras preguntas las trataremos en estas páginas.
Código administrado y no administrado
<<dotNetManía
José Miguel Torres
colabora habitualmente con
dotNetManía. Es técnico
superior en desarrollo de
aplicaciones informáticas y
trabaja como arquitecto de
software en el departamento de
tecnologías de la
información de MRW
40
Con el tiempo las aplicaciones en .NET sustituirán
a las aplicaciones basadas en COM, pero hasta que esto
suceda habrá una serie de componentes que funcionan
a la perfección que podremos utilizar, o incluso crear,
desde nuestras aplicaciones .NET. He aquí un ejemplo
de interoperabilidad. Pero profundicemos algo más.
El código de una aplicación en .NET que compila el CLR, se llama Código Administrado. Éste utiliza
datos que son gestionados en cuanto a solicitud y asignación de memoria o la comprobación de tipos por
el CLR (Common Language Runtime) con lo cual los
datos también pasan a ser datos administrados. Así
cualquier acceso que debamos hacer a cualquier código, sea COM o no, que esté fuera de este marco de
desarrollo será código no administrado, como los
ActiveX o las llamadas a API Win32.
Los tipos de datos, la definición en sí de componente
y sus métodos y el control de errores son totalmente dis-
tintos entre código administrado y no administrado.
CLR permite ocultar estas diferencias para poder facilitar la migración y/o interoperabilidad entre ambos.
De esta forma podremos consumir componentes
bajo las rigurosas normas COM desde .NET, pero
también podremos consumir componentes .NET desde COM, así como utilizar librerías de vínculo dinámico (DLL) externas, no basadas en COM, como por
ejemplo las APIs de Windows, desde .NET.
En la interoperabilidad de código administrado a
código no administrado existe una serie de reglas que
establecen la conversión de manera segura y lo más
eficaz posible. Estas reglas utilizan un cálculo de referencias y su ámbito se centra en la administración de
memoria, y en las conversiones de tipos en todos sus
contextos, desde el paso de parámetros hasta la manipulación de matrices.
Para poder entender mejor en qué consiste detallaremos un comportamiento predeterminado en interoperabilidad COM. Tanto en código administrado como
en no administrado existen tipos de datos de 1, 2 y 4
bytes, por ejemplo. Sí, es verdad que se llaman distinto,
por ejemplo un long de Visual Basic 6.0 equivale a un
Int en el CLR (System.Int32), en realidad no se debe
hacer un cálculo muy complejo puesto que un dato de
4 bytes no supondrá un control exhaustivo por parte del
contador de referencias, sino que tendrán una representación común en memoria. A estos tipos se le llaman
tipos que se pueden representar como bits o bytes.
Sin embargo existen tipos de datos que sus representaciones no pueden basarse en bits o bytes. La representación de dichos tipos en código no administrado es,
por tanto, distinta que en código administrado y viceversa, y será la aplicación de una serie de reglas para el
cálculo de sus referencias las que harán posible su inte-
<< dotNetManía
Conocer las ventajas y posibilidades tanto de COM Interop como de la interoperabilidad con código no adminsitrado en general, nos permite no sólo extender el alcance de nuestras apliciones sino replantearnos los escenarios de migración,ayudados con
estas técnicas que ofrece .NET, permitiendo una mayor productividad, menores costes de mantenimiento y como resultado una estrategia de migración mas eficiente.
40
<< dnm.plataforma.net
Tipos de Datos que se representan
en bits o bytes
Tipo que no puede representarse como
bits o bytes
System.Byte
System.Array
System.SByte
System.Boolean
System.Int16
System.Char
System.UInt16
System.Class
System.Int32
System.Object
System.UInt32
System.String
System.Int64
System.Valuetype
System.IntPtr
System.UIntPtr
Matrices unidimensionales de estos tipos
Tabla 1. Relación de tipos que pueden o no representarse como bits o bytes.
El proceso interno y funcional de
CCW no es idéntico que RCW.
Cuando un componente .NET es llamado por un COM, el runtime lee la
información de tipo para el componente del metadato del ensamblado y genera un CCW compatible que ejerce de
proxy entre ambos contextos.
De la misma forma que RCW y
CCW se responsabiliza de crear y administrar el objeto administrado crea las
interfaces más importantes como
IUnknown e IDispatch en él, basadas en
tipo de información del componente
.NET e interpreta las excepciones
.NET en valores COM HRESULT para el
manejo de errores.
roperabilidad. Ambos los podemos encontrar en la tabla 1.
El cálculo de referencias facilita,
como hemos visto, la conversión de
tipos entre contextos, aunque a veces,
deberemos echarle una mano, por ejemplo, con conversiones explícitas en llamadas a funciones externas.
Con la entrada de .NET Framework
son muchos ya los que han empezado a
migrar sus aplicaciones a .NET. En
muchos casos, existen componentes COM
que funcionan perfectamente y que las
empresas optan por exponerlos bajo código administrado, descartando la necesidad de reprogramarlos de nuevo. También
los hay que desarrollan componentes
.NET para que puedan ser accesibles desde componentes COM. Estos son un
ejemplo bidireccional entre la interoperabilidad COM y .NET.
CLR es el encargado de gestionar la
interoperabilidad entre ambos pero,
realmente, ¿cómo lo hace? Pues se ayuda de contenedores. Veamos que son.
Para conocer más a fondo la interoperabilidad debemos conocer la existencia y funcionamiento del Runtime Callable
Wrapper RCW. RCW es un contenedor
que actúa como proxy para las llamadas a
código no administrado. Cuando un componente realiza una llamada, ésta utiliza
o se ayuda de RCW para que a través de
sus interfaces públicas llegue la llamada al
Figura 1.Tanto RCW como CCW facilitan la tarea de Interoperabilidad entre COM y .NET
objeto COM bajo código no administrado. RCW no deja de ser un objeto administrado por CLR aunque su funcionamiento es algo distinto ya que su principal función es el cálculo de referencias de
llamadas entre .NET y COM.
Asimismo RCW es la responsable
de la creación del objeto COM que
recibirá la llamada, de administrar la
vida de uso del mismo y su posterior
deshecho administrando a su vez una
caché de punteros de interfaz.
También compatibiliza los tipos de
datos entre ambos contextos mediante la aplicación de las reglas de cálculo de referencias en argumentos entre
métodos y valores de retorno, así
como interpretará los valores retornados por COM HRESULT en excepciones administradas.
Si RCW permitía la comunicación
desde .NET a COM, COM Callable
Wrapper CCW, es el que se encarga del
proceso contrario, es decir, es el contenedor COM que permite la llamada de
un objeto COM a uno .NET.
Para ver más claramente la funcionalidad de ambos contenedores expondremos dos ejemplos de interoperabilidad, de COM a .NET y viceversa en
unos ejemplos sencillos.
Implementar COM desde
.NET
El primer paso es importar toda la
información del componente COM
para que se pueda exponer bajo .NET
y el lugar dónde está dicha información
es en la biblioteca de tipos.
Para ello lo primero que hay que
hacer es importar la biblioteca de tipos
como un ensamblado. En la biblioteca
de tipos se guarda la información del
componente COM; por otro lado los
metadatos son los encargados de esa
misma función para .NET. Ambos son
muy distintos con lo que necesitamos
que la biblioteca de tipos genere dicha
información para poder residir bajo un
ensamblado. Los archivos de biblioteca
de tipos residen como archivos inde-
<<dotNetManía
Interoperabilidad COM vs.
.NET
41
<<dotNetManía
<< dnm.plataforma.net
42
pendientes bajo extensión .TLB o bien
dentro del mismo componente COM
DLL o COM EXE. Aunque a priori
parece complejo, tenemos cuatro posibles vías de importación y de un manejo realmente sencillo.
Por una parte tenemos el propio
Visual Studio. NET. Quizás sea la
opción más sencilla y directa aunque
también la menos flexible. Visual Studio
.NET convierte directamente la biblioteca de tipos en metadatos de un ensamblado. El proceso es muy similar al de
referenciar a un ensamblado. Cuando
agregamos una referencia a nuestro proyecto tenemos, por una parte los componentes .NET firmados y registrados
en nuestro sistema y en otra ficha los
componentes COM, tales como
ADODB, etcétera. En caso de tener
nuestro propio componente buscaremos el archivo de biblioteca de tipo con
extensión .DLL, .TLB, .EXE o dónde
proceda, el cual deberemos tener registrado en el sistema, y lo seleccionaremos.
Otra posibilidad es importar la
biblioteca de tipos y generar un ensamblado con su propio espacio de nombres
de una forma más flexible mediante una
herramienta que funciona bajo el intérprete de comando y que se llama
TLBIMP.EXE. Su funcionamiento puede
ser tan sencillo como ejecutar el programa seguido del archivo .DLL o .
TLB, incluyendo a continuación una
serie de parámetros opcionales que permitirán una serie de operaciones como
la de crear, por ejemplo, un espacio de
nombre propio con nombre seguro para
evitar el problema de la duplicación de
nombres mediante la utilización de
fichero de claves keyfile.
Otra alternativa, quizás las más flexible, es utilizando la clase TypeLibConverter. TypeLibConverter es una clase
sellada (no heredable) del espacio de
nombre System.Runtime.InteropServices que permite convertir objetos
COM a .NET y viceversa. Es lógico
pensar pues, que la utilización de esta
clase pueda resultar mucho más flexible, como la posibilidad de convertir en
metadatos una biblioteca de tipos almacenada en memoria, y además algo más
compleja que las posibilidades vistas
anteriormente.
Nos podemos encontrar con el caso
de que un componente no tenga una
biblioteca de tipos determinada o ésta
contenga información errónea. Esta
situación se resuelve mediante los contenedores COM personalizados. Éstos
crean una definición del componente
en código administrado y posteriormente es compilado con un compilador CLR para generar los metadatos
en un ensamblado. Desgraciadamente
es necesario una serie de elementos
entre los que se encuentran las descripciones de las interfaces del componente y conocimiento de las reglas
de conversión de biblioteca de tipos en
ensamblados.
De todas estas posibilidades vistas
obtenemos un ensamblado. El ensamblado resultante se conoce como ensamblado de interoperabilidad primaria.
Dicho ensamblado puede ser modificado mediante el desensamblador y/o creado manualmente mediante compilador, añadiendo ciertos atributos.
Vamos a ver un ejemplo que va a ser
realizado con Visual Basic 6.0, aunque
también podríamos utilizar Visual C++
6.0 para la realización del componente
COM. La definición del componente
en Visual Basic 6.0 la podemos ver en la
figura 2.
fichero DLL llamado clsUsuario.dll.
Para facilitar y no extendernos demasiado, dicha clase no contiene dependencias a ningún otro objeto COM.
Además, Visual Basic 6.0 crea la biblioteca de tipos dentro del mismo archivo
DLL por defecto.
Veremos cómo utilizar dicha clase
mediante dos de las tres posibles opciones de interoperabilidad dentro de nuestro proyecto .NET.
Visual Studio .NET
Bien, ahora se trata de que desde
.NET podamos utilizar todas las propiedades, métodos y eventos; así que lo
primero es la importación de la biblioteca de tipos. En este primer supuesto
partimos de la base que tenemos el
fichero clsUsuario.dll y tenemos la
biblioteca de tipos en dicha clase.
Mediante Visual Studio .NET en nuestro proyecto agregamos una nueva
referencia (figura 3). En la ficha COM
localizamos el fichero clsUsuario.dll
y los seleccionamos y fijémonos en el
comportamiento de Visual Studio
.NET.
La referencia que se ha añadido es
UsuarioCOM. Este nombre proviene del
nombre del proyecto que ha genera-
Figura 2. Clase COM en Visual Basic 6.0 que utilizaremos para el ejemplo.
Se trata de un módulo de clase que
gestiona, de una manera simple, un
determinado usuario en un contexto
funcional de manipulación de expedientes. Esta clase ha sido compilada y
como resultado hemos obtenido un
do la clase clsUsuario.dll. Como ha
encontrado la biblioteca de tipos a
partir de la DLL, la referencia
UsuarioCOM es del tipo ActiveX, y no
Assembly como por ejemplo
System.Data.
<< dnm.plataforma.net
Figura 3. Formulario Agregar referencia de Visual Studio .NET
private void Form1_Load(object sender, System.EventArgs e)
{
UsuarioCOM.clsUsuarioClass usu = new UsuarioCOM.clsUsuarioClass();
//asignamos eventos
usu.ExpedienteCaducado += new UsuarioCOM.__clsUsuario_
ExpedienteCaducadoEventHandler(usu_ExpedienteCaducado);
//asignamos una propiedad de prueba
usu.Apellidos = "Torres";
//obtenemos de una propiedad
MessageBox.Show(usu.Apellidos);
}
// evento ExpedienteCaducado.
private void usu_ExpedienteCaducado( ref object expediente,
ref DateTime fechaCaducado)
{
}
Fuente 1. Ejemplo de utilización del ensamblado de interoperabilidad primaria.
Figura 4.Vista del Ensamblado de Interoperabilidad primaria des del Examinador de objetos
<<dotNetManía
Si examinamos el espacio de nombres UsuarioCOM vemos que éste se
encuentra dentro de interop.usuariocom. Además dentro de dicho espacio de
nombres encontramos una serie de elementos. Éstos elementos han sido creados para que el componente se integre en el CLR de manera satisfactoria.
Encontramos 4 interfaces que implementan los respectivos métodos y propiedades, por un lado, y los eventos, por
otro, que ha encontrado en clsUsuario.
Además, ha creado dos delegados
correspondientes a los dos eventos de
clsUsuario y que se implementan en la
interface __clsUsuario_Event. Recordemos que en COM, una itnerfaz es
una clase abstracta, y que siempre se
crea una interfaz con prefijo subrayado, en este caso _clsUsuario. Durante
la importación se crea una clase administrada que representa a cada coclase
COM, en este caso de la clase original
clsUsuario a clsUsuarioClass , añadiéndole al final la palabra Class. De
manera transparente, al importar se le
añade a la clase administrada el atributo GuidAttribute para capturar el identificador de clase (CLSID) perteneciente a la coclase, clsUsuario, cuyas
interfaces tienen un único identificador
global (IID). Además se agrega una
interfaz con el mismo nombre que la
coclase y al igual que la clase administrada en dicha interfaz se añade un atributo CoClassAttribute para la identifación CLSID de la coclase origen. Como
el nombre de los elementos de un mismo tipo no pueden ser el mismo, al
importar, por defecto, se resuelve cualquier conflicto subrayando antes del
nombre de la interfaz, de ahí que
encontremos interfaces con nombre
__clsUsuario. En la clase administrada
clsUsuarioClass, .NET ha añadido un
constructor por defecto sin parámetros
(figura 4).
Hasta aquí hemos visto la sencillez
de importación de un componente
COM propio y hemos explicado lo que
hace .NET cuando se importa una clase de tipo COM. Las llamadas..., pues
tan sencillo como utilizar cualquier otra
clase en .NET como podemos observar
en el ejemplo del fuente 1.
43
<< dnm.plataforma.net
TlbImp.exe
Para mostrar el siguiente ejemplo
de cómo importar el componente
COM vamos a crear la biblioteca de
tipos fuera de la DLL. Para ello, a la
hora de compilar el proyecto
UsuarioCOM de Visual Basic 6.0 en la
propiedades de proyecto, en la ficha
componente, marcamos la opción
“Remote Server Files”, generar archivos remotos. Esto generará un archivo clsUsuario.TLB con la descripción
de la biblioteca de tipos.
Lo que haremos será importar
mediante TlbImp.exe la biblioteca de
tipos y registrar el ensamblado resultante con un nombre seguro. Para ello
abriremos el “Símbolo del sistema” de
Visual Studio .NET y ejecutamos la
utilidad TlbImp.exe seguido del nombre del archivo que hace referencia a
la biblioteca de tipos y que tiene
extensión TLB; en nuestro caso sería
clsUsuario.tlb. Podemos utilizar los
parámetros /keyfile para aplicar un
nombre seguro señalando el fichero
resultante de la ejecución de la utilidad sn.exe, por ejemplo. El resultado
una vez ejecutado TlbImp será un
archivo DLL. El nombre por defecto
será el que ha utilizado anteriormente y que es el equivalente al nombre
del proyecto de Visual Basic 6.0 en el
que se compiló, o sea, UsuarioCOM.DLL.
A continuación utilizaremos la utilidad Regasm.exe y registraremos el nuevo ensamblado, UsuarioCOM.
Figura 5.Vista desde del bloc de notas del ensamblado UsuarioCOM en MSIL.
Una vez hecho esto ahora sí podemos desde Visual Studio .NET agregar una referencia pero no es necesario que sea desde la ficha de COM,
sino que en el mismo .NET seleccionamos el recientemente creado archivo UsuarioCOM.DLL. Ahora, podemos
empezar a trabajar bajo código administrado.
observar, pese a que la teoría y funcionamiento interno es realmente
complejo, el CLR nos lo oculta y nos
permite interactuar con objetos COM
de una manera simple, transparente y
eficaz.
Esta es la primera parte de tres
entregas. En la siguiente entrega
veremos un ejemplo de interopera-
C:\sn -k UsuarioCOM.snk
C:\Tlbimp clsUsuario.tlb /
keyfile:UsuarioCOM.snk
Este ensamblado, llamado ensamblado de interoperabilidad, será el encargado de hacer de puente con el componente COM. Dicho ensamblado
puede ser modificado manualmente
utilizando el desensamblador
IldASM.exe. Si ejecutamos C:\ildasm
Figura 6.Vista del ensamblado de interoperabilidad UsuarioCOM
des del examinador de objetos
<<dotNetManía
UsuarioCOM.dll /out=UsuarioCOM.il
44
creará un archivo con extensión IL
que contendrá la definición MSIL
(código intermedio). Si abrimos dicho
archivo con el Bloc de Notas (figura 5),
podríamos modificarlo y tras guardarlo trataríamos de ensamblarlo de
nuevo.
Conclusión
En esta primera parte, hemos
implantado un componente COM
desde .NET. Como habrá podido
bilidad de .NET desde COM con un
ejemplo sencillo. En la web de
dotNetManía (www.dotnetmania.com)
puede descargar el código fuente de
este artículo.
dnm.lenguajes.delphi
Octavio Hernández
Acceso a datos en Delphi 2005
Delphi 2005 ofrece la posibilidad de desarrollar para la plataforma .NET utilizando dos vías diferentes para el acceso a datos: a través de los recursos que ofrece
la VCL.NET, una librería de compatibilidad desarrollada por Borland; o a través de
ADO.NET, la tecnología de acceso a datos “nativa” de la plataforma .NET.
<< Delphi 2005 es un entorno integrado para el desarrollo Acceso a datos desde aplicaciones
<<dotNetManía
Octavio Hernández
es colaborador habitual
de dotNetManía,
Ingeniero en Informática
de Sistemas y MVP de
C#.Actualmente es
Director Técnico de
Danysoft
46
de aplicaciones tanto para Win32 como para .NET
Framework. En cualquiera de los dos casos, la herramienta ofrece toda una gama de facilidades para
permitir desarrollar de una manera altamente productiva, aplicaciones y componentes que accedan a
cualquiera de las bases de datos más populares del
mercado.
En lo que respecta al desarrollo de aplicaciones
.NET, Delphi 2005 ofrece la posibilidad de hacerlo
utilizando dos vías diferentes para el acceso a datos: a
través de los recursos que ofrece la VCL.NET, una
librería de compatibilidad desarrollada por Borland
para facilitar la migración de aplicaciones Win32 a
.NET, así como el desarrollo de aplicaciones portables entre ambas plataformas; o a través de ADO.NET
–la tecnología de acceso a datos nativa de la plataforma .NET–. Ambas vías ofrecen a su vez diferentes
alternativas al desarrollador.
Este artículo presenta las principales alternativas
disponibles para acceder de una manera directa a diferentes bases de datos desde aplicaciones o componentes .NET creados con Delphi 2005. Esto quiere
decir que no describiremos aquí los recursos que permiten el desarrollo de aplicaciones de múltiples capas,
tema que merece un artículo independiente.
Inicialmente se presentan brevemente las alternativas que ofrece la VCL.NET, que interesarán
mayormente a los usuarios de versiones anteriores de
Delphi; a continuación, nos centraremos en las alternativas “cien por cien .NET” basadas en la utilización
de ADO.NET, y describiremos con mayor nivel de
detalle el Proveedor de Datos de Borland (BDP, Borland
Data Provider), una extensión de las clases de acceso
a datos de .NET desarrollada por Borland para facilitar el acceso nativo de alto rendimiento a las bases
de datos relacionales más populares del mercado.
VCL.NET
Con la aparición de Delphi 2005, Borland ha puesto a disposición de los desarrolladores interesados en
migrar sus aplicaciones a .NET o en mantener aplicaciones que puedan ser compiladas para ambas plataformas a partir de una única base de código fuente,
todos los mecanismos de acceso a datos con los que
se podía desarrollar en Delphi 7 y versiones anteriores. Estos mecanismos son:
• Borland Database Engine (BDE). La alternativa de acceso a datos por excelencia de Borland
durante casi una década. El BDE es un motor de
acceso a datos cuyo objetivo fundamental era facilitar el acceso genérico a diferentes bases de datos
a las aplicaciones C++ y Delphi. Permite el acceso tanto a bases de datos “de escritorio” (dBase,
Paradox, Access) como a las principales bases de
datos corporativas (Oracle, Informix, DB2, SQL
Server, InterBase). Actualmente el BDE ha visto
pasar sus mejores días, y no se recomienda utilizarlo en nuevos desarrollos. No obstante, quedan
muchísimas aplicaciones basadas en él, y sigue siendo la vía más efectiva para acceder a bases de datos
con interfaz ISAM, como Paradox.
• DBExpress (DBX). Esta tecnología apareció con
Delphi 6, como sustituto para el obsolescente
BDE. Se trata igualmente de una tecnología para
el acceso genérico a bases de datos que intentaba
superar las deficiencias fundamentales del BDE,
en primer lugar muy “pesado” y engorroso de desplegar, y en segundo lugar demasiado atado a
Windows (en aquellos tiempos comenzaba su
andadura Kylix, la versión de Delphi para Linux).
Para aligerar DBExpress en la medida de lo posible, Borland tomó las siguientes decisiones:
<< dnm.lenguajes.delphi
Acceso a datos desde aplicaciones FCL.NET
La plataforma .NET define un
mecanismo universal para el acceso a
ensamblado común y se asocian a un
mismo espacio de nombres. La versión
1.1 de .NET Framework incluye de
serie cuatro proveedores de datos diferentes (ver tabla 1):
• El proveedor de datos .NET para SQL Server, un conjunto de clases diseñadas específicamente para interactuar de
forma nativa y con un alto nivel de eficiencia con bases de
Especializados
datos de Microsoft SQL Server.
• El proveedor de datos .NET para Oracle, un conjunto de
clases que permite el acceso nativo a bases de datos Oracle.
Genéricos
• El proveedor de datos .NET para OLEDB, un conjunto
de clases que permite acceder a cualquier almacén de datos
para el que se disponga de un proveedor OLEDB.
• El proveedor de datos .NET para ODBC, un conjunto de
clases que permite acceder a cualquier base de datos relacional para el que se disponga de un controlador ODBC.
Tabla 1
datos –ADO.NET–, que entre muchas
otras buenas características incluye la de
ser una tecnología abierta y extensible.
El objetivo del resto de este artículo no
es otro que mostrar cómo Delphi 2005
no sólo ofrece la posibilidad de explotar todas las características de
ADO.NET, sino que además se apoya
en dicha tecnología para ofrecer una
nueva solución que aporta un valor añadido a sus usuarios –el Proveedor de Datos
de Borland (BDP)–.
Se denomina en su conjunto “proveedor de datos .NET”, al conjunto de
clases que implementan las interfaces
de .NET Framework que especifican
las funcionalidades que se deben satisfacer para acceder a una fuente de datos
específica e interactuar con ella en
ambas direcciones (recuperando y
enviando datos). Tales conjuntos de clases generalmente se almacenan en un
La plataforma .NET define un mecanismo universal
para el acceso a datos -ADO.NET-, que entre muchas
otras buenas características incluye la de ser
una tecnología abierta y extensible.
Delphi 2005 ofrece soporte completo para la utilización de estos cuatro proveedores en aplicaciones y componentes
.NET. Inicialmente, la Paleta de
Componentes sólo muestra los componentes que conforman el proveedor de datos
para SQL Server (ver figura 1).
Figura 1.Contenido inicial de la página de
Acceso a Datos de la Paleta de Componentes
Para hacer uso mediante programación
de cualquiera de los otros tres proveedores de datos desde Delphi 2005, será necesario incorporarlos a la “Paleta de
Componentes”. Esto se logra mediante la
opción “Component | Installed .NET
<<dotNetManía
• Limitar el soporte de
DBExpress sólo a bases de datos
basadas en la utilización del lenguaje SQL.
• Ofrecer únicamente recursos
para el trabajo con cursores unidireccionales. Esta característica
potenció el crecimiento de una
filosofía de desarrollo basada en
componentes de caché y trabajo
en régimen desconectado.
• DBGo. Inicialmente conocida
como ADOExpress, y luego
renombrada por problemas legales, esta tecnología no es más que
una fina capa de software impuesta sobre ADO para adecuarla a los
convenios habituales a los que
están acostumbrados los programadores de Delphi. Desde su aparición, ha sido utilizada con bastante frecuencia por los equipos de
desarrollo de Delphi para crear
aplicaciones, fundamentalmente
contra bases de datos SQL Server
o Access.
• IBExpress (IBX). Es una librería
de componentes orientada únicamente a bases de datos InterBase,
el motor SGBD propio de
Borland. Su principal ventaja es el
alto rendimiento que proporciona, al apoyarse directamente en
GDS32.DLL , la librería cliente de
InterBase.
En principio, el uso recomendado
de estas tecnologías para el desarrollo
.NET se circunscribe a las aplicaciones VCL.NET; si bien es factible
acceder a estas tecnologías desde aplicaciones Windows Forms o ASP.NET,
su utilización complicaría tanto la programación como el despliegue de las
mismas.
47
<< dnm.lenguajes.delphi
Components…” del menú principal, marcando las casillas correspondientes a las clases Command, Connection y DataAdapter con
prefijos ODBC, OleDB y Oracle (ver figura 2).
Ejemplo de aplicación básica
A continuación, ofrecemos un
pequeño tutorial que describe la creación con Delphi 2005 de una aplica-
Figura 4.El asistente para la edición de la
cadena de conexión
Figura 2. Instalación de componentes ADO.NET en la “Paleta de
Componentes” de Delphi 2005
Las clases se integrarán en la página “Data Components” de la “Paleta de
Componentes” (figura 3).
ción que accede a la tabla HR.EMPLOYEES de la base de datos de sistema de
una instancia de Oracle llamada ORCL.
El proceso es muy similar al que realizaríamos de estar utilizando Visual
Studio .NET.
Para comenzar, creamos una nueva
aplicación WinForms en Delphi 2005.
Es conveniente configurar en este
momento las propiedades del formulario principal y guardar todos los ficheros del proyecto. Seguidamente, arrastramos sobre el formulario un componente de la clase OracleConnection y le
asignamos su cadena de conexión utilizando el asistente asociado a la propiedad (vea la figura 4).
La cadena de conexión resultante tiene una apariencia similar a la siguiente:
<<dotNetManía
data source=ORCL;user
id=MiUsr;password=MiPwd
48
Figura 3.La página de “Componentes
de Datos” ampliada
Donde MiUsr y MiPwd son el nombre
de usuario y la contraseña a utilizar para
acceder a la base de datos. Por supuesto, resulta obligada la advertencia de que
no es una buena idea incluir la contraseña estáticamente en la cadena de conexión (¡ni siquiera en aplicaciones de
prueba como ésta!).
Ahora colocamos sobre el formulario un componente OracleDataAdapter, que utilizaremos como
“puente” para traer los datos de la base
de datos a un objeto DataSet .
Desplegamos la propiedad SelectCommand, donde se deben establecer las
características de la sentencia SQL
que utilizaremos para recuperar esos
datos. Asignamos una referencia a
nuestro objeto de conexión a la propiedad interna Connection de
SelectCommand, y la sentencia SELECT *
FROM HR.EMPLOYEES a la propiedad
CommandText.
A continuación, pulsamos con el
botón derecho del ratón sobre el adaptador de datos y lanzamos el asistente
“Generate DataSet”; esto producirá un
objeto DataSet11 , que contendrá un
objeto llamado Table, de tipo DataTable,
donde se almacenarán los datos de los
empleados provenientes de la base de
datos.
Finalmente, para presentar los datos
en el formulario, colocamos sobre él un
componente DataGrid (página Data
Controls), asignamos a su propiedad
DataSource una referencia a DataSet11,
y a la propiedad DataMember una referencia a Table.
Ahora sólo falta una línea de
código en el evento Load del formulario para que al arrancar la aplicación se traigan los datos de la base
de datos al formulario y se muestren
en la rejilla:
<< dnm.lenguajes.delphi
procedure fmOracle1.fmOracle1_Load(
sender: Object; e: EventArgs);
begin
OracleDataAdapter1.Fill(DataSet11);
end;
La aplicación en ejecución tendrá
una apariencia similar a la figura 5.
liares) que ofrece una interfaz de programación uniforme para las principales bases de datos SQL del mercado (en
Delphi 2005: Oracle, SQL Server, DB2,
Sybase, InterBase y Access). En el fondo, BDP no es más que un “paraguas”
Figura 5. La aplicación creada, en ejecución
El Proveedor de Datos de
Borland (BDP)
Como hemos comentado antes,
Microsoft ha provisto al acceso a datos en
.NET de una arquitectura abierta, que
hace posible que no sólo dispongamos de
genérico que oculta tras de sí a conjuntos de clases especializadas en el acceso
nativo de alto rendimiento a una base
de datos específica. El BDP enruta todas
las peticiones que recibe al proveedor
interno correspondiente, como se muestra en la figura 6.
cación a otro SGBD podría reducirse a
algo tan simple como cambiar los valores
de la propiedad ConnectionString de los
objetos de conexión (que podrían, para
una flexibilidad aún mayor, almacenarse
en un fichero de configuración, fuera del
código).
Otra ventaja relacionada con la anterior es que el uso del Proveedor de Datos de
Borland simplifica en gran medida el desarrollo de aplicaciones que deban estar preparadas para poder trabajar contra diferentes bases de datos, algo que utilizando
exclusivamente las librerías de .NET
Framework sólo puede resolverse programando a nivel de interfaces.
Por último, hay que destacar que los
proveedores específicos para cada una de
las bases de datos soportadas son proveedores nativos que “atacan” directamente
al software cliente de la base de datos, lo
que asegura un alto rendimiento, además
de simplificar el despliegue, ya que no se
requiere la instalación de ningún middleware adicional.
Soporte para BDP en tiempo de
diseño
Las facilidades que ofrece Delphi 2005
para el desarrollo visual de aplicaciones
de acceso a datos a través del BDP son
superiores a las que obtendremos con
cualquier otra tecnología de acceso a datos.
Las conexiones a bases de datos se
configuran dentro del propio entorno utilizando la pestaña “Data
un conjunto cerrado de proveedores, sino
que podamos además aprovechar los nuevos proveedores que desarrollen los diferentes fabricantes de software para dar un
soporte optimizado para una base de datos
específica, o (como en el caso de Borland)
un tipo de soporte diferente del que ofrece por defecto .NET.
El Proveedor de Datos de Borland
(BDP, Borland Data Provider) no es más
que un proveedor de datos .NET (formado por las clases BdpConnection ,
BdpCommand, BdpDataAdapter y otras auxi-
La ventaja fundamental de este enfoque radica en que los desarrollos quedan
mucho más protegidos ante un posible
cambio de base de datos. Si se utilizan
directamente los componentes que ofrece .NET 1.1, cualquier cambio de base de
datos exigiría numerosas modificaciones
en el código fuente (por ejemplo, para
cambiar todos los usos de SqlConnection
por OracleConnection, etc.). Si se utiliza
el proveedor BDP (y se evita en lo posible la utilización de extensiones propietarias de SQL en el código), portar una apli-
Figura 7.El “Explorador de Datos “
de Delphi 2005
<<dotNetManía
Figura 6. Arquitectura del Proveedor de Datos de Borland
49
<< dnm.lenguajes.delphi
ría es Live Data, o sea, datos vivos), que hace
posible visualizar los datos directamente
en tiempo de diseño, detalle al que están
acostumbrados desde siempre los programadores de Delphi (figura 9).
Invitamos al lector a que desarrolle
la aplicación básica equivalente a la que
hemos creado en el punto “Ejemplo de
aplicación básica”, utilizando el proveedor BDP en lugar del proveedor de
Oracle suministrado por .NET
Framework.
El Proveedor de Datos de Borland no es más que un
proveedor de datos .NET que ofrece una interfaz
de programación uniforme para las principales
bases de datos SQL del mercado
Explorer” del “Gestor de Proyectos”
(figura 7).
El explorador no sólo nos permite
configurar las propiedades de las conexiones a bases de datos, sino también
realizar de forma centralizada muchas
tareas prácticas como crear, copiar o
visualizar tablas, entre otras.
En el caso de Oracle, el diálogo de
configuración de una conexión a una
base de datos a través de BDP podría
tener la apariencia de la figura 8.
Figura 9. “Datos vivos” en tiempo de diseño
Figura 8.El “Editor de Conexiones” de
Delphi 2005
La cadena de conexión resultante
sería similar a la siguiente:
hace el Proveedor de Datos de Borland
cuando se le indica, por ejemplo, que
ejecute una sentencia SQL contra una
conexión específica.
Durante el desarrollo, para generar
objetos BdpConnection y BdpDataAdapter
correctamente configurados basta con
arrastrar y soltar una tabla cualquiera desde el “Explorador de Datos” a un formulario del proyecto. Sólo resta entonces
generar mediante el asistente del adaptador el objeto DataSet y configurar los controles visuales necesarios. Como ventaja
<<dotNetManía
Assembly=Borland.Data.Oracle,Version=2.0.0.0,Culture=neutral,
PublicKeyToken=91d62ebb5b0d1b1b;vendorclient=oci.dll;database=ORCL;provider=Oracle;
username=MiUsr;password=MiPwd
50
La estructura de esta cadena de
conexión deja entrever qué es lo que
adicional, los adaptadores de datos BDP
ofrecen una propiedad Active (su catego-
Conclusiones
En este artículo hemos presentado
las opciones que pone Delphi 2005 en
manos del desarrollador que se enfrenta
al desarrollo de una aplicación o componente .NET que acceda a bases de
datos. Inicialmente hemos mencionado
las opciones de compatibilidad con
Win32, para luego centrarnos en las
alternativas basadas en ADO.NET, la
tecnología de acceso a datos incorporada a .NET Framework. Hemos mostrado cómo con Delphi 2005 es posible utilizar cualquiera de los proveedores de
datos .NET predefinidos por la
FCL.NET, o aprovechar las ventajas que
ofrece el BDP, un proveedor de datos
creado por Borland para el acceso genérico de alto rendimiento a las bases de
datos más populares del mercado.
CD VOLUMEN 1
dotNetManía
LLÉVATELO TODO
dotNetManía CD Volumen 1 es un CD con todos los
artículos publicados en la revista dotNetManía entre
febrero de 2004 y enero de 2005 (números 1 al 11).
Puede obtener de forma gratuita este dotNetManía
CD Volumen 1 con una nueva suscripción o con su
renovación a la revista dotNetManía. Aunque aún
no tenga que renovar, puede hacerlo de forma anticipada y así recibirlo gratuitamente y sin esperas.
Si no desea suscribirse o renovar su suscripción,
puede adquirir el dotNetManía CD Volumen 1 por
24,50€ (IVA incluido) (sólo para envíos en España).
Más información y pedidos al teléfono
(34) 91 666 74 77 o en www.dotnetmania.com.
dnm.todotnet.qa
Dino Esposito
¿Está seguro con ASP.NET?
ToDotNet-QA es la nueva columna dirigida por Dino Esposito con la que pretendemos solucionar las dudas que los lectores nos envíen y servir a todos con contenidos amenos e interesantes. Si desea enviar consultas a Dino para esta columna, puede hacerlo al email [email protected].
<< Muchos desarrolladores han aprendido por cuenta propia
Dino Esposito
es redactor de dotNetManía.
Formador, consultor y escritor
afincado en Roma. Miembro del
equipo de Wintellect, Dino está
especializado en ASP.NET y
ADO.NET.
Puede enviarle sus consultas a
[email protected]
que la seguridad de sus aplicaciones no es algo que se
pueda añadir simplemente al final, o ser olvidado en las
fases de diseño de las aplicaciones. La seguridad es algo
que debe ser inherente a la funcionalidad de la aplicación y debería planearse como una de las primeras características al más alto nivel.
Por naturaleza, las aplicaciones Web están sujetas a
varios tipos de ataques, cuyo daño e impacto varían bastante dependiendo de la naturaleza misma de la aplicación. La aplicación segura es aquella que resiste los ataques, no la que se queda en el mero diseño de seguridad,
ya que se trata de un puzzle complejo que cambia entre
aplicaciones. Lo importante es recordar que –muy a
menudo– la seguridad se manifiesta mediante una mezcla de medidas a nivel de aplicación junto a otras que
afectan al sistema operativo.
No hay aplicaciones Web seguras en una red insegura, de la misma forma que la red más fortificada no
puede proteger una aplicación pobremente diseñada,
que ofrece el campo suficiente para los ataques. En esta
primera entrega de esta nueva sección responderé unas
cuantas cuestiones generales sobre seguridad, y espero
que muestre la forma de construir e instalar aplicaciones sólidas y resistentes.
Habría que estar sordo y ciego para ignorar todos
los comentarios acerca de los problemas asociados
a la seguridad. No digo que esto sea un bulo, porque lo demuestran las estadísticas e informes, pero
veo que la mayoría de la literatura al respecto se limita a mostrar causas y efectos pero no se para mucho
en las contramedidas. Así pues, ¿Qué se entiende
por una aplicación segura?
Cada vez más analistas acuerdan que la parte más
insegura son las aplicaciones y no los sistemas. Los años
de experiencia han hecho que se cree hardware que no
contiene en sí ninguna medida de seguridad, para luego
implantarla mediante configuraciones del software.
Durante años hemos construido aplicaciones bajo la falsa apreciación de que un sistema seguro era más que suficiente. Esto se ha demostrado que es falso ya que en la
1
actualidad la mayoría de los ataques de seguridad se camuflan bajo la apariencia de peticiones correctas al servidor, y acceden a las aplicaciones a través de la puerta
principal: el puerto 80.
¿Cómo puedes diseñar una aplicación segura? Hay
varias soluciones implicadas, tal y como comentan David
Leblanc y Michael Howard, en su clásico “Writing
Secure Applications”, de MS Press (2003)1. Sin embargo, un aspecto en particular es fácil de implementar y de
recordar, al menos en lo que concierne a ASP.NET 1.1.
La guía de seguridad se puede resumir en lo siguiente:
nunca te fíes de los datos de entrada del usuario.
Solamente mediante la aplicación de este principio,
habrás conseguido reducir la superficie de exposición a
ataques en un considerable porcentaje.
void OnSubmit (Object sender, EventArgs e)
{
Output.Text = "Hello, " + Input.Text;
}
Tres de los ataques más comunes –inyección SQL,
código de script fuera de ámbito o el llamado ataque
“one-click”– son debidos a una capa de validación pobre
e insegura. Las aplicaciones Web funcionan aceptando
y procesando datos de usuarios; si la entrada está falseada, la aplicación está en riesgo. Que levante la mano el
usuario que nunca haya añadido a una cadena, el contenido de una caja de texto para construir una consulta.
Esta operación no es peligrosa de por sí, pero puede tener
efectos devastadores combinada con otras debilidades.
Fijémonos en el siguiente código:
Supongamos que Input es una caja de texto y Output
una etiqueta (label). En este código, cualquier cosa que
escriba el usuario, se reflejará en la página final. Un usuario malintencionado puede insertar ahí un bloque de
Javascript que permita grabar y recuperar cookies. De
nuevo, una cookie robada puede ser o no un problema.
Sin embargo, ofrece a los atacantes un frente claro sobre
el que actuar en el sistema.
¿Y qué pasa si el contenido simbolizado por Input es
una consulta o una cookie envenenada? (una cookie enve-
Los distribuidores para España de libros de MS Press en inglés para su distribución vía WEB son Visual Programming (visualpr.net)
nenada es aquella cuyo contenido ha sido
artificialmente creado o alterado).
Más en general, el problema con el
código anterior es que no existe validación alguna del mismo. Antes de utilizar
cualesquiera datos introducidos por el
usuario, el texto debería de pasar por un
examen preliminar, que nos garantice que
la entrada es segura. Eso significa que los
datos deben ser del tipo esperado, acorde con el patrón y longitud esperadas, y
encontrarse dentro del rango de valores
requerido. Una aplicación que no cumple estos requisitos es potencialmente
insegura, mientras que una aplicación
que sí lo hace consigue reducir la superficie de ataque expuesta a la mínima
dimensión.
¿Puede decirnos algunas reglas
prácticas para la construcción de aplicaciones ASP.NET seguras? No quiero leer más avisos genéricos acerca de
“buffer overruns” o validaciones de
entrada. Lo que me gustaría es una lista detallada de cosas a tener en cuenta.
Me gusta la pregunta por que plantea
el mismo problema desde una distinta perspectiva. Los “buffer overrun”, o sea, permitir más espacio para las entradas del que
es necesario, y por lo tanto, capacitar a los
atacantes a que incluyan instrucciones de
ataque adicionales, y la validación de entradas, son la clave de la seguridad Web. Estoy
de acuerdo sin embargo, en que estas directivas son quizá un tanto generalistas, así
que pongámoslo claro: las aplicaciones
ASP.NET seguras deberían cumplir al
menos con lo siguiente:
• Mantener ValidateRequest activo.
• Asignar un valor no vacío a ViewStateUserKey.
• Utilizar procedimientos almacenados
para el acceso a datos.
• Otorgar permisos de escritura en las
bases de datos con extremo cuidado.
• Utilizar datos fuertemente tipados,
expresiones regulares y validaciones
de rango.
Analicémoslas con más detalle.
ValidateRequest es un atributo de la directiva @Page introducido por ASP.NET 1.1.
Aplica una expresión regular a ciertos formularios de entrada de datos (campos de
entrada y cadenas de consulta SQL) para
detectar datos potencialmente peligrosos.
En particular, este atributo filtra cualquier
código HTML que pueda ser el preludio
de código Javascript malicioso. Este atributo está activado por defecto y no hay
razón para deshabilitarlo a no ser que
resulte imprescindible que tu aplicación
tenga que captar datos en formato
HTML. No se trata de un salvavidas absoluto contra los ataques, sino una medida
más de prevención, que debe ser tenida
en cuenta junto con las propias que adopte el desarrollador.
ViewStateUserKey es también una propiedad de la clase Page que fue introducida en la versión 1.1 de ASP.NET. Debería
inicializarse a una cadena no vacía diferente para cada usuario. Por ejemplo,
podría ser el nombre de usuario, si la aplicación tiene una pantalla de credenciales
de inicio, o incluso mejor, el valor de la
variable SessionID. ¿Qué beneficios se
obtienen con esto? Que hace que sea
imposible para los potenciales atacantes
preparar un formulario específico para
“crackear” una página concreta, el llamado “ataque one-click”, una forma relativamente nueva de “script fuera de ámbito”.
Si se activa y asigna a un valor dependiente del servidor y con un dato específico
para cada usuario, resulta imposible –prácticamente– violarlo mediante esa técnica.
En cuanto a los procedimientos almacenados, existen dos razones: rendimiento
y seguridad. Es bien conocido que los procedimientos almacenados están “precompilado” en el servidor, lo que redunda en
un acceso mucho más rápido. Además,
suelen utilizar un buen número de sentencias que obligan al programador a personalizar el procedimiento mediante el
uso de variables fuertemente tipadas. No
hay necesidad de concatenar cadenas para
construir las peticiones de datos, el tipo y
la longitud son obligatorios y el riesgo de
“inyección de código” se minimiza.
Al mismo tiempo, el acceso a datos
requiere una cuenta con permisos de lectura y escritura. Para reducir la superficie de ataques, deberían utilizarse las
cuentas con el menor número de permisos para realizar la operación deseada, y
–si es posible– nunca elevar los permisos
por encima del nivel de seguridad (y
menos a nivel de administrador) a ninguno de los usuarios.
Finalmente, exigir la validación estricta de los datos de entrada. Cualquier canal
de entrada, en cualquier aplicación está
diseñado para recibir datos de un cierto
tipo y con un cierto tamaño e incluso con
alguna clase de formato, o dentro de un
rango determinado. Por variadas razones,
sin embargo, no siempre se verifican los
datos de entrada. Esta discrepancia es la
semilla potencial para los ataques. Después
de todo, de eso va la validación.
Muchas fuentes recomiendan utilizar seguridad integrada cuando se
accede a SQL Server. ¿Es ésa la mejor
política en las aplicaciones ASP.NET?
Podría ser. La ventaja clave de la seguridad integrada cuando se conecta a una
instancia de SQL Server, es que no necesita de credenciales explícitas. No se toman
datos personales de la cadena de conexión,
ni se tienen que introducir manualmente
o recordar. Utilizamos en ese caso un
modelo único de seguridad que hereda las
características de bloqueo y expiración de
contraseñas directamente de Windows.
SQL Server necesita configurarse para
ejecución en Windows o en modo mixto.
Ambos programas gestionan todo e intercambian la información necesaria. ¿Qué
significa eso en el contexto de una aplicación ASP.NET?
Trata de escribir una página simple
que se conecte a SQL Server usando seguridad integrada. En una configuración
estándar, obtienes un error de autenticación. La seguridad integrada significa que
la cuenta de proceso de ASP.NET (sea
ASPNET o NETWORK SERVICE) es la que se usa
en la conexión al servidor. Si esta cuenta
no aparece en la lista de cuentas del servidor, se emite una excepción de autorización. Si se añade un nuevo login, todo
empieza a funcionar. ¿Es eso todo?
La seguridad integrada es estupenda,
siempre que sea aceptable que una única
cuenta de usuario realice todas las tareas
en el servidor. ¿Qué sucede si se ha diseñado la aplicación utilizando roles? En ese
caso, existen muchas probabilidades de
que algunos usuarios ejecuten tareas con
más nivel de permisos del que sea necesario. Esto no es malo en sí, pero puede
dejar la puerta abierta a ataques por
“inyección SQL”. Si se utilizan roles, lo
mejor es autenticar al usuario en la misma puerta de la aplicación y aprovechar
la capa intermedia para comprobarlas. Se
asigna cada rol a una cuenta específica de
acceso al servidor y es esa cuenta la que
realiza las tareas competentes del rol que
le corresponde. No existe una superficie
extra para los ataques, y se mantiene la eficiencia del pool de conexiones.
<<dotNetManía
<< dnm.todotnet.qa
53
dnm.laboratorio.net
Pedro Pozo
Raptier, rápido por naturaleza
Raptier es una herramienta de desarrollo rápido, que sirve para generar una aplicación web o de escritorio para gestionar la información de una base de datos en
un abrir y cerrar de ojos.
<< Raptier nos permite acortar de forma espectacular el
<<dotNetManía
Pedro Pozo
es redactor de dotNetManía. Es
es consultor e-Bussines.
Ingeniero Técnico Informático
de Sistemas y Webmaster
del portal para desarrolladores
.NET Framework Clikear.com
54
tiempo de desarrollo, obteniendo un código muy
bien estructurado y documentado. En Raptier todo
es muy sencillo, se trata de una herramienta poco
vistosa que ofrece las opciones justas y evita incluir
cosas superfluas que casi nunca se utilizan.
A pesar de ser poco espectacular en su aspecto,
sí que nos sorprenderá por su efectividad; en apenas unos minutos podemos tener una aplicación
completamente funcional, bien estructurada y fiable para gestionar la información de nuestra base
de datos.
El código que se genera es independiente del
tipo de base de datos que utilicemos de forma que
podemos cambiar, por ejemplo, de Microsoft SQL
Server a ORACLE sin ningún problema. Raptier
admite cualquier base de datos OLE DB, por lo
cual podemos utilizar casi cualquier base de datos
existente.
Al entrar en Raptier nos aparece una aplicación
que puede parecer incluso un poco austera, y al
comenzar un nuevo proyecto nos aparecerá una
ventana (igual que cuando realizamos una conexión
UDL) para definir sobre qué base de datos vamos
a trabajar.
A continuación, tan solo deberemos marcar las
opciones que deseamos para nuestro proyecto, que
no son muchas pero sí muy interesantes.
Como podemos ver en la figura, Raptier nos
permite elegir entre Visual Basic .NET y C# como
lenguajes en los que creará el código fuente, también nos permite elegir entre si deseamos que cree
un proyecto para Visual Studio .NET 2002 o 2003
o Borland C#.
Otra opción curiosa es que nos da a elegir entre
crear procedimientos almacenados o generar las
consultas en el código y, sin duda la mejor de todas,
es que nos permite crear la aplicación para Web o
como aplicación de escritorio, o de ambas formas.
Después tan solo tendremos que seleccionar generar código y ya tendremos nuestra aplicación para
gestionar la información de una base de datos.
Podremos añadir, modificar y borrar datos de
todas nuestras tablas de la base de datos a través de
sencillos formularios, y si deseamos darle más funcionalidad siempre podemos acceder al código fuente y modificarlo a nuestro gusto.
El código que genera Raptier separa perfectamente la capa de acceso a datos de la interfaz de la
aplicación, es un código bien estructurado y fácilmente modificable. Además genera una documentación muy completa sobre la base de datos en
HTML.
Aunque el diseño gráfico de las aplicaciones que
genera RapTier no es muy espectacular, nos ofrece la posibilidad de crear una plantilla que nos permite personalizar más el aspecto de nuestras aplicaciones. Así podemos crear distintos diseños web
y adaptarlos al look&feel de nuestra web.
La versión Enterprise nos ofrece la posibilidad
de generar la documentación de la base de datos
automáticamente. Esta documentación incluye
información sobre las tablas, vistas, procedimientos almacenados, triggers y relaciones. De esta forma Raptier también nos ahorra tiempo, no sólo en
el desarrollo sino también a la hora de generar documentación y poder mantenerla actualizada.
También cabe destacar de Raptier que genera
un conjunto de servicios Web con toda la funcionalidad del mantenimiento de las tablas de la base
de datos elegida, pudiendo así gestionar los datos
de las tablas de nuestra base de datos desde cual-
<< dnm.laboratorio.net
bajar y obtener resultados visibles. Sin
necesidad de ningún conocimiento de
programación podemos crear una aplicación que sirva para añadir, modificar
o borrar datos de las tablas de una base
de datos. Hay muchas herramientas de
desarrollo más completas y versátiles
que Raptier, pero hay pocas con las que
se pueda empezar a obtener resultados
tan rápido y con un tiempo de aprendizaje tan corto.
Entre los inconvenientes se debe
destacar la corta funcionalidad de esta
aplicación, es una pena que sólo sirva
para crear mantenimientos de tablas
de base de datos y no nos ofrezca más
posibilidades, pero si lo hiciera quizá
perdería su sencillez.
quier entorno que llame a estos servicios Web.
Requisitos del sistema
Los requisitos básicos para la instalación Raptier son bastante asequibles, lo mínimo recomendable puede
verse en la siguiente tabla de requisitos del sistema:
Requisitos del Sistema
Procesador
Intel Pentium 100
Memoria RAM
128 MB
Disco duro
5 Mb de espacio libre
Sistema
Operativo
Windows XP o
Windows 2000
Software
.NET Framework
Diferencias entre las versiones
Raptier se ofrece en 3 versiones:
Lite, Professional y Enterprise. La versión Lite podemos descargarla gratuitamente de Internet y tiene como limitación el poder trabajar con un máximo de 15 tablas. La versión
Professional permite trabajar con un
número ilimitado de tablas y también
ofrece soporte técnico. Por último, la
versión Enterprise que suma a las
características de la versión professional el permitir generar la documentación de la base de datos.
Conclusiones
Quizá se echen en
falta algunas opciones
más para poder personalizar más la aplicación o para poder
añadirle alguna funcionalidad más, pero
siempre tenemos la
opción de poder modificar el código
que obtenemos con Raptier a través
de la herramienta de desarrollo que
deseemos.
Pero si desea poder realizar mantenimientos de base de datos de una
forma rápida y sencilla, Raptier es una
herramienta ideal.
Ficha técnica
Ventajas e inconvenientes
Sin duda la principal virtud de
Raptier es la rapidez y sencillez con la
que podemos conseguir empezar a tra-
A pesar de ser poco espectacular en su aspecto, sí que
nos sorprenderá por su efectividad; en apenas unos
minutos podemos tener una aplicación completamente
funcional, bien estructurada y fiable para gestionar la
información de nuestra base de datos
Nombre
RapTier
Versión
1.4.1
Fabricante
SharpPower
Web
www.sharppower.com
Categoría
Herramientas de desarrollo
Edición
Precio
Lite
Gratis
Professional 1 licencia
299$
> 4 licencias 169$
Enterprise
1 licencia
499$
>4 licencias 279$
Valoración
<<dotNetManía
Aspecto de la pantalla de configuración de Raptier.
55
Suscripción a
dotNetManía
❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) y beneficiarme de la oferta del 10% de descuento por un
importe total de 60 € para España; o por 120€ para el resto del mundo (envío por avión) (IVA incluido).
❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) por un importe de 45 € por ser estudiante (IVA incluido).
Aporto fotocopia del carné de estudiante o sello del centro académico (IMPRESCINDIBLE). OFERTA VÁLIDA SÓLO
PARA ESTUDIANTES RESIDENTES EN ESPAÑA.
IMPORTES VÁLIDOS HASTA NUEVA OFERTA
DATOS DE FACTURACIÓN
CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . .
Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .
DATOS DE ENVÍO (sólo si son distintos de los datos de facturación)
CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . .
Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .
FORMA DE PAGO
❑ Talón nominativo a nombre NETALIA, S.L.
❑ Transferencia bancaria a nombre de NETALIA, S.L. a:
La Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia)
❑ Domiciliación Bancaria (con renovación automática, previo aviso)
Indique su número de cuenta:
❑ Tarjeta de crédito
❑ VISA
❑ MASTERCARD
Número de su tarjeta:
Fecha de caducidad:
/
(imprescindible)
Firma y/o sello (imprescindible)
a
❑ Nº5
❑ Nº6
❑ Nº7
de
❑ Nº8
de 20 0
❑ Nº9
Si desea algún otro número indíquelo
Puede enviar los datos al email [email protected],
al FAX (34) 91 499 13 64 o al teléfono (34) 91 666 74 77.
También puede enviarlo por correo postal a la siguiente dirección:
Netalia, S.L
C/ Robledal, 135
28529 - Rivas Vaciamadrid
Madrid (España)
Usted autoriza a la mecanización
de estos datos. El responsable y
destinatario de éstos es Netalia,
S.L. Usted tiene derecho a acceder a sus datos, modificarlos y
cancelarlos cuando lo desee. Sus
datos no serán cedidos en ninguna de las formas posibles a terceras partes y no se utilizarán
más que para el buen funcionamiento de su suscripción a la
revista dotNetManía y para
informarle de las actividades
comerciales que realice la editorial Netalia, S.L. Si no desea
recibir información comercial de
dotNetManía marque la casilla
siguiente ❑
❑ Nº10
❑ Nº11
<< dnm.biblioteca.net
dnm.biblioteca.net
OOP:Building Reusable Components with Microsoft® Visual Basic® .NET
Ken Spencer,Tom Eberhard, y John Alexander
Editorial: Microsoft Press
ISBN: 0735613796
Páginas: 495
Publicado: Octubre, 2002
En el camino se implementan los elementos de la solución mediante capas que se corresponden con algunas de las técnicas más importantes de construcción de aplicaciones: mecanismos de seguridad, capas de datos, implementación de clientes génericos de servicios Web,
capas de negocio, interfaces de usuario (Web y Windows) e incluso el uso de Remoting para
comunicaciones.
C# for Java Developers
Allen Jones y Adam Freeman
Editorial: Microsoft Press
ISBN: 0735617791
Páginas: 550
Publicado: Agosto, 2002
Los autores, dos experimentados programadores en Java (y autores de varias obras
sobre ese lenguaje), analizan primero la plataforma y sus diferencias estructurales
respecto a J2EE, para continuar con un análisis exhaustivo del lenguaje C#, siempre manteniendo en el punto de mira el perfil teórico del lector del libro (o sea,
otro programador de Java), haciendo especial hincapié en las diferencias entre ambos
lenguajes, y explicando, en muchos casos, las novedades que aporta C#, de las que
no existen equivalentes naturales en Java. La obra concluye con unos capítulos finales sobre servicios Web, integración de plataforma, creación de ensamblados compartidos, recolección de basura, interoperabilidad entre lenguajes, configuración
de aplicaciones, y una –utilísima– guía de las APIs .NET en su correspondencia
con los “packages” java.*. De lectura recomendable para el desarrollador de java
que desee migrar aplicaciones.
<<dotNetManía
<<
Esta primera propuesta bibliográfica es algo que por su sencillez aparente, muchos echábamos de menos. Un habitual del Tech-Ed, Ken Spencer, gran comunicador y divulgador
famoso por su sencillez y claridad expositiva, codirige, junto a otros colaboradores también
conocidos, esta obra cuya mayor virtud es, quizás, lo modesto de sus objetivos iniciales. El
libro, recorre la construcción de una aplicación, siguiendo algunas de las más populares “buenas prácticas para .NET”, en un viaje que va desde la arquitectura de la solución propuesta, (que será desarrollada en su integridad a lo largo del libro), hasta el montaje final o implementación.
57
noticias.noticias
<< dnm.desvan
Marino Posadas
Nuevas herramientas de seguridad de Microsoft
Microsoft sigue empeñada en la mejora de sus herramientas de seguridad, pero esta vez, anuncia herramientas instalables, y no service packs. Por un lado, y basada en la tecnología adquirida a la compañía Giant,
Windows Antispyware, se encuentra disponible desde
el pasado mes de enero, y aparte de su funcionalidad esencial, aporta complementos de seguridad que aparecieron
asociados el Windows XP SP2, como control de las ventanas pop-up, los cambios no deseados en las configuraciones de Internet y el uso no autorizado de información
personal. Microsoft cuenta con la comunidad SpyNet,
una red de usuarios voluntarios que ayuda a descubrir
rápidamente nuevas amenazas para asegurar que todos
los usuarios estén bien protegidos.
Documentos en la Red
Asimismo, la nueva herramienta para eliminar código malicioso consolida las herramientas existentes en una única solución, que será actualizada el segundo martes de cada mes como
parte de la iniciativa de actualizaciones mensuales de Microsoft.
La herramienta se encuentra en http://www.microsoft.com/athome/security/spyware/software, y podría completarse con otras
herramientas para la eliminación de virus.
Microsoft vuelve a organizar PDC (Professional Developers
Conference)
Esta vez, en Septiembre 2005 (del 11 al 16, en Los Angeles,
CA). Las fechas son tremendamente sospechosas, así que
(dados los anuncios de calendario), parece que coincidiría
con la salida de Visual Studio 2005 y/o SQL Server 2005, si
es que uno de ellos no ha visto la luz antes.
Utilidades recomendadas
(Especial utilidades de monitorización de sitios web)
Introduction to Data Communications es un obra
muy completa, (más de 500 páginas) de Eugene
Blanchard, que puede encontrarse gratuitamente
en www.techbooksforfree.com/intro_to_data_com/
toc.html.
Las 46 mejores utilidades gratuitas de todos los tiempos (moder-
En la misma ubicación, pueden encontrarse otras “joyas”, sobre tecnología
informática y sobre .NET en particular, en especial las ubicadas en la página www.techbooksforfree.com/microsoft.shtml, incluidos algunos interesantes avances, como por ejemplo Developer Guide
to Migration and Interoperability in Longhorn,
o las excelentes Real World XML Web Services,
del conocido divulgador Yasser Shohoud (ponente habitual en Tech-Ed's y PDC's), o The .NET
Developer's Guide to Windows Security, de
Keith Brown, otro gran conocedor de las APIs de
Windows y autor de obras de referencia desde los
tiempos de MS-DOS.
ConfigInspector: Utilidad gratuita para análisis de la información
<<dotNetManía
Guia para la grabación y codificación musical es
el nombre aproximado de “A guide to ripping and
encoding music”, documento disponible en
http://arstechnica.com/guides/tweaks/encoding.ars
comenzando por las definiciones de los conceptos
más comunes.
58
Cómo funciona un buscador Por fin, como complemento a al especial de utilidades recomendadas
para la monitorización de sitios Web, recomendamos este documento en: www.alt64.com/extras/Como_Funciona_un_Buscador.zip
nos), es la oferta que podemos encontrar en “The 46 Bestever Freeware Utilities”, disponible en http://www.techsupportalert.com/best_46_free_utilities.htm.
del sistema. Dispone de las mismas
utilidades que el “Administrador de
Tareas de Windows” más toda una
serie de características añadidas.
Está disponible en http://softvoile.
com/configinspector.php.
Herramientas gratuitas para el seguimiento y mejora del posicionamiento de sitios Web en los buscadores: Las hay de
varios tipos, desde las que permiten altas simultáneas: Marketleap en http://www.marketleap.com/siteindex o seguimiento de bloqueos
(Poodle predictor: http://www.gritechnologies.com/tools/spider.go?q=www.noticias.com y
Summit Spider Simulator: http://tools.summitmedia.co.uk/spider), hasta conocer la densidad de las palabras clave en el texto (sitio:
http://www.ranks.nl/tools/spider.html, o herramienta Density
Analyzer, en http://www.searchengineworld.com/cgi-bin/kwda.cgi),
pasando por comparaciones de la posición de una Web respecto a ciertas palabras (Thumbshots: http://ranking.thumbshots.com) o cómo conocer el Page Rank de una página Web:
http://pagerank.walidator.com.
Photo Story 3 for Windows: Para concluir esta larga lista de recomendaciones, no olvidemos esta nueva herramienta gratuita
de Microsoft, que puede descargarse de www.microsoft.com/windowsxp/using/digitalphotography/photostory.

Documentos relacionados

El modelo de objetos de Visual Studio .NET El modelo de objetos

El modelo de objetos de Visual Studio .NET El modelo de objetos Administración Pilar Pérez ([email protected]) Asesor Técnico Marino Posadas ([email protected]) Redactores Antonio Quirós, Dino Esposito, Guillermo 'guille' Som, Jorge Serra...

Más detalles

PON: P2P Over .NET PON: P2P Over .NET

PON: P2P Over .NET PON: P2P Over .NET Administración Pilar Pérez ([email protected]) Asesor Técnico/Coordinación Marino Posadas ([email protected]) Redactores Antonio Quirós, Dino Esposito, Guillermo 'guille' Som...

Más detalles

Visual Basic • C# • ASP.NET • ADO.NET • .NET Framework

Visual Basic • C# • ASP.NET • ADO.NET • .NET Framework problemas de rendimiento en SQL Server. El artículo de portada este mes es nuevamente para la sección dnm.futuro, donde Octavio Hernández presenta las novedades de VB 9.0 para implementar LINQ. Est...

Más detalles