domingo, 29 de julio de 2012

Power Shell para Mono

Power Shell es el más reciente intérprete de comandos o CLI (Command Line Interface) para ambientes Windows similar a la consola de MS-DOS pero a diferencia de esta; Power Shell es además un lenguaje de guiones (Scripting Language) con derecho propio para competir con las opciones de cualquier shell en las plataformas UNIX/Linux.
Si retomamos una de las definiciones clásicas de lo que es un Shell:


"El Shell lee las ordenes y las interpreta como peticiones de ejecución de un programa o programas, por esta característica al shell se le denomina interprete de comandos, aquí el Shell es un lenguaje de programación."

tomado del libro UNIX System V Versión 4, Kenneth H. Rosen & Richard R. Rosinski.


Uno de los objetivos de Power Shell es llenar el vacío que siempre ha caracterizado a los sistemas Windows en cuanto a tener una consola de comandos medianamente funcional y poderosa ya que en este aspecto el Shell en los sistemas UNIX/Linux nunca han tenido ni cercanamente una competencia en el MS-DOS.
Dentro de las características de Power Shell tenemos las siguientes:


  • Esta basado en el Korn Shell por lo que hasta cierto la funcionalidad de este Shell es compatible con Power Shell.

  • Cumple con el estándar POSIX IEEE 1003.2

  • Es un scripting language que se agrega a los lenguajes de programación de Microsoft.

  • Utiliza el modelo de objetos de .NET para la representación de datos.


Pues bien en la página http://pash.sourceforge.net/ hay una versión Open Source de Power Shell la cual puede usarse con Mono.
Una vez que se han descargado los binarios desde la pagina se ejecuta el comando:

$ mono Pash.exe

Enseguida aparecerá la consola de Power Shell como en la siguiente imagen:


sábado, 23 de junio de 2012

Manuales acerca de PostgreSQL

Uno de los aspectos importantes para el desarrollo de aplicaciones corporativas en .NET o Mono es conocer una sistema manejador de base de datos (DBMS) a un buen nivel, en el caso de los ambientes Windows la opción predeterminada para los desarrolladores .NET es SQL Server,aunque también existen opciones open source para esa plataforma, una buena parte de las herramientas de base de datos de .NET es concebida en inicio para ese producto.
Para los ambientes Linux existen DBMS comerciales y open source igualmente buenas, pero hay un DBMS en particular que la mayoría de las ocasiones debemos de tener en cuenta sobretodo por sus características y este sin duda es PostgreSQL, ya por algo su lema es: "The world's most advanced open source database" (la base de datos open source más avanzada del mundo).
Pues bien, aquí pongo unos documentos que nos apoyarán en el conocimiento de este DBMS.

lunes, 18 de junio de 2012

Envio de e-mails vía SMTP con GTK# y Monodevelop.

Uno de los requerimientos más comunes para las aplicaciones .NET es el envío de E-mails o correos electrónicos, entre los ejemplos mas usuales para este tipo de requerimiento se encuentran el envío automático automático de boletines electrónicos, notificaciones de eventos, bitácora del sistema, solicitudes de reunión, envío de archivos adjuntos entre otros. .NET nos proporciona los ensamblados System.Net.Mail y System.Net.Mime, los cuales contienen todas las clases e interfaces necesarias para habilitar este tipo de requerimiento en cualquier aplicación .NET, a continuación describimos los elementos más importantes de estos ensamblados:

  • MailMessage:
  • Representa un mensaje de correo electrónico, esta clase tiene todas las propiedades del mensaje por ejemplo: tema del mensaje, destinatario, destinatarios, remitente,cuerpo entre otras.
  • MailAdress:
  • Representa una dirección de correo electrónico, esta clase ya implenta la lógica para validar que el formato sea correcto.
  • ContentType:
  • Representa la cabecera del protocolo MIME
  • AlternateView:
  • Representa una vista alternativa del mensaje en un formato diferente al predeterminado, por ejemplo HTML ó Calendar.
  • SmtpClient:
  • Esta clase se encarga de enviar el mensaje, aquí se establecen los parámetros de configuración del servidor SMTP, como: numero de puerto, usuario, password, SSL entre otros.

Como ejemplo de la utilización de estas clases, mostramos un formulario GTK# en Monodevelop que recibe los parámetros de configuración de un servidor SMTP, crea un mensaje de correo electrónico y lo envía hacia el o los destinatarios, utilizando dos clases: EMailMessage y SendMail.

El formulario en vista de diseño de MonoDevelop.


El código fuente de la clase EmailMessage


El código fuente de la clase Sendmail
<--Code Sendmail-->

<--Code Sendmail-->
El código fuente del formulario GTK#.
using System;
using Gtk;
using TestMail;
using System.Collections.Generic;

public partial class MainWindow : Gtk.Window
{
public MainWindow () : base(Gtk.WindowType.Toplevel)
{
Build ();
}

protected void OnDeleteEvent (object sender, DeleteEventArgs a)
{
Application.Quit ();
a.RetVal = true;
}
protected virtual void OnBtnSubmitClicked (object sender, System.EventArgs e)
{
try{
SendMail sendMail = null;
var email = new EMailMessage(txtSubject.Text,
                                  txtFrom.Text,
                                  GetAddresses(),
                                  txtDescription.Buffer.Text,
                         chkIsHtml.Active);
if(chkCredentials.Active)
sendMail = new SendMail(txtHost.Text,Convert.ToInt32(txtPort.Text),chkEnableSSL.Active);
else
sendMail = new SendMail(txtHost.Text,Convert.ToInt32(txtPort.Text),chkEnableSSL.Active
                            ,txtUserName.Text,txtPassword.Text);
sendMail.Send(email);
ShowMessageBox("Email Sent");
}catch(Exception ex){
ShowMessageBox(ex.Message);
}
}

void ShowMessageBox(string msg){
using (Dialog dialog = new MessageDialog (this,
      DialogFlags.Modal | DialogFlags.DestroyWithParent,
      MessageType.Info,
      ButtonsType.Ok,
      msg)) {
dialog.Run ();
dialog.Hide ();
}
}

List<string> GetAddresses() {
var resp = new List<string>();
foreach (string s in txtTo.Text.Split(','))
resp.Add(s);
return resp;
} 
protected virtual void OnBtnQuitClicked (object sender, System.EventArgs e)
{
Application.Quit();
} 

protected virtual void OnChkCredentialsToggled (object sender, System.EventArgs e)
{
tblCredentials.Visible = !chkCredentials.Active;
}
}

Básicamente el envió de correos electrónicos consiste de dos pasos: Primero la creación del mensaje con sus adjuntos si es que los hubiese, de esta responsabilidad se encarga la clase EMailMessage, la cuál es una clase derivada de MailMessage y se establecen todos sus parámetros en el constructor.

public EMailMessage (string subject,string fromField,List to,string body,
                       bool isBodyHtml)
 {
 Subject = subject;
 From = new MailAddress(fromField);
 foreach(string item in to) To.Add(new MailAddress(item));
 IsBodyHtml = isBodyHtml;
 if(IsBodyHtml)
  Body = GetHTMLContent(body);
 else
  Body = body;
 }

Como segundo paso, el envió del mensaje mediante un servidor SMTP. La clase Sendmail se ocupa de esta responsabilidad solicitando los parámetros de configuración del Server.

public SendMail(string server,int port,bool enableSSL){
 Server = server; 
 Port = port;
 EnableSSL = enableSSL;
 }
 public SendMail(string server,int port,bool enableSSL,string username,string password): 
 this(server,port,enableSSL){
 UserName = username;
 Password = password;
 Credentials = true;
 }

Y después envía el mensaje con el siguiente método:

public void Send(MailMessage msg){
 SmtpClient = new SmtpClient(Server,Port);
 SmtpClient.EnableSsl = EnableSSL;
 //DO NOT use: this property throws a Exception
 //SmtpClient.UseDefaultCredentials = true;
 if(Credentials){
 SmtpClient.UseDefaultCredentials = false;
 SmtpClient.Credentials = new NetworkCredential(UserName,Password);
 }
 ServicePointManager.ServerCertificateValidationCallback = 
     delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
     { return true; };
 SmtpClient.Send(msg);
 }

En este método primeramente establecemos la configuración del servidor, indicamos si se usa o no una conexión segura, después en caso de requerir identificación establecemos el usuario y la contraseña, después utilizamos el delegado ServerCertificateValidationCallback de la clase estática ServicePointManager para la validación del certificado del servidor.
Luego de compilar, ejecutamos y probamos la aplicación utilizando el servidor de correo Gmail en cuyo caso establecemos la configuración como: Host: smtp.gmail.com
Port: 587
Username: [user name]@gmail.com
EnableSSL: true

Si el envío resulta exitoso la aplicación nos mostrará el siguiente mensaje:

De forma predeterminada el mensaje se envia en texto plano, para enviar el mensaje en HTML, habilitamos el checkbox para activar la propiedad IsBodyHtml y recibir el mensaje en este formato.

Tambien podemos utilizar un servidor local SMTP en caso de que nuestra distribución OpenSuse tenga instalados Postfix o Sendmail.

En el caso de no usar autentificación existe la propiedad UseDefaultCredentials que funciona en el Framework .NET de Microsoft, no así en el Framework Mono, si la utilizamos, Mono lanzará una excepción como se muestra en la siguiente imagen:

martes, 22 de mayo de 2012

Serialización de Objetos en .NET

Serialización se denomina al proceso de transferir un objeto que se ejecuta en la memoria de un programa hacia un medio de persistencia para conservar su estado y sus datos en ese momento, para deserializarlo o bien volver a recuperarlo cuando se considere conveniente, en algunos casos el mecanismo de serialización/deserialización es más práctico que utilizar las clases readers/writers para persistir.

En .NET existen tres tipos de serialización: Binaria, XML y Soap los cuales nos permiten cierta independencia del medio de transporte. La serialización binaria es la más sencilla, óptima y ofrece un mejor rendimeinto que los otros tipos de serialización, aunque no es recomendada si los objetos serializados requieren ser transportados hacia otros sistemas operativos, lenguajes de programación o arquitecturas que no sean .NET, por lo que para el tema de interoperabilidad las mejores opciones son la serialización de objetos en XML ó SOAP.

La serialización en .NET consiste básicamente en dos responsabilidades: una es la responsabilidad del objeto serializable el cuál indica los miembros a serializar y la otra es la del serializador/deserializador la cuál se encarga de transferir el objeto hacia o desde un medio de persistencia. Supongamos una aplicación encargada de administrar una colección de libros, esta aplicación tiene una clase Author la cuál queremos serializar, primeramente marcamos la clase con el atributo:

[Serializable]
Hay que tener presente que no todas variable de instancia puede ser serializables, por ejemplo los metodos o variables estáticas no lo son, al contrario de los tipos primitivos, los arreglos y los objetos string los cuales son serializables de forma predeterminada. Siempre hay que asegurarse que los objetos y su clase base sean serializables antes de asumir que cualquier tipo de objeto puede ser serializado. Si encontramos o necesitamos que una propiedad del objeto no sea serializable la marcamos con el atributo:
[NonSerialized]
A continuación mostramos el código fuente de una aplicación que muestra la serialización y deserialización binaria de una relación de objetos mediante la utilización de la clase BinaryFormatter. Los archivos que componen la aplicación son: Author, Book , Publisher y la clase principal TestSerialization la cuál implementa todo el código de forma concreta.

La clase Author

La clase Book
La clase Publisher
La clase TestSerialization
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Samples;

namespace Samples{
  public class TestSerialization{
    static FileStream stream = null;
    static BinaryFormatter binaryformatter = new BinaryFormatter();
    static Book b;
    public static int Main(string[] args){
      Console.WriteLine("Enter the Author ");
      Console.Write("Name: ");
      string na = Console.ReadLine();
      Console.Write("Last Name: ");
      string la = Console.ReadLine();
      Console.Write("Organization: ");
      string or = Console.ReadLine();
      Console.Write("Country: ");
      string ac = Console.ReadLine();
      Console.WriteLine("Enter the book");
      Console.Write("Title: ");
      string bt = Console.ReadLine();
      Console.Write("Publication's date: ");
      string pd = Console.ReadLine();
      Console.Write("Number of pages: ");
      string np = Console.ReadLine();
      Console.WriteLine("Enter the publisher");
      Console.Write("Name: ");
      string pn = Console.ReadLine();
      Console.Write("Country: ");
      string pc = Console.ReadLine();
      b = new Book{
 Title = bt,
 Numpages = Convert.ToInt32(np),
 PublicationDate = Convert.ToDateTime(pd),
 Author = new Author{
   Name = na,
   LastName = la,
   Organization = or,
   Country = ac
 },
 Publisher = new Publisher{
   Name = pn,
   Country = pc
 }
      };
      try{
 Console.WriteLine("Serializing ...");
 using(stream = new FileStream("Book.bin",FileMode.OpenOrCreate,FileAccess.Write)){
   binaryformatter.Serialize(stream,b);
 }
 Console.WriteLine("Done.");
 Console.WriteLine("Deserializing ...");
 using(stream = new FileStream("Book.bin",FileMode.Open,FileAccess.Read)){
   b = (Book)binaryformatter.Deserialize(stream);
   Console.WriteLine("======== Get the Author ========");
   Console.WriteLine("Name [{0}]",b.Author.Name);
   Console.WriteLine("Last Name [{0}]",b.Author.LastName);
   Console.WriteLine("Organization [{0}]",b.Author.Organization);
   Console.WriteLine("Country [{0}]",b.Author.Country);
   Console.WriteLine("======== Get the Book ========");
   Console.WriteLine("Title [{0}]",b.Title);
   Console.WriteLine("Numpages [{0}]",b.Numpages);
   Console.WriteLine("Publication's Date [{0}]",b.PublicationDate);
   Console.WriteLine("======== Get the Publisher ========");
   Console.WriteLine("Name [{0}]",b.Publisher.Name);
   Console.WriteLine("Country [{0}]",b.Publisher.Country);
 }
      }catch(SerializationException ex){
 Console.WriteLine(ex.Message);
      }
      return 0;
    }
  }
}

Este ejemplo básicamente crea un grafo de una relación de clases y lo serializa (lo pasa de la memoria hacia un medio de almacenamiento) en un archivo binario e inmediatamente lo deserializa, (del medio de almacenamiento lo trae a la memoria).En todo este proceso (excepto en donde se indique que no) se convierte el objeto Book,sus clases relacionadas y sus miembros en un flujo de bytes hacia el disco duro para posteriormente recuperarlo con el mismo proceso en orden inverso. Todo esto se logra en esencia con las siguientes líneas.Para serializar y deserializar respectivamente:

using(stream = new FileStream("Book.bin",FileMode.OpenOrCreate,FileAccess.Write)){
   binaryformatter.Serialize(stream,b);
 }
using(stream = new FileStream("Book.bin",FileMode.Open,FileAccess.Read)){
   b = (Book)binaryformatter.Deserialize(stream);
}
Al compilar y ejecutar el programa, mediante los siguientes comandos:
$ mcs /t:library Author.cs Book.cs Publisher.cs /out:Samples.dll
$ mcs -r:Samples.dll TestSerialization.cs
$ mono TestSerialization.cs


Mostramos la serialización y deserialización de un grafo de objetos relacionados.

domingo, 29 de abril de 2012

Habilitando contraseñas en Switches y Routers

Una de las recomendaciones minímas de seguridad para switches y routers es la de habilitar un password para el acceso a la consola, al Privileged EXEC mode (modo privilegiado de comandos) y a las terminales virtuales o VTY's. Aunque mostramos los comandos para un switch, estos comandos sirven igualmente para un router.

Para asegurar el Privileged EXEC mode con un password, se ejecutan los siguientes comandos (se muestran en forma abreviada):

SW1> en
SW1# config t
SW1(config)# enable secret [the Password]
SW1(config)# exit
SW1# disable
Siempre se recomienda usar enable secret en lugar de enable password, porque el password se guarda de forma encriptada en la configuración.
Para quitar el password del Privileged EXEC mode se ejecutan los siguientes comandos:
SW1> en
Password: [Teclear the Password]
SW1# config t
SW1(config)# no enable secret 
SW1(config)# exit
SW1# disable

Para asegurar con un password la consola se ejecutan los siguientes comandos:

SW1> en
SW1# config t
SW1(config)# line con 0
SW1(config-line)# password [thePassword]
SW1(config-line)# login
SW1(config-line)# exit
SW1(config)# exit
SW1# disable
Para quitar el password de la consola se ejecutan los siguientes comandos:
User Access Verification

Password: [Teclear the Password]

SW1> en
SW1# config t
SW1(config)# line con 0
SW1(config-line)# no login
SW1(config-line)# exit
SW1(config)# exit
SW1# disable

Para asegurar las terminales virtuales con un password se ejecutan los siguientes comandos:

SW1>en
SW1# conf t
SW1(config)# line vty 0 15
SW1(config-line)# password [thePassword]
SW1(config-line)# login
SW1(config-line)# exit
Para quitar el password de las terminales virtuales se ejecutan los siguientes comandos:
SW1>en
SW1# conf t
SW1(config)# line vty 0 15
SW1(config-line)# no login
SW1(config-line)# exit

Es importante tener unas buenas políticas de contraseñas, por ejemplo no usar el mismo password para todos los switches o routers, ni tampoco usar password fáciles de adivinar como: cisco, Cisco123, router, etc.

sábado, 31 de marzo de 2012

Entendiendo la clase Process de .NET

La definición clásica de proceso [1] nos dice que un proceso "es un programa en ejecución" también nos señala que un proceso es más que un programa, ya que por programa se refiere únicamente al conjunto de instrucciones que se van ejecutando dentro del proceso, por lo que subraya que un proceso es una entidad activa que tiene un contador de programa (program counter), un conjunto de recursos asociados y ese conjunto de instrucciones que están representadas por el programa.
Un proceso tiene los siguientes estados durante su ejecución:

  1. Nuevo (New): El proceso se ha creado
  2. En ejecución (Running): Las instrucciones están siendo ejecutadas.
  3. En espera (Waiting): El proceso esta en espera de algún evento ocurra.
  4. Listo (Ready): El proceso esta en espera de una asignación del procesador.
  5. Terminado (Terminated): El proceso ha terminado su ejecución.

.NET proporciona la clase Process que representa un proceso del sistema operativo con todas sus propiedades y operaciones, esta clase se encuentra dentro del ensamblado System.Diagnostics.
A continuación mostramos el listado correspondiente a un proyecto GTK# de MonoDevelop, este programa sencillo muestra el uso de esta clase.


Primeramente obtenemos el nombre del host del cuál obtendremos sus procesos en ejecucción, este nombre lo asignamos a una variable de tipo string para después mostrarlo en una etiqueta de la interfaz gráfica


lbMachineName.Text = machineName = System.Environment.MachineName;

Teniendo el nombre del host, entonces con el metódo estático GetProcesses de la clase Process obtenemos un arreglo de procesos representados mediante la clase Process, este arreglo sera nuestro model (Model) para mostrar en el control GTK# TreeView de la interfaz gráfica, a continuación el código con el cuál realizamos esta función:

var resp = (from p in Process.GetProcesses(machineName)
where p.Id > 100
orderby p.ProcessName ascending select p);
Process[] arrProcesses = resp.ToArray();

Por útimo obtemos la información detallada del proceso, con el metódo estático GetProcessById un metódo que recibe como argumento un entero representando el pid (process identifier), esto se realiza con el código siguiente:


TreePath[] selected_paths = trProcessList.Selection.GetSelectedRows ();
TreeIter iter;
int pid;
foreach (TreePath p in selected_paths)
{
if (store.GetIter (out iter, p)) {
pid = Convert.ToInt32(store.GetValue(iter,1));
Process process = Process.GetProcessById(pid);
lbVirtualMemory.Text = Convert.ToString(process.WorkingSet64 / 1024) + " Kb";
lbPriority.Text = process.PriorityClass.ToString();
lbStartProcessorTime.Text = process.StartTime.ToString("HH:mm:ss.ffff");
}
}
Las siguientes imagenes muestran el programa en ejecucción



[1]Basado en el libro “Operating System Concepts”, Silberschatz Abraham, Baer Galvin Peter, Greg Gagne; John Wiley & Sons inc, 7 edición, 2005, Chapter 3

lunes, 19 de marzo de 2012

Flujos de entrada y salida en .NET

Todos los programas de computadora hacen uso de dispositivos de entrada y salida, los más clásicos para estos fines son el teclado (entrada estándar) y la consola salida (salida estándar).
.NET hace una abstracción de cada uno de estos dispositivos con el modelo de flujos (bajo el (concepto) de flujo), haciendo la analogía como si se tratase de una corriente de agua, solo que para el caso de las aplicaciones .NET se trata de corrientes de bytes. En resumen la comunicación entre .NET y el hardware de la computadora se realiza mediante el concepto de flujos.
La clase base para el tratamiento de estos flujos es la clase Stream, de la cuál derivan los flujos necesarios para la comunicación de los programas hacia el respaldo (persistencia) o en términos de .NET el Backing Store. .NET a diferencia de Java utiliza la misma clase para los flujos de entrada como para los de salida. A continuación la lista de los flujos básicos de entrada/salida:



  • FileStream: hacia archivos de disco

  • MemoryStream: hacia estructuras de memoria

  • NetworkStream: hacia conexiones de red


A continuación, mostramos como ejemplo un proyecto GTK# realizado en MonoDevelop cuyo diseño de pantalla se muestra en la siguiente imagen:


Ahora se muestra el listado que utiliza algunos de estos conceptos para leer un archivo binario .mp3 y obtener la información correspondiente al los datos del ID3 tag en estos archivos.


Primeramente en el código utilizamos las clases FileStream, BinaryReader, FileInfo del ensamblado System.IO, el cuál utilizamos en el encabezado:


using System.IO;

Con las siguientes lineas utilizamos la clase FileInfo para obtener algunas propiedades acerca del archivo, propiedades que mostramos en las etiquetas de la interfaz.

file = new FileInfo(fc.Filename);
int size = Convert.ToInt32(file.Length);
lbFileName.Text = file.Name;
lbWriteTime.Text = file.LastWriteTime.ToString();
lbFileSize.Text = size.ToString();

Ahora con el siguiente código implementamos toda la funcionalidad para la lectura de un archivo binario, utilizando un FileStream hacia un archivo creando un flujo de bytes como entrada que dirigimos hacia un BinaryReader (Lector binario) con el cuál utilizando el metódo ReadBytes para leer un arreglo de 128 bytes que son los bytes que contienen los datos del ID3 tag.

FileStream fis = new FileStream(file.FullName,FileMode.Open,
FileAccess.Read,FileShare.Read);
using(BinaryReader reader = new BinaryReader(fis))
{
int offset = size - 128;
reader.BaseStream.Position = offset;
b = reader.ReadBytes(128);
}

Una vez obtenido el arreglo de bytes,lo convertimos a caracteres, para que utilicemos la longitud y la posición correcta de cada dato según el estándar ID3, esto se logra con el siguiente código:

char[] c = new char[128];
for(int i = 0;i < b.Length;i++)
c[i] = (char)b[i];
string strTag = new string(c,0,3);
if(strTag.Equals("TAG")){
PutMsg("File loaded");
txtTitle.Text = new string(c,3,30);
txtArtist.Text = new string(c,33,30);
txtAlbum.Text = new string(c,63,30);
txtYear.Text = new string(c,93,4);
txtComments.Buffer.Text = new string(c,97,30);
}

Una vez compilada la aplicación, al ejecutarse utilizaremos el botón "open" para seleccionar un archivo mp3 del sistema de archivos.


Una vez que el archivo ha sido cargado se mostrará la información correspondiente: