Resumen del Evento de la Comunidad.NET Febrero 2007

Hola. ¿Qué tal?


Pues esta ocasión quiero comentarles que la reunión de la comunidad.NET del DF se llevó a cabo con bastante éxito, el suficiente diría yo, pues por poco y no cabemos en la sala de la cantidad que fue, eso es bueno y nos motiva a superarnos cada sesión.


Empezamos con Héctor Obregón, quién nos habló de XAML y su implementación en 3D, un tema de actualidad dada la liberación del .NET Framework 3.0, así que lo que mostró es ahora una realidad viable e integrable en nuestras aplicaciones.


Seguido tocó el turno a Octavio Telis, o sea yo, y toqué un tema básico sobre el desarrollo de componentes de interfaz de usuario, en específico de los componentes de proceso de interfaz de usuario, donde de manera general mostré las ventajas de concentrar la funcionalidad común de la interfaz de usuario en un componente proveedor de dicha funcionalidad.  Además, mostré un ejemplo básico para Windows forms sobre la concentración de funcionalidad en dichos componentes. También hablamos de algunos conceptos un poco más profundos sobre componentes de acceso a datos, ya un poco fuera de tema, por lo que podríamos tomar ese tema para futuras reuniones. Por cierto, grabé la presentación a manera de WebCast, y haciendo honor al nombre de mi blog de contenido en línea, o sea, AS-IS, así será como lo publique, AS-IS. Creo que en futuras versiones estaremos haciendo lo mismo si todo sale bien. El sitio de este WebCast  estará disponible pronto. Además, aprovechando el viaje, quiero comentarles que también estará saliendo la segunda parte del WebCast de delegados con una serie de ScreenCasts sobre algunas maneras útiles de explotar esta funcionalidad.


Seguido a mi participación, vino el turno de Juan Karam, donde expuso todo lo relacionado a metodologías de prueba con VSTS, Visual Studio Team Suite, mostró las características de las pruebas unitarias utilizando la funcionalidad de Visual Studio TS.


En resumen, una buena velada con mucho conocimiento útil para la comunidad.


Los esperamos para la próxima, no falten.


Saludos…


Octavio Telis.

WebCast AS-IS

En está página está el contenido de los WebCasts que he publicado.


Próximamente:


Delegados Parte II
Componentes de Proceso de Interfaz de Usuario (grabado en vivo)
Tipos Anulables


WebCast Delegados Parte I: Introducción al uso de delegados


En este webcast  quiero dar una introducción al uso de los delegados, el webcast viene acompañado de un screencast para la presentación de ejemplos. Aquí pretendo cubrir el tema de uso de eventos en nuestras clases. Espero que lo disfruten y que sea de utilidad.

WebCast Delegados: Introducción al uso de delegados

ScreenCast Delegados: Introducción al uso de delegados

Saludos…

Octavio Telis

 


WebCast – Arquitectura de aplicaciones .NET Parte I La interfaz de usuario


En este webcast pretendo mostrar las características básicas de la interfaz de usuario de aplicaciones .NET utilizando los conceptos de la arquitectura de aplicaciones .NET.

Espero que sea de su agrado y utilidad.

Arquitectura de Aplicaciones .NET Parte I: Interfaz de Usuario

 

Saludos…

Octavio Telis

WMI… Consultar el sistema de una PC de modo remoto

Anteriormente mostré un ejemplo bastante simple de la consulta de procesos en una PC, sin embargo WMI tiene más capacidad y no se limita a solo consultar de manera local la información del sistema, también puede hacerlo de manera distante o remota dentro de una red y esto hace mucho sentido cuando tratamos de entender que WMI es al final un conjunto de instrumentos para la administración de sistemas ya sea en modo local o remoto.


La manera remota de hacer consultas dependerá de algunos factores y como es de suponerse son factores relacionados estrechamente con la seguridad y qué más que el nombre de la PC, un usuario y una contraseña válidos.


No será difícil realizar un ejemplo de lo que estamos hablando, y precisamente lo haremos con la clase Win32_Process, que bien podría ser cualquier otra, teniendo en cuenta siempre las propiedades de la clase. Veamos pues nuestro ejemplo, en el cual usaremos nuevos elementos, entre ellos el “Alcance” formalmente llamado System.Management.ManagementScope el cual servirá para proporcionar la información de usuario y esas cosas para que el sistema al que estamos consultando sepa quien llama y a qué tiene acceso y a qué no, es interesante ver que de alguna manera WMI no es tan vulnerable para los aspectos críticos del sistema, esto es, que no cualquiera puede consultar lo que sea en la PC de otra persona.


Bueno pues continuemos con el ejemplo:


Crearemos un método estático para colocarlo en donde más nos convenga, tal vez en nuestro componente de procesos de interfaz de usuario o en algo parecido. Este método devolverá una tabla de la misma manera que el ejemplo anterior para poder desplegarlo en cualquier control que contenga una propiedad DataSource que acepte un DataTable como fuente de datos. Veamos:


public static DataTable GetProcess(string Equipo, string Usuario, string Password)


{


    System.Management.ManagementPath path =


            new System.Management.ManagementPath(“\\\\” + Equipo + “\\root\\cimv2″);


    System.Management.ConnectionOptions cops = new System.Management.ConnectionOptions();


    cops.Username = Usuario;


    cops.Password = Password;


 


    System.Management.ManagementScope scope = new System.Management.ManagementScope(path, cops);


    System.Management.ManagementObjectSearcher searcher =


        new ManagementObjectSearcher(scope, new System.Management.ObjectQuery(“Select * From Win32_Process”));


    DataTable dt = new DataTable();


    DataRow dr;


 


    dt.Columns.Add(“Caption”);


    dt.Columns.Add(“CreationClassName”);


    dt.Columns.Add(“CreationDate”);


    dt.Columns.Add(“Description”);


    dt.Columns.Add(“ExecutablePath”);


    dt.Columns.Add(“ExecutionState”);


    dt.Columns.Add(“Handle”);


    dt.Columns.Add(“InstallDate”);


    dt.Columns.Add(“MaximumWorkingSetSize”);


    dt.Columns.Add(“MinimumWorkingSetSize”);


    dt.Columns.Add(“Name”);


    dt.Columns.Add(“Priority”);


    dt.Columns.Add(“ProcessId”);


    dt.Columns.Add(“SessionId”);


    dt.Columns.Add(“Status”);


    dt.Columns.Add(“TerminationDate”);


    dt.Columns.Add(“ThreadCount”);


    dt.Columns.Add(“WindowsVersion”);


    dt.Columns.Add(“WorkingSetSize”);


 


    try


    {


        foreach (ManagementObject share in searcher.Get())


        {


            dr = dt.NewRow();


            dr[“Caption”] = share[“Caption”];


            dr[“CreationClassName”] = share[“CreationClassName”];


            dr[“CreationDate”] = share[“CreationDate”];


            dr[“Description”] = share[“Description”];


            dr[“ExecutablePath”] = share[“ExecutablePath”];


            dr[“ExecutionState”] = share[“ExecutionState”];


            dr[“Handle”] = share[“Handle”];


            dr[“InstallDate”] = share[“InstallDate”];


            dr[“MaximumWorkingSetSize”] = share[“MaximumWorkingSetSize”];


            dr[“MinimumWorkingSetSize”] = share[“MinimumWorkingSetSize”];


            dr[“Name”] = share[“Name”];


            dr[“Priority”] = share[“Priority”];


            dr[“ProcessId”] = share[“ProcessId”];


            dr[“SessionId”] = share[“SessionId”];


            dr[“Status”] = share[“Status”];


            dr[“TerminationDate”] = share[“TerminationDate”];


            dr[“ThreadCount”] = share[“ThreadCount”];


            dr[“WindowsVersion”] = share[“WindowsVersion”];


            dr[“WorkingSetSize”] = share[“WorkingSetSize”];


            dt.Rows.Add(dr);


        }


    }


    catch (System.UnauthorizedAccessException ex)


    {


        MessageBox.Show(“Mensaje: “ + ex.Message);


    }


    catch (System.Management.ManagementException ex)


    {


        MessageBox.Show(“Mensaje: “ + ex.Message + System.Environment.NewLine +


            “Código de error: “ + ex.ErrorCode.ToString() + System.Environment.NewLine +


            “Información de Error: “ + ex.ErrorInformation + System.Environment.NewLine);


    }


 


    return dt;


}



Este método acepta tres parámetros, el primero es equipo y es el nombre del equipo tal y como está identificado en la red, el segundo es el nombre del usuario, este usuario debe ser un usuario con suficientes privilegios en la PC que se consulta o miembro del grupo de administradores dentro del dominio en el que se identifica la PC, por último, Password que es la contraseña del usuario que se está autenticando en el equipo.


Hemos llegado al final del ejemplo, lo que hace es semejante al ejemplo anterior, sin embargo aquí estamos mostrando el uso extendido para consultar los procesos en un equipo remoto. Se pueden utilizar otras clases como Win32_RegistryAction para consultar el registro del sistema o también Win32_OperatingSystem que da información del sistema operativo, la descripción detallada de propiedades puede ser consulta en el MSDN Library en la sección de WMI


Saludos…


 

Octavio Telis

WMI… Una breve presentación de esta tecnología

Tanto tiempo enfrente y poco caso…

 

Bueno… si digo eso será porque puede ser sorprendente que muy pocos desarrolladores le hayan tomado interés a WMI, así es y además se preguntarán en caso de no saberlo ¿Qué es WMI?.

Bueno, WMI significa Windows Management Instrumentation, o bien, Instrumental de administración de Windows, y ¿Qué es?, bueno en sí son un conjunto de clases que residen en el sistema operativo… es increíble, pero WMI está presente de manera nativa desde Windows 2000, ya hace un buen tiempo de eso, además se le prestó soporte a Windows 9x con redistribuibles que permitían a un servidor consultar elementos del sistema operativo de manera remota. WMI no nace de la nada y no es algo que Microsoft haya inventado, WMI es la implementación de Microsoft dentro de Windows de un estándar llamado WBEM (Web-Based Enterprise Management ) que está basado en la definición de CMI (Common Model Information). CMI provee definiciones para clases de administración que podemos encontrar prácticamente en cualquier sistema operativo que adopte estos estándares.

WMI implementa clases para consultas de información del sistema operativo, se divide en tres grandes grupos:

  • Hardware
  • Software
  • Sistema Operativo

Las clases están bien documentadas y lo mejor es que con la llegada del .NET Framework se ha simplificado enormemente su uso. En el .NET Framework existe un solo espacio de nombres enfocado a WMI: System.Management.

En lo personal he disfrutado mucho usando WMI con .NET, de cierta manera es divertido hacer aplicaciones como un visor de procesos y mejor cuando le encuentra uno la utilidad, por ejemplo; en Windows 2000 a pesar de poder ver los procesos, difícilmente sabemos cuál es la ruta de ejecución y me he cansado de buscar esa columna en el Administrador de Tareas sin éxito, y cuando se es desconfiado siempre es bueno saber qué se ejecuta y donde se está ejecutando y WMI ofrece esa información.

Para ilustrar un poco el uso de WMI con .NET me gustaría presentarles este ejemplo, es un método que devuelve un DataTable para poder pasárselo a lo que quieran que acepte un DataTable como DataSource.


public static DataTable GetProcess()

{

    System.Management.ManagementObjectSearcher searcher = new ManagementObjectSearcher(“Select * From Win32_Process”);

    DataTable dt = new DataTable();

    DataRow dr;

 

    dt.Columns.Add(“Caption”);

    dt.Columns.Add(“CreationClassName”);

    dt.Columns.Add(“CreationDate”);

    dt.Columns.Add(“Description”);

    dt.Columns.Add(“ExecutablePath”);

    dt.Columns.Add(“ExecutionState”);

    dt.Columns.Add(“Handle”);

    dt.Columns.Add(“InstallDate”);

    dt.Columns.Add(“MaximumWorkingSetSize”);

    dt.Columns.Add(“MinimumWorkingSetSize”);

    dt.Columns.Add(“Name”);

    dt.Columns.Add(“Priority”);

    dt.Columns.Add(“ProcessId”);

    dt.Columns.Add(“SessionId”);

    dt.Columns.Add(“Status”);

    dt.Columns.Add(“TerminationDate”);

    dt.Columns.Add(“ThreadCount”);

    dt.Columns.Add(“WindowsVersion”);

    dt.Columns.Add(“WorkingSetSize”);

 

    foreach (ManagementObject share in searcher.Get())

    {

        dr = dt.NewRow();

        dr[“Caption”] = share[“Caption”];

        dr[“CreationClassName”] = share[“CreationClassName”];

        dr[“CreationDate”] = share[“CreationDate”];

        dr[“Description”] = share[“Description”];

        dr[“ExecutablePath”] = share[“ExecutablePath”];

        dr[“ExecutionState”] = share[“ExecutionState”];

        dr[“Handle”] = share[“Handle”];

        dr[“InstallDate”] = share[“InstallDate”];

        dr[“MaximumWorkingSetSize”] = share[“MaximumWorkingSetSize”];

        dr[“MinimumWorkingSetSize”] = share[“MinimumWorkingSetSize”];

        dr[“Name”] = share[“Name”];

        dr[“Priority”] = share[“Priority”];

        dr[“ProcessId”] = share[“ProcessId”];

        dr[“SessionId”] = share[“SessionId”];

        dr[“Status”] = share[“Status”];

        dr[“TerminationDate”] = share[“TerminationDate”];

        dr[“ThreadCount”] = share[“ThreadCount”];

        dr[“WindowsVersion”] = share[“WindowsVersion”];

        dr[“WorkingSetSize”] = share[“WorkingSetSize”];

        dt.Rows.Add(dr);

    }

 

    return dt;

}

Se puede consultar la información de las clases WMI y sobre System.Management en línea en MSDN:

Clases WMI
System.Management

Para terminar solo quiero comentar que WMI está jugando un papel muy importante en los sistemas operativos y sin duda se convertirá en parte medular de nuestras aplicaciones, así pues, no duden en darse una tiempo para aprender un poco más de WMI.

Espero que lo disfruten.

Saludos…

 

Octavio Telis

Obtener el “Content Type” de un archivo en base a su extensión

Qué es el “Content Type”, no es más que el tipo de contenido de un archivo. La definición de este tipo de contenido es utilizado con frecuencia para tareas utilizando aspectos relacionados con “MIME” (Multipurpose Internet Mail Extensions). Los tipos definidos de esta manera no solo son utilizado en los mensajes de correo electrónico, sin embargo el uso del campo “Content-Type” está definido por el estándar <a href=”http://www.faqs.org/rfcs/rfc2046.html” target=”_blank”>RFC 2046</a> , en el que en grandes rasgos, se recomienda el uso de un tipo y subtipo para definir el tipo de medio que se está enviando por correo electrónica ya sea como adjunto o como parte incrustada de un mensaje.
En el estándar mencionado se definen cinco tipos discretos de medios a saber: text, image, audio, video y application. Además se tienen dos tipos de composición de alto nivel que son: multipart y message.

Lo que nos atañe es el uso de los tipos discretos y cómo están vinculados con los archivos que usamos comúnmente y las aplicaciones.

En específico, la tarea de obtener el “Content-Type” de un archivo tiene gran relevancia cuando estamos enviando o publicando el mismo en Internet, más cuando es necesario para construir el encabezado que lo describe.

No es extenso este ejemplo solo describe la manera de consultar el registro de Windows, ya que en él se encuentran registradas las extensiones del archivo, en específico las que están en el equipo en cuestión.

La llave del registro que consultaremos será el HKEY_CLASSES_ROOT, misma que contiene descripción del contenido de archivos de una extensión de archivo. Por ejemplo:

El Content-Type de un archivo con extensión “.doc” será la que se describe en esta llave:
   HKEY_CLASSES_ROOT\.doc\Conten Type

La cual tiene el siguiente valor:
   application/msword

Veamos el ejemplo que utilicé para obtener este valor:


private string GetContentType(stringFileExtension)
{
   
// Convertimos la extensión en minúsculas
   
string ext = FileExtension.ToLower(
        System.Threading.Thread.CurrentThread.CurrentCulture);
   
// Verificamos que contenga el punto de
    // otra manera habría que agregarlo para
    // poder obtener los resultados esperados

   
if (!ext.StartsWith(“.”))
        ext = String.Concat(“.”, ext);
   
// Se declara un permisos pata obtener
    // acceso de solo lectura al registro
    // NOTA: Se está utilizando: using System.Security.Permissions;

    RegistryPermission Reg =
new RegistryPermission(
    RegistryPermissionAccess.Read, “HKEY_CLASSES_ROOT\\”);
   
// Creamos un llave de registro para
    // HKEY_CLASSES_ROOT

    Microsoft.Win32.RegistryKey regKey =
        Microsoft.Win32.Registry.ClassesRoot;
   
// Intentamos crear una llave de registro
    // a partir de la extensión

    Microsoft.Win32.RegistryKey regKeyExt =
        regKey.OpenSubKey(ext);
   
// Si la extensión existe como sub llave de registro
    // entonces devolveremos su valor de lo contrario
    // se devuelve el valor predeterminado

   
if(regKeyExt == null)
       
return “application/octet-stream”;
   
else
       
return regKeyExt.GetValue(“Content Type”,
    “application/octet-stream”).ToString();
}


Este es solo un método que a partir de la extensión dada de un archivo, buscará información sobre el Content Type en el registro. Se devuelve el tipo predeterminado application/octet-stream si no se encuentra información referente al tipo del archivo en cuestión.


Espero sea de utilidad y les sea útil como a mí.


Saludos…


Octavio Telis

Tipos Parciales… Introduciendo el concepto

Dentro de las nuevas características de los lenguajes .NET en su versión 2005 podemos encontrar el modificador partial, el cual nos permite tener una organización más adecuada de nuestro código. Este modificador podemos utilizarlo para dividir la funcionalidad de nuestros tipos de acuerdo a nuestras políticas de desarrollo, las cuales pueden dividir el código en distintas ramas. Por ejemplo, en una clase podría ser útil dividir el código en métodos y propiedades, o bien, en código que rara vez cambia debido a su definición, como las propiedades y métodos principales de una clase de acceso a datos definida para un objeto de la base de datos, el cual podríamos llamar “estático” y en otra parte generar los métodos inherentes a la funcionalidad dinámica de la clase, como métodos de consulta específicos. También podemos tener el caso de dividir el código por concepto, encontrando en un tipo las propiedades y métodos para cálculo, y propiedades y métodos para mostrar resultados, separar la implementación de interfaces en partes separadas del mismo tipo, etc.

El modificador partial está definido para tres de las cuatro definiciones de tipos, estos son: class, struct, interface. Es obvia la razón, ya que un delegado difícilmente podría ser dividido en varias partes por su naturaleza, la cual es propiamente la de apuntar hacia un método dentro del programa, indirectamente estaríamos hablando de dividir un método en varias partes y por ende a un miembro de la clase. Más aún, los delegados al ser definidos simplemente expresan la firma del método que manejará las llamadas a este. Por otro lado el enumerador (enum) no es posible dividirlo pues enlista una serie de valores, de lo cual, si dividiéramos esta lista sería prácticamente imposible saber cual de las partes es el principio y cual el final. Además, se pretende separar funcionalidad y no la propia definición del tipo.

El modificador partial se coloca precediendo a las palabras claves class, struct e interface. La palabra partial no es una palabra clave, y tiene sentido solo en tiempo de compilación, ya que al final el ensamblado contendrá la integración de todas las partes de los tipos parcializados, esto es, si dividimos una clase en dos o tres partes, esta clase será compilada en una sola pieza dejando al modificador partial fuera del assembly final.

Un ejemplo de la definición de un tipo parcial es como sigue:

partial class EjemploParcial
{

}


Se deben tener ciertas consideraciones al utilizar un tipo parcial, primeramente debemos tener en mente que al dividir un tipo en varias partes no es hacer dos tipos distintos, por lo que se afecte o modifique en una definición afectará al tipo completo, veamos un poco más detallado esto:

Los atributos de un tipo parcial que se definan en una o mas de sus partes y se aplica a todas sus partes como resultado de la combinación de estos.

Los modificadores public, static, private que se apliquen en una o varias de las partes del tipo deben ser congruentes entre sí, esto es, que se pueden definir distintas partes utilizando uno de los modificadores mencionados ya que una clase no puede ser public y private al mismo tiempo.

Si al menos una de las partes de una clase parcial tiene el modificador abstract, entonces se considera el tipo abstracto.

Si al menos una de las partes de una clase parcial tiene el modificador sealed, entonces se considera el tipo sellado.

Una clase solo puedes abstracta o sellada más no ambos. Así que la definición de una de las partes de la clase solo podrá ser abstract o sealed o bien no tener definido ninguno de los dos.

Las variables declaradas en una de las partes del tipo serán visibles en todas sus partes y no podrán repetirse los nombres de los identificadores para evitar declaraciones ambiguas. Así, todo lo que se declare en una de las partes de un tipo parcial estará visible en todas las demás partes.

partial class A
{
int x; // Error, no se puede declarar X más de una vez
partial struct B // Ok, B es un tipo parcial

{
int y;
}
}

partial class A
{
int x; // Error, no se puede declarar x más de una vez
partial struct B // Ok, B es un tipo parcial

{
int z;
}
}

Todas las partes de un tipo parcial deben ser declaradas bajo el mismo espacio de nombres.

La definición de una clase base en una de las partes debe coincidir con las definiciones de clase base en las demás partes, dado que no es posible la herencia múltiple, solo podrá definirse una clase base y bastará con estar en una de las partes para aplicarse al tipo completo.

La definición de una o más interfaces en cada una de las partes será la unión de todas en una sola definición. Esto es, que si se ha definido la misma interfaz en varias partes, se aplicara como una solo definición, y únicamente se definirán los miembros requeridos de la interfaz una sola vez.
Una implementación típica de tipos parciales la veremos comúnmente en los formularios de Visual Studio 2005

Pues bien, a grandes rasgos esta es la definición de un tipo parcial.

Saludos…

Octavio Telis

WebCast Delegados Parte I: Introducción al uso de delegados

En este webcast  quiero dar una introducción al uso de los delegados, el webcast viene acompañado de un screencast para la presentación de ejemplos. Aquí pretendo cubrir el tema de uso de eventos en nuestras clases. Espero que lo disfruten y que sea de utilidad.


WebCast Delegados: Introducción al uso de delegados


ScreenCast Delegados: Introducción al uso de delegados


Saludos…


Octavio Telis

Reunión de la Comunidad .NET Febrero 2007

 

Fecha: Martes 27 de Febrero (Confirmado)
Horario: 7:00 a 9:50 p.m.
Lugar: Intersoftware Training
World Trade Center – Piso 35
Mexico D.F.

Agenda:
Por confirmar – Hector Obregon
Componentes de Proceso de Interfaz de Usuario – Octavio Telis
Pruebas unitarias en Team Foundation Server – Juan Karam
.NET Remoting – Raúl Guerrero

Entrada Gratuita . no requiere registro.