<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3398533864216934520</id><updated>2012-01-25T15:51:27.587-08:00</updated><category term='Opciones'/><category term='Visual Studio'/><category term='WebService'/><category term='Microsoft'/><category term='Path'/><category term='Cast'/><category term='Cursos online'/><category term='Portapapeles'/><category term='Control'/><category term='UI'/><category term='Utilidades'/><category term='Recursividad'/><category term='Threads'/><category term='DataTable'/><category term='Imprimir'/><category term='Confirmación'/><category term='IDE'/><category term='My.Computer'/><category term='ASP.NET'/><category term='List(Of T)'/><category term='Logs'/><category term='Extension Methods'/><category term='Eventos'/><category term='System.IO'/><category term='WinForms'/><category term='.net framework'/><category term='LINQ'/><category term='Clipboard'/><category term='EventLog'/><category term='Propiedades'/><category term='PDF'/><category term='Registro de Windows'/><category term='NumericUpDown'/><category term='Tipos Anónimos'/><category term='Shortcuts'/><category term='Tips'/><category term='Generics'/><category term='IIS'/><category term='Microsoft.Win32'/><category term='Dialogos'/><category term='Delegates'/><category term='LinkLabel'/><category term='C#'/><category term='System.Diagnostics'/><category term='Exportar'/><category term='Servicios de Windows'/><category term='Componentes'/><category term='Process'/><category term='Aplicaciones de Consola'/><category term='VB.Net'/><category term='Patrones'/><category term='Miembros de'/><category term='Enlaces'/><category term='Ejemplos'/><category term='Invoke'/><category term='ErrorProvider'/><category term='Ayuda'/><title type='text'>Aprendiendo.NET</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-162141947856203867</id><published>2010-09-17T06:38:00.000-07:00</published><updated>2010-09-17T06:58:06.691-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='Servicios de Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Como hacer un servicio de Windows auto instalable</title><content type='html'>Todos nos hemos encontrado en la situación de tener que instalar un servicio, y utilizar el comando &lt;strong&gt;installutil.exe&lt;/strong&gt;, pero por qué no ahorrarnos un paso y hacer que el servicio sea auto instalable?&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh6.ggpht.com/_61c_vpZbWyk/TJNxLEYmpII/AAAAAAAAA2c/y0H5E82qd4w/s288/servicios-de-windows.png" style="text-align:center" /&gt;&lt;br /&gt;&lt;br /&gt;Este tip no tiene mayor secreto, simplemente es &lt;strong&gt;un atajo al installutil.exe dentro del ejecutable de nuestro servicio&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Lo que haremos será ir a la clase Program.cs en C# o Módulo Main.vb eb VB y modificar el método main de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;static class Program&lt;br /&gt;    {&lt;br /&gt;        /// &lt;summary&gt;&lt;br /&gt;        /// The main entry point for the application.&lt;br /&gt;        /// &lt;/summary&gt;&lt;br /&gt;        static void Main(String[] args)&lt;br /&gt;        {&lt;br /&gt;            if (args.Length &gt; 0)&lt;br /&gt;            {&lt;br /&gt;                switch (args[0])&lt;br /&gt;                {&lt;br /&gt;                    case "/install":&lt;br /&gt;                        install();&lt;br /&gt;                        break;&lt;br /&gt;                    case "/uninstall":&lt;br /&gt;                        uninstall();&lt;br /&gt;                        break;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                ServiceBase[] ServicesToRun;&lt;br /&gt;                ServicesToRun = new ServiceBase[] { new SecurityProviderService() };&lt;br /&gt;                ServiceBase.Run(ServicesToRun);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Lo que hicimos fue agregarle a nuestro ejecutable la posibilidad de recibir parámetros, en éste caso /install o /uninstall, sólo nos resta crear los métodos para ejecutar éstas acciones y listo.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        // Devuelve la ruta a installutil.exe&lt;br /&gt;        private static String installUtill()&lt;br /&gt;        {&lt;br /&gt;            return System.IO.Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "installutil.exe");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void uninstall()&lt;br /&gt;        {&lt;br /&gt;            if (System.IO.File.Exists(installUtill()))&lt;br /&gt;            {&lt;br /&gt;                System.Diagnostics.Process.Start(installUtill(), String.Format("/u \"{0}\"", System.Reflection.Assembly.GetExecutingAssembly().Location));&lt;br /&gt;                System.Diagnostics.Trace.WriteLine("Service uninstalled.");&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;                throw new System.IO.FileNotFoundException("InstallUtil.exe not found");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static void install()&lt;br /&gt;        {&lt;br /&gt;            if (System.IO.File.Exists(installUtill()))&lt;br /&gt;            {&lt;br /&gt;                System.Diagnostics.Process.Start(installUtill(), String.Format("\"{0}\"", System.Reflection.Assembly.GetExecutingAssembly().Location));&lt;br /&gt;                System.Diagnostics.Trace.WriteLine("Service installed.");&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;                throw new System.IO.FileNotFoundException("InstallUtil.exe not found");&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Muy simple, ahora cuando necesitemos instalar nuestro servicio simplemente lo haremos desde una consola ejecutando &lt;code&gt;NombreDelServicio.exe /install&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-162141947856203867?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/162141947856203867/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=162141947856203867' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/162141947856203867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/162141947856203867'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2010/09/como-hacer-un-servicio-de-windows-auto.html' title='Como hacer un servicio de Windows auto instalable'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_61c_vpZbWyk/TJNxLEYmpII/AAAAAAAAA2c/y0H5E82qd4w/s72-c/servicios-de-windows.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-835685436035725238</id><published>2010-08-16T05:29:00.000-07:00</published><updated>2010-08-16T05:39:06.025-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PDF'/><category scheme='http://www.blogger.com/atom/ns#' term='Ayuda'/><category scheme='http://www.blogger.com/atom/ns#' term='Shortcuts'/><title type='text'>Referencia de atajos de teclado para Visual Studio 2010</title><content type='html'>Desde la web de Microsoft, nos ofrecen una serie de archivos PDF con los &lt;strong&gt;atajos de teclado para Visual Studio 2010&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_61c_vpZbWyk/TGkxIM4JC0I/AAAAAAAAA0Y/C0BGRC0M5Kc/s1600/VS-2010-CSharp-Shortcuts.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 247px;" src="http://1.bp.blogspot.com/_61c_vpZbWyk/TGkxIM4JC0I/AAAAAAAAA0Y/C0BGRC0M5Kc/s320/VS-2010-CSharp-Shortcuts.jpg" border="0" alt="C# shortcuts para Visual Studio 2010" id="BLOGGER_PHOTO_ID_5505986036402555714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=92CED922-D505-457A-8C9C-84036160639F&amp;displaylang=en" target="_blank" title="Atajos de teclado para Visual Studio 2010"&gt;Descargar&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-835685436035725238?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/835685436035725238/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=835685436035725238' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/835685436035725238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/835685436035725238'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2010/08/referencia-de-atajos-de-teclado-para.html' title='Referencia de atajos de teclado para Visual Studio 2010'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_61c_vpZbWyk/TGkxIM4JC0I/AAAAAAAAA0Y/C0BGRC0M5Kc/s72-c/VS-2010-CSharp-Shortcuts.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-7649088260009643063</id><published>2009-10-14T11:24:00.000-07:00</published><updated>2009-10-14T11:51:10.766-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cast'/><category scheme='http://www.blogger.com/atom/ns#' term='Control'/><category scheme='http://www.blogger.com/atom/ns#' term='Propiedades'/><category scheme='http://www.blogger.com/atom/ns#' term='NumericUpDown'/><title type='text'>Como acceder a la propiedad Text de un control NumericUpDown</title><content type='html'>&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 314px; height: 152px;" src="http://3.bp.blogspot.com/_61c_vpZbWyk/StYdCTU9HeI/AAAAAAAAAqc/6RAksMBGxMY/s320/NumericUpDown-problema-propiedad-Text.png" border="0" alt="Problema con NumericUpDown y la propiedad Text"id="BLOGGER_PHOTO_ID_5392529529207856610" /&gt;&lt;br /&gt;&lt;br /&gt;Hoy me encontré con un problemita trabajando sobre un formulario que contiene varios &lt;strong&gt;NumericUpDown&lt;/strong&gt;. El tema es que se podía seleccionar un valor, luego borrarlo y el sistema no hacía una validación que indicara al usuario que debía introducir un valor.&lt;br /&gt;&lt;br /&gt;Al empezar a hacer pruebas noté que el texto queda vacío, pero el valor no cambia, o sea que si el &lt;strong&gt;NumericUpDown&lt;/strong&gt; tiene un valor de 75 y le borramos el texto, al acceder a la propiedad Value del mismo, ésta nos devuelve 75.&lt;br /&gt;&lt;br /&gt;El problema para solucionar ese bug me lo encontré cuando intenté acceder a la propiedad Text, para chequear que la misma no contenga un String vacío... Oh sorpresa, no se puede acceder a esa propiedad porque es privada!!&lt;br /&gt;&lt;br /&gt;Para acceder a la propiedad Text aprovecharemos de la herencia de esta clase, &lt;strong&gt;NumericUpDown&lt;/strong&gt; es una subclase de &lt;strong&gt;Control&lt;/strong&gt;, entonces al hacer un cast podemos acceder a la propiedad Text para hacer el chequeo.&lt;br /&gt;Esto nos permite varias soluciones posibles, una que me pareció bastante elegante fue asignar un event handler, o manejador de eventos al evento TextChanged, al cual también accederemos mediante un cast a &lt;strong&gt;Control&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Solución:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load&lt;br /&gt;  For Each c As Control In Me.Controls&lt;br /&gt;    If TypeOf c Is NumericUpDown Then&lt;br /&gt;      AddHandler c.TextChanged, AddressOf NumericUpDownControls_TextChanged&lt;br /&gt;    End If&lt;br /&gt;  Next&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Private Sub NumericUpDownControls_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs)&lt;br /&gt;  If CType(sender, Control).Text = String.Empty Then&lt;br /&gt;    CType(sender, Control).Text = CType(sender, NumericUpDown).Value.ToString()&lt;br /&gt;  End If&lt;br /&gt;End Sub&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Otra posible solución, más eficiente desde el punto de vista de reusabilidad sería crear un control que herede de &lt;strong&gt;NumericUpDown&lt;/strong&gt; y ya implemente de por si este comportamiento; que a mi entender es una falta de parte del equipo que desarrolló el control.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-7649088260009643063?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/7649088260009643063/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=7649088260009643063' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/7649088260009643063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/7649088260009643063'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/10/como-acceder-la-propiedad-text-de-un.html' title='Como acceder a la propiedad Text de un control NumericUpDown'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_61c_vpZbWyk/StYdCTU9HeI/AAAAAAAAAqc/6RAksMBGxMY/s72-c/NumericUpDown-problema-propiedad-Text.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-8732831139527523242</id><published>2009-06-08T07:21:00.000-07:00</published><updated>2009-06-08T07:28:41.681-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Opciones'/><category scheme='http://www.blogger.com/atom/ns#' term='IDE'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Deshabilitar el Cortar / Copiar de líneas vacías en Visual Studio</title><content type='html'>Un comportamiento muy molesto de &lt;strong&gt;Visual Studio&lt;/strong&gt; es cuando por error copias o cortas una línea vacía, o sin seleccionar nada... hasta hace un tiempo pensaba que era el comportamiento normal del &lt;strong&gt;IDE&lt;/strong&gt;, pero un día hurgando en la &lt;strong&gt;ventana de opciones&lt;/strong&gt; me encontré con que se puede desactivar.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 400px; height: 237px;" src="http://2.bp.blogspot.com/_61c_vpZbWyk/Si0e62WPUmI/AAAAAAAAAho/LRxB1n78Xs4/s400/visual-studio-no-copiar-lineas-vacias.jpg" border="0" alt="Evitar copiar sin seleccionar en Visual Studio"id="BLOGGER_PHOTO_ID_5344962329128686178" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-8732831139527523242?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/8732831139527523242/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=8732831139527523242' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8732831139527523242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8732831139527523242'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/06/deshabilitar-el-cortar-copiar-de-lineas.html' title='Deshabilitar el Cortar / Copiar de líneas vacías en Visual Studio'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_61c_vpZbWyk/Si0e62WPUmI/AAAAAAAAAho/LRxB1n78Xs4/s72-c/visual-studio-no-copiar-lineas-vacias.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-6427161715193556052</id><published>2009-05-07T11:39:00.000-07:00</published><updated>2009-05-07T11:47:53.041-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataTable'/><category scheme='http://www.blogger.com/atom/ns#' term='Extension Methods'/><category scheme='http://www.blogger.com/atom/ns#' term='Exportar'/><category scheme='http://www.blogger.com/atom/ns#' term='Generics'/><category scheme='http://www.blogger.com/atom/ns#' term='List(Of T)'/><title type='text'>Extendiendo la clase List(Of T)</title><content type='html'>Hoy necesité &lt;strong&gt;exportar el contenido de una Lista a un DataTable&lt;/strong&gt;, entonces pensé:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;Crear una tabla con la estructura necesaria&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Recorrer la lista secuencialmente y agregar filas a la tabla&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Pero pensando como programador, se me ocurrió que seguramente volviera a necesitar esta función y posiblemente la necesitaría con diferentes tipos de listas.&lt;br /&gt;&lt;br /&gt;Como era lógico, pensé en &lt;strong&gt;Generics&lt;/strong&gt;, entonces me creé una función que recibe una &lt;strong&gt;System.Collections.Generic.List(Of T)&lt;/strong&gt; y devuelve un &lt;strong&gt;System.Data.DataTable&lt;/strong&gt; con la siguiente firma:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Public Function ListToDataTable(Of T)(List As System.Collections.Generic.List(Of T)) As System.Data.DataTable&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;después creé toda la lógica utilizando &lt;strong&gt;System.Reflection&lt;/strong&gt; para examinar las propiedades, y aprovechando los &lt;strong&gt;CustomAttributes&lt;/strong&gt; para poder ocultar propiedades, entonces para hacer un Test, hice una clase con la siguiente estructura:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Public Class MiClase&lt;br /&gt;&lt;br /&gt;    Private mId As Integer&lt;br /&gt;    Private mNombre As String&lt;br /&gt;    Private mCantidad As Integer&lt;br /&gt;&lt;br /&gt;    &lt;System.ComponentModel.Browsable(False)&gt; _&lt;br /&gt;    Public Property Id() As Integer&lt;br /&gt;        Get&lt;br /&gt;            Return mId&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Integer)&lt;br /&gt;            mId = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Property Nombre() As String&lt;br /&gt;        Get&lt;br /&gt;            Return mNombre&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As String)&lt;br /&gt;            mNombre = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Property Cantidad() As Integer&lt;br /&gt;        Get&lt;br /&gt;            Return mCantidad&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Integer)&lt;br /&gt;            mCantidad = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Sub New()&lt;br /&gt;&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public Sub New(ByVal Id As Integer, ByVal Nombre As String, ByVal Cantidad As Integer)&lt;br /&gt;        mId = Id&lt;br /&gt;        mNombre = Nombre&lt;br /&gt;        mCantidad = Cantidad&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;como ven, la propiedad Id tiene un CustomAttribute, el &lt;strong&gt;System.ComponentModel.BrowsableAttribute&lt;/strong&gt; seteado con el valor False, o sea que esa propiedad estaría excluida de la exportación.&lt;br /&gt;&lt;br /&gt;Todo muy lindo, funcionó a la perfección... pero se me ocurrió algo mejor... usar &lt;strong&gt;Extension Methods&lt;/strong&gt; o &lt;strong&gt;métodos de extensión&lt;/strong&gt;, esa nueva posibilidad que nos brinda el .Net Framework 3.5 de extender clases sin la necesidad de tener el código fuente de la misma.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 320px; height: 200px;" src="http://3.bp.blogspot.com/_61c_vpZbWyk/SgMsAndnrLI/AAAAAAAAAd0/kWq4innID8g/s320/generic-list-extension-methods.png" border="0" alt="Usando extension methods sobre la clase System.Collections.Generic.List(Of T)"id="BLOGGER_PHOTO_ID_5333154772841639090" /&gt;&lt;br /&gt;&lt;br /&gt;Entonces creé un módulo llamado ListExtension y le asigné el mismo Namespace de la lista, &lt;strong&gt;System.Collections.Generic&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Imports System.Reflection&lt;br /&gt;Imports System.ComponentModel&lt;br /&gt;Imports System.Runtime.CompilerServices&lt;br /&gt;&lt;br /&gt;Namespace System.Collections.Generic&lt;br /&gt;    Module ListExtension&lt;br /&gt;        ''' &lt;summary&gt;&lt;br /&gt;        ''' Gets a Datatable with all Browsable properties of T as columns containing all Items in the List.&lt;br /&gt;        ''' &lt;/summary&gt;&lt;br /&gt;        ''' &lt;typeparam name="T"&gt;&lt;/typeparam&gt;&lt;br /&gt;        ''' &lt;param name="List"&gt;System.Collections.Generic.List(Of T)&lt;/param&gt;&lt;br /&gt;        ''' &lt;returns&gt;System.Data.DataTable&lt;/returns&gt;&lt;br /&gt;        ''' &lt;remarks&gt;http://aprendiendonet.blogspot.com&lt;/remarks&gt;&lt;br /&gt;        &lt;Extension()&gt; _&lt;br /&gt;        Public Function ToDataTable(Of T)(ByVal List As List(Of T)) As DataTable&lt;br /&gt;            Dim dt As New DataTable()&lt;br /&gt;&lt;br /&gt;            Dim tipo As Type = GetType(T)&lt;br /&gt;            Dim members As MemberInfo() = tipo.GetMembers() ' Obtenemos todos los Miembros de la clase correspondiente al tipo T&lt;br /&gt;&lt;br /&gt;            For Each m As MemberInfo In members&lt;br /&gt;                If m.MemberType = MemberTypes.Property Then ' Sólo nos interesan las propiedades&lt;br /&gt;                    Dim skip As Boolean = False&lt;br /&gt;&lt;br /&gt;                    Dim atts As Object() = m.GetCustomAttributes(GetType(BrowsableAttribute), False) ' Chequeamos si tiene BrowsableAttribute&lt;br /&gt;                    If atts.Length &gt; 0 Then&lt;br /&gt;                        If CType(atts(0), BrowsableAttribute).Browsable = False Then&lt;br /&gt;                            skip = True ' Seteamos un flag para no agregar la columna&lt;br /&gt;                        End If&lt;br /&gt;                    End If&lt;br /&gt;&lt;br /&gt;                    If Not skip Then&lt;br /&gt;                        Dim c As DataColumn = Nothing&lt;br /&gt;                        Try&lt;br /&gt;                            c = New DataColumn(m.Name, CType(m, PropertyInfo).PropertyType) ' Nueva columna con el nombre de la propiedad y el tipo de la misma&lt;br /&gt;                        Catch ex As Exception&lt;br /&gt;                            c = New DataColumn(m.Name, GetType(String)) ' En caso de error intento crearla como String&lt;br /&gt;                        End Try&lt;br /&gt;                        dt.Columns.Add(c)&lt;br /&gt;                    End If&lt;br /&gt;                End If&lt;br /&gt;            Next&lt;br /&gt;&lt;br /&gt;            For Each itm As T In List ' Recorro la lista y agrego una fila por cada item de la misma&lt;br /&gt;                Dim r As DataRow = dt.NewRow()&lt;br /&gt;                For Each c As DataColumn In r.Table.Columns&lt;br /&gt;                    Dim aux As MemberInfo() = tipo.GetMember(c.ColumnName)&lt;br /&gt;                    If aux.Length &gt; 0 Then&lt;br /&gt;                        r(c.ColumnName) = CType(aux(0), PropertyInfo).GetValue(itm, Nothing)&lt;br /&gt;                    End If&lt;br /&gt;                Next&lt;br /&gt;                dt.Rows.Add(r)&lt;br /&gt;            Next&lt;br /&gt;&lt;br /&gt;            Return dt&lt;br /&gt;        End Function&lt;br /&gt;&lt;br /&gt;    End Module&lt;br /&gt;End Namespace&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Entonces ahora en toda mi solución tengo la posibilidad de exportar mis Listas a DataTable con tan solo llamar a este &lt;strong&gt;método de extensión&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Dim auxDT as DataTable = miLista.ToDataTable()&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-6427161715193556052?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/6427161715193556052/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=6427161715193556052' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/6427161715193556052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/6427161715193556052'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/05/extendiendo-la-clase-listof-t.html' title='Extendiendo la clase List(Of T)'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_61c_vpZbWyk/SgMsAndnrLI/AAAAAAAAAd0/kWq4innID8g/s72-c/generic-list-extension-methods.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-7067656320652659176</id><published>2009-04-29T12:49:00.000-07:00</published><updated>2009-04-29T12:55:10.595-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EventLog'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='System.Diagnostics'/><category scheme='http://www.blogger.com/atom/ns#' term='Logs'/><title type='text'>Como dejar un log en el Visor de Sucesos de Windows</title><content type='html'>&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 400px; height: 195px;" src="http://3.bp.blogspot.com/_61c_vpZbWyk/SfivoZJXkaI/AAAAAAAAAdI/n2usxuXc_Uk/s400/visor-de-sucesos-vbnet.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5330203267472789922" /&gt;&lt;br /&gt;Todos hemos visto el &lt;strong&gt;Visor de Sucesos&lt;/strong&gt; de Windows, y a veces es una buena alternativa para guardar registros de nuestras aplicaciones, ya que nos evita el tener que definirnos una estructura de logs.&lt;br /&gt;&lt;br /&gt;Suele ser muy útil cuando desarrollamos un &lt;strong&gt;Servicio de Windows&lt;/strong&gt; y queremos llevar registro de excepciones o ciertas situaciones... por eso el ejemplo de hoy se trata de crear un log para nuestra aplicación utilizando la clase &lt;strong&gt;EventLog&lt;/strong&gt; del Namespace &lt;strong&gt;System.Diagnostics&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;        Public Sub EscribirEventLog(ByVal Origen As String, ByVal Mensaje As String, ByVal Equipo As String, ByVal TipoDeEntrada As EventTipoDeEntrada)&lt;br /&gt;            If Not EventLog.SourceExists(Origen, Equipo) Then ' Si el origen no existe lo creamos&lt;br /&gt;                EventLog.CreateEventSource(Origen, "GNSys", Equipo)&lt;br /&gt;            End If&lt;br /&gt;&lt;br /&gt;            Dim eLog As New EventLog("GNSys", Equipo, Origen) ' Instanciamos la clase EventLog&lt;br /&gt;            eLog.WriteEntry(Mensaje, TipoDeEntrada, GetSafeShort(111), GetSafeShort(1)) ' Escribimos la entrada&lt;br /&gt;        End Sub&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En el código anterior, (que por cierto es muy sencillo), en la línea que escribe nuestra entrada de log hay datos que deberemos definir en función de nuestras necesidades, veamos la línea y cómo está formada:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;eLog.WriteEntry([Event], LogEntryType, GetSafeShort(111), GetSafeShort(1))&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;La firma del método &lt;code&gt;WriteEntry&lt;/code&gt; es la siguiente:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Public Shared Sub WriteEntry(ByVal source As String, ByVal message As String, ByVal type As System.Diagnostics.EventLogEntryType, ByVal eventID As Integer, ByVal category As Short)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Viendo la siguiente imágen se puede ver qué es cada campo.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_61c_vpZbWyk/SfivogdA-vI/AAAAAAAAAdQ/NN0uAi-aCwM/s1600-h/detalles-de-eventlog-vbnet.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 396px; height: 400px;" src="http://1.bp.blogspot.com/_61c_vpZbWyk/SfivogdA-vI/AAAAAAAAAdQ/NN0uAi-aCwM/s400/detalles-de-eventlog-vbnet.png" border="0" alt="Detalles de una entrada en el Visor de Sucesos"id="BLOGGER_PHOTO_ID_5330203269434243826" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-7067656320652659176?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/7067656320652659176/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=7067656320652659176' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/7067656320652659176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/7067656320652659176'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/04/como-dejar-un-log-en-el-visor-de.html' title='Como dejar un log en el Visor de Sucesos de Windows'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_61c_vpZbWyk/SfivoZJXkaI/AAAAAAAAAdI/n2usxuXc_Uk/s72-c/visor-de-sucesos-vbnet.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-2420598261373788965</id><published>2009-04-28T09:51:00.000-07:00</published><updated>2009-04-28T10:00:32.455-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft.Win32'/><category scheme='http://www.blogger.com/atom/ns#' term='Registro de Windows'/><title type='text'>Como leer y escribir en el Registro de Windows desde una aplicación .NET</title><content type='html'>Para trabajar sobre el registro de Windows utilizaremos las cases &lt;strong&gt;Registry&lt;/strong&gt; y &lt;strong&gt;RegistryKey&lt;/strong&gt; del &lt;strong&gt;Namespace Microsoft.Win32&lt;/strong&gt;. Con éstas 2 clases podremos realizar todas tareas de lectura y escritura en el registro.&lt;br /&gt;Este es un ejemplo muy sencillo, por lo tanto vamos a crear una clave &lt;em&gt;Key&lt;/em&gt;, dentro crearemos un valor &lt;em&gt;Value&lt;/em&gt; luego los eliminaremos. Después leeremos todos los &lt;em&gt;Values&lt;/em&gt; que se encuentren en &lt;code&gt;HKLM\Microsoft\Windows\CurrentVersion\Run&lt;/code&gt;, que son los que indican qué aplicaciones se ejecutan al iniciar Windows para todos los usuarios.&lt;br /&gt;&lt;br /&gt;Debajo de estas líneas está el código, uno de los ejemplos más sencillos para &lt;strong&gt;leer y escribir en el Registro de Windows&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 320px; height: 186px;" src="http://4.bp.blogspot.com/_61c_vpZbWyk/Sfc0jYGZk5I/AAAAAAAAAc4/XQi6KPyLZ1I/s320/trabajar-registro-windows-NET.jpg" border="0" alt="Trabajar con el Registro de Windows en nuestra aplicación .NET"id="BLOGGER_PHOTO_ID_5329786466385630098" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;Imports Microsoft.Win32&lt;br /&gt;Public Class Form1&lt;br /&gt;&lt;br /&gt;    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click&lt;br /&gt;        CrearKey()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub CrearKey()&lt;br /&gt;        Dim KeyPath As String = "Software\Test"&lt;br /&gt;        Registry.CurrentUser.CreateSubKey(KeyPath)&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click&lt;br /&gt;        CrearValue()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub CrearValue()&lt;br /&gt;        Dim KeyPath As String = "Software\Test"&lt;br /&gt;        Dim ValueName As String = "TestValue"&lt;br /&gt;&lt;br /&gt;        Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey(KeyPath, True) ' True indica que se abre para escritura&lt;br /&gt;        If key IsNot Nothing Then ' Si key es Nothing significa que no se encontró&lt;br /&gt;            key.SetValue(ValueName, "Esto es una prueba", RegistryValueKind.String)&lt;br /&gt;        Else&lt;br /&gt;            If MessageBox.Show(String.Format("No se encontró la clave 'HKCU\{0}'. Desea crearla?", KeyPath), "", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then&lt;br /&gt;                CrearKey() ' Creamos la clave y volvemos a intentar crear el valor&lt;br /&gt;                CrearValue()&lt;br /&gt;            End If&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click&lt;br /&gt;        EliminarValue()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub EliminarValue()&lt;br /&gt;        Dim KeyPath As String = "Software\Test"&lt;br /&gt;        Dim ValueName As String = "TestValue"&lt;br /&gt;&lt;br /&gt;        Dim Key As RegistryKey = Registry.CurrentUser.OpenSubKey(KeyPath, True)&lt;br /&gt;&lt;br /&gt;        If Key IsNot Nothing Then&lt;br /&gt;            If Key.GetValueNames().Contains(ValueName) Then ' Buscamos el nombre del valor en la lista de todos los valores de la clave&lt;br /&gt;                Key.DeleteValue(ValueName) ' Borramos el valor&lt;br /&gt;            Else&lt;br /&gt;                MessageBox.Show(String.Format("No se encontró el valor '{0}'.", ValueName))&lt;br /&gt;            End If&lt;br /&gt;        Else&lt;br /&gt;            MessageBox.Show(String.Format("No se encontró la clave 'HKCU\{0}'.", KeyPath))&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click&lt;br /&gt;        EliminarKey()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub EliminarKey()&lt;br /&gt;        Dim KeyPath As String = "Software\Test"&lt;br /&gt;&lt;br /&gt;        Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey(KeyPath)&lt;br /&gt;&lt;br /&gt;        If key IsNot Nothing Then&lt;br /&gt;            Registry.CurrentUser.DeleteSubKey(KeyPath) ' Borramos la sub clave&lt;br /&gt;        Else&lt;br /&gt;            MessageBox.Show(String.Format("No se encontró la clave 'HKCU\{0}'.", KeyPath))&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click&lt;br /&gt;        LeerRegistro()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub LeerRegistro()&lt;br /&gt;        Dim KeyPath As String = "Software\Microsoft\Windows\CurrentVersion\Run"&lt;br /&gt;        Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey(KeyPath, False) ' Abrimos para sólo lectura&lt;br /&gt;&lt;br /&gt;        If key IsNot Nothing Then&lt;br /&gt;            Dim sb As New System.Text.StringBuilder()&lt;br /&gt;&lt;br /&gt;            Dim values As String() = key.GetValueNames() ' Obtenemos los nombres de todos los valores en la key&lt;br /&gt;            For Each value As String In values&lt;br /&gt;                sb.AppendLine(String.Format("{0}   &gt;   {1} ({2})", value, key.GetValue(value), key.GetValueKind(value).ToString()))&lt;br /&gt;            Next&lt;br /&gt;&lt;br /&gt;            Me.TextBox1.Text = sb.ToString() ' Mostramos el resultado en nuestra TextBox Multilínea&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 320px; height: 225px;" src="http://1.bp.blogspot.com/_61c_vpZbWyk/Sfc1BzSA6dI/AAAAAAAAAdA/xhMmEeTCG8w/s320/registry-create-value.png" border="0" alt="Registro de Windows - Aprendiendo.NET"id="BLOGGER_PHOTO_ID_5329786989078178258" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-2420598261373788965?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/2420598261373788965/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=2420598261373788965' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2420598261373788965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2420598261373788965'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/04/como-leer-y-escribir-en-el-registro-de.html' title='Como leer y escribir en el Registro de Windows desde una aplicación .NET'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_61c_vpZbWyk/Sfc0jYGZk5I/AAAAAAAAAc4/XQi6KPyLZ1I/s72-c/trabajar-registro-windows-NET.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-2704036815981744288</id><published>2009-03-09T06:19:00.000-07:00</published><updated>2009-03-09T06:34:31.946-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='WinForms'/><category scheme='http://www.blogger.com/atom/ns#' term='Imprimir'/><title type='text'>Como imprimir un formulario - Microsoft.VisualBasic.PowerPacks.Printing.PrintForm</title><content type='html'>Este código muestra una forma sencilla de &lt;strong&gt;imprimir un formulario&lt;/strong&gt;, para lo cual utilizaremos la clase &lt;strong&gt;PrintForm&lt;/strong&gt;, que se encuentra en el &lt;strong&gt;Namespace Microsoft.VisualBasic.PowerPacks.Printing&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Lo primero que haremos será chequear si tenemos la referencia, para lo cual haremos click con el botón derecho sobre nuestro cuadro de herramientas y en el menú seleccionaremos la opción &lt;em&gt;Choose Items...&lt;/em&gt;, cuando se abra el diálogo para seleccionar las referencias buscaremos la que corresponde al namespace antes mencionado y si no está seleccionada la seleccionaremos en este momento.&lt;br /&gt;&lt;br /&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center; cursor:hand;width: 320px; height: 159px;" src="http://1.bp.blogspot.com/_61c_vpZbWyk/SbUZlXWkuPI/AAAAAAAAAXY/eTrvwdTfh8k/s320/ms-visualbasic-powerpacks-printing-printform.png" border="0"  alt="Microsoft.VisualBasic.PowerPacks.Printing.PrintForm" id="BLOGGER_PHOTO_ID_5311179465267919090" /&gt;&lt;br /&gt;&lt;br /&gt;Puede ocurrir que no se muestre en el cuadro de herramientas, para poder verla haremos un click con el botón derecho sobre el cuadro de herramientas y en el menú seleccionaremos la opción &lt;em&gt;Show All&lt;/em&gt;, que nos agregará varias secciones al cuadro de herramientas, la que buscamos se encuentra bajo el título de &lt;strong&gt;VisualBasic PowerPacks&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Ahora ya podemos arrastrar este componente a nuestro form y crear el siguiente método para poder imprimir el formulario:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;    Private Sub Imprimir()&lt;br /&gt;        PrintForm1.PrintAction = Printing.PrintAction.PrintToPreview ' Crea una vista previa&lt;br /&gt;        ' PrintForm1.PrintAction = Printing.PrintAction.PrintToFile ' Imprime a un archivo&lt;br /&gt;        ' PrintForm1.PrintAction = Printing.PrintAction.PrintToPrinter ' Envía a la impresora&lt;br /&gt;        PrintForm1.Print() ' Finalmente hacemos la impresión&lt;br /&gt;    End Sub&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-2704036815981744288?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/2704036815981744288/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=2704036815981744288' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2704036815981744288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2704036815981744288'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/03/como-imprimir-un-formulario.html' title='Como imprimir un formulario - Microsoft.VisualBasic.PowerPacks.Printing.PrintForm'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_61c_vpZbWyk/SbUZlXWkuPI/AAAAAAAAAXY/eTrvwdTfh8k/s72-c/ms-visualbasic-powerpacks-printing-printform.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-8702937653373845290</id><published>2009-02-27T04:49:00.000-08:00</published><updated>2009-02-27T04:50:26.429-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Portapapeles'/><category scheme='http://www.blogger.com/atom/ns#' term='My.Computer'/><category scheme='http://www.blogger.com/atom/ns#' term='Clipboard'/><title type='text'>Utilizando el portapapeles de Windows en nuestras aplicaciones .NET</title><content type='html'>Para manejar el &lt;strong&gt;portapapeles de Windows&lt;/strong&gt;, el .Net Framework provee la clase &lt;strong&gt;Clipboard&lt;/strong&gt;, del namespace &lt;strong&gt;My.Computer&lt;/strong&gt;la cual posee todo lo necesario para copiar y pegar archivos, textos, imágenes, etc.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Veamos como copiar elementos al portapapeles:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;My.Computer.Clipboard.SetImage(PictureBox1.Image)&lt;/code&gt; - Copia la imagen del picturebox&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;My.Computer.Clipboard.SetText(WebBrowser1.DocumentText, TextDataFormat.Html)&lt;/code&gt; - Copia el código HTML del documento que estamos mostrando en el WebBrowser como texto y setea el formato de éste como HTML.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;My.Computer.Clipboard.SetText(RichTextBox1.Rtf, TextDataFormat.Rtf)&lt;/code&gt; - Ídem anterior pero formato RTF.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;My.Computer.Clipboard.SetText(TextBox1.Text)&lt;/code&gt; - Copia un texto cualquiera, sin formato.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;My.Computer.Clipboard.SetData(MyClassInstance.GetType().Name, MyClassInstance)&lt;/code&gt; - Copia el objeto MyClassInstance al portapapeles.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Ahora tenemos que recuperar los objetos que copiamos al portapapeles:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;PictureBox2.Image = My.Computer.Clipboard.GetImage()&lt;/code&gt; - Recupera la imagen copiada al portapapeles y la setea como Image en el PictureBox2.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;WebBrowser2.DocumentText = My.Computer.Clipboard.GetText(TextDataFormat.Html)&lt;/code&gt; - Obtiene el texto con formato HTML&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;RichTextBox2.Rtf = My.Computer.Clipboard.GetText(TextDataFormat.Rtf)&lt;/code&gt; - Idem anterior con formato RTF.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;TextBox2.Text = My.Computer.Clipboard.GetText()&lt;/code&gt; - Recupera un texto sin formato y lo asigna en TextBox2.Text&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;Dim MyClassNewInstance As MyClass = CType(My.Computer.Clipboard.GetData(GetType(MyClass).Name), MyClass)&lt;/code&gt; - Recupera el objeto de tipo MyClass que copiamos anteriormente.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Para limpiar ó vaciar el portapapeles utilizaremos:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;My.Computer.Clipboard.Clear()&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Algunos controles que podemos hacer sobre la info contenida en el portapapeles:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;If My.Computer.Clipboard.ContainsImage() Then&lt;/code&gt; - Para saber si hay una imagen en el portapapeles&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;If My.Computer.Clipboard.ContainsText(TextDataFormat.Html)&lt;/code&gt; - Para saber si el portapapeles contiene un texto en formato HTML&lt;/li&gt;&lt;br /&gt; &lt;li&gt;&lt;code&gt;If My.Computer.Clipboard.ContainsData(GetType(MyClass).Name) Then&lt;/code&gt; - Comprueba si hay un objeto del tipo MyClass en el portapapeles.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Al preguntar por &lt;code&gt;My.Computer.Clipboard.ContainsText()&lt;/code&gt;, se puede preguntar por varios formatos, los mismos se especifican en el &lt;strong&gt;Enum TextDataFormat&lt;/strong&gt;:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;CommaSeparatedValue&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Html&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Rtf&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Text&lt;/li&gt;&lt;br /&gt; &lt;li&gt;UnicodeText&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Y ese sería un resumen de los usos más frecuentes del portapapeles, aunque también se puede utilizar de varias maneras más, estas son las que consideré más útiles.&lt;br /&gt;&lt;br /&gt;Una aclaración con respecto a copiar y pegar objetos, yo utilicé como nombre del formato el nombre del tipo tal cual se devuelve por &lt;code&gt;GetType().Name&lt;/code&gt;, en ese parámetro se puede escribir cualquier String, pero considero una &lt;strong&gt;buena práctica&lt;/strong&gt; utilizar el nombre del tipo para que al recuperar sepamos qué es lo que estamos buscando.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-8702937653373845290?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/8702937653373845290/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=8702937653373845290' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8702937653373845290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8702937653373845290'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/02/utilizando-el-portapapeles-de-windows.html' title='Utilizando el portapapeles de Windows en nuestras aplicaciones .NET'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-5973483953582035028</id><published>2009-02-11T07:27:00.000-08:00</published><updated>2009-02-11T08:26:16.460-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='System.IO'/><category scheme='http://www.blogger.com/atom/ns#' term='Miembros de'/><category scheme='http://www.blogger.com/atom/ns#' term='Path'/><title type='text'>Trabajando con Archivos y Carpetas: System.IO.Path</title><content type='html'>La clase &lt;strong&gt;System.IO.Path&lt;/strong&gt; provee una serie de métodos para realizar las tareas más comunes a la hora de trabajar con rutas de archivos o directorios, a continuación veremos los métodos de esta clase y para qué sirve cada uno.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.AltDirectorySeparatorChar&lt;/code&gt; : Devuelve el caracter alternativo usado como separador de directorios en el sistema actual. Generalmente "/".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.ChangeExtension("C:\prueba.txt", "xml")&lt;/code&gt; : Cambia la extensión del archivo pasado como primer parámetro, en este ejemplo devuelve C:\prueba.xml.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.Combine("C:\Directorio1\", "prueba.xml")&lt;/code&gt; : Combina ambas rutas para generar una sola. Atención al segundo parámetro porque si empieza con el separador de directorio no funcionará como esperamos.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt; System.IO.Path.DirectorySeparatorChar&lt;/code&gt; : Devuelve el caracter usado como separador de directorios en el sistema actual. Generalmente "\".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetDirectoryName("C:\Directorio1\prueba.txt")&lt;/code&gt; : Devuelve la ruta al directorio según la ruta que recibe por parámetro. En este ejemplo devuelve "C:\Directorio1"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetExtension("C:\Directorio1\prueba.xml")&lt;/code&gt; : Devuelve la extensión del archivo que recibe por parámetro, por el ejemplo ".xml" si el archivo no tiene extensión devuelve "".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetFileName("C:\Directorio1\prueba.xml")&lt;/code&gt; : Devuelve el nombre del archivo especificado en el parámetro sin el resto de la ruta. En este ejemplo devuelve "prueba.xml". Si la ruta especificada termina con el separador de directorios, devuelve "".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetFileNameWithoutExtension("C:\Directorio1\prueba.xml")&lt;/code&gt; : Idem que &lt;code&gt;GetFileName()&lt;/code&gt; pero sin extensión. En el ejemplo "prueba"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetFullPath("C:")&lt;/code&gt; Devuelve la ruta actual sobre la unidad C: Por ejemplo "C:\miApp\bin\Debug&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetFullPath("\prueba1")&lt;/code&gt; : Devuelve la ruta absoluta, toma en cuenta la unidad actual o la ruta actual.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetInvalidFileNameChars()&lt;/code&gt; : Devuelve los caracteres que no pueden formar parte del nombre de un archivo&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetInvalidPathChars()&lt;/code&gt; : Devuleve los caracteres no válidos para una ruta.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetPathRoot("C:\Directorio1\prueba.xml")&lt;/code&gt; : Devuelve la raíz de la ruta especificada, en este caso "C:\"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetRandomFileName()&lt;/code&gt; : Devuelve un nombre randómico para usar como nombre de archivo o directorio.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetTempFileName()&lt;/code&gt; : Devuelve un nombre de archivo temporal, apuntando al directorio especificado en %TEMP%. Por ejemplo "C:\Documents and settings\usuario\Configuración local\Temp\tmp131E.tmp"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.GetTempPath()&lt;/code&gt; : Devuelve la ruta al directorio temporal, siguiendo con el ejemplo anterior, "C:\Documents and settings\usuario\Configuración local\Temp\"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.HasExtension("C:\prueba.xml")&lt;/code&gt; : Devuelve un valor Boolean indicando si la ruta especificada contiene una extensión, en el ejemplo la extensión es ".xml" o sea que devuelve &lt;code&gt;True&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.IsPathRooted("..\Directorio1\prueba.xml")&lt;/code&gt; : Devuelve un valor Boolean indicando si la ruta especificada es absoluta o no, en el ejemplo la ruta es relativa por lo que devuelve &lt;code&gt;False&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.PathSeparator&lt;/code&gt; : Devuelve el separador de rutas, generalmente ";"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;System.IO.Path.VolumeSeparatorChar&lt;/code&gt; : Devuelve el caracter separador de volúmenes, generalmente ":"&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Estos son todos los miembors de la clase &lt;strong&gt;System.IO.Path&lt;/strong&gt; con una breve descripción de cada uno.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-5973483953582035028?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/5973483953582035028/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=5973483953582035028' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/5973483953582035028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/5973483953582035028'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/02/trabajando-con-archivos-y-carpetas.html' title='Trabajando con Archivos y Carpetas: System.IO.Path'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-2879054695998490444</id><published>2009-02-06T04:38:00.000-08:00</published><updated>2009-03-12T23:19:39.752-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IIS'/><category scheme='http://www.blogger.com/atom/ns#' term='ASP.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='WebService'/><title type='text'>Problema al crear un WebService: Failed to access IIS metabase - SOLUCIONADO</title><content type='html'>Intentando crear un &lt;strong&gt;WebService con C#&lt;/strong&gt; me encontré con que cada vez que intentaba ejecutarlo &lt;abbr title="Internet Information Server"&gt;IIS&lt;/abbr&gt; me devolvía el siguiente error: &lt;strong&gt;Failed to access IIS metabase problem&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Busqué por acá y por alla, descargué un código &lt;abbr title="Visual Basic Script"&gt;VBS&lt;/abbr&gt; pero nada... después de probar las mil y una soluciones encontré &lt;strong&gt;la solución definitiva&lt;/strong&gt;, así que decidí publicarla aquí para tenerla siempre a mano y de paso le puede servir a alguien más.&lt;br /&gt;&lt;br /&gt;La &lt;strong&gt;solución&lt;/strong&gt; consiste en abrir una consola, ir al directorio de instalación del Framework, 2.0 en este caso y ejecutar un comando que hará una reinstalación de &lt;strong&gt;ASP.Net&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;div  style="background-color: #000; color: #fff;"&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;C:\&gt; cd WINDOWS\Microsoft.NET\Framework\v2.0.50727&lt;br /&gt;&lt;br /&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\&gt; aspnet_regiis.exe -i&lt;br /&gt;&lt;br /&gt;Start installing ASP.NET (2.0.50727).&lt;br /&gt;......................&lt;br /&gt;Finished installing ASP.NET (2.0.50727).&lt;br /&gt;&lt;br /&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-2879054695998490444?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/2879054695998490444/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=2879054695998490444' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2879054695998490444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2879054695998490444'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/02/problema-al-crear-un-webservice-failed.html' title='Problema al crear un WebService: Failed to access IIS metabase - SOLUCIONADO'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-3643588695110900785</id><published>2009-01-16T04:18:00.001-08:00</published><updated>2009-01-16T12:37:52.960-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delegates'/><title type='text'>MethodInvoker: un delegado simple integrado en el framework</title><content type='html'>Muchas veces necesitamos hacer un &lt;strong&gt;Invoke&lt;/strong&gt;, para las veces que necesitamos invocar un método simple, sin parámetros podemos usar el delegado &lt;strong&gt;MethodInvoker&lt;/strong&gt;, que no es más que un &lt;strong&gt;Delegate sub&lt;/strong&gt; sin parámetros:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Public Delegate Sub MethodInvoker()&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;O sea que si tenemos que utilizarlo podríamos por ejemplo ahcer lo siguiente:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Dim d as MethodInvoker = New MethodInvoker(AddressOf MyProcedimiento)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Simplemente un tip, que me fue útil, ya que hasta que lo encontré declaraba mi propio &lt;strong&gt;delegate&lt;/strong&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-3643588695110900785?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/3643588695110900785/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=3643588695110900785' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/3643588695110900785'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/3643588695110900785'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/01/methodinvoker-un-delegado-simple.html' title='MethodInvoker: un delegado simple integrado en el framework'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-8052798278158189180</id><published>2009-01-14T05:25:00.000-08:00</published><updated>2009-01-14T06:23:29.486-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Enlaces'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><category scheme='http://www.blogger.com/atom/ns#' term='Ejemplos'/><title type='text'>101 Ejemplos de LINQ en VB.Net</title><content type='html'>Un muy buen recurso para aprender a dominar esta gran tecnología, tiene ejemplos de LINQ para SQL, Dataset, XML y Objetos, todos con código fácil de comprender.&lt;br /&gt;&lt;br /&gt;Sin duda es un enlace que vale la pena tener a mano.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Enlace: &lt;a href="http://msdn.microsoft.com/es-es/vbasic/bb688088(en-us).aspx" target="_blank" title="MSDN: 101 ejemplos de LINQ"&gt;http://msdn.microsoft.com/es-es/vbasic/bb688088(en-us).aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-8052798278158189180?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/8052798278158189180/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=8052798278158189180' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8052798278158189180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8052798278158189180'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/01/101-ejemplos-de-linq.html' title='101 Ejemplos de LINQ en VB.Net'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-3883691899106874881</id><published>2009-01-05T16:14:00.000-08:00</published><updated>2009-01-05T16:28:13.216-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delegates'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Recursividad'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='Invoke'/><title type='text'>Recursividad + Invoke = Procedimiento Thread Safe</title><content type='html'>Este es más un apunte que un gran conocimiento, pero puede ayudar a más de uno, la idea es mostrar datos en la &lt;abbr title="User Interface"&gt;UI&lt;/abbr&gt; desde un hilo diferente del principal, por ejemplo: creamos un hilo que se encargue de ir a buscar datos a la &lt;abbr title="Base de Datos"&gt;BDD&lt;/abbr&gt; y los muestre en una grilla cuando los reciba.&lt;br /&gt;&lt;br /&gt;Cuando aprendí a usart &lt;strong&gt;Invoke&lt;/strong&gt; lo que hacía era un método que mostraba los datos en la &lt;abbr title="User Interface"&gt;UI&lt;/abbr&gt; y otro que chequeaba si era necesario utilizar &lt;strong&gt;Invoke&lt;/strong&gt; o no.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Public Sub MostrarDatos(Datos as DataSet)&lt;br /&gt; If Me.InvokeRequired = True Then&lt;br /&gt;  Me.Invoke(New SetDataSource_Delegate(AddressOf SetDataSource), Datos)&lt;br /&gt; Else&lt;br /&gt;  Me.SetDataSource(Datos)&lt;br /&gt; End If&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Private Delegate Sub SetDataSource_Delegate(ds As DataSet)&lt;br /&gt;&lt;br /&gt;Private Sub SetDataSource(ds As DataSet)&lt;br /&gt; Me.DatagridView1.DataSource = ds&lt;br /&gt; Me.DatagridView1.DataMember = ds.Tables(0).TableName&lt;br /&gt;End Sub&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Un tiempo después, como parte de mi eterna búsqueda por escribir mejor código, descubrí que podía simplificar todo eso usando una llamada recursiva y combinando ambos procedimientos en uno solo de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Private Delegate Sub MostrarDatos_Delegate(ds As DataSet)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Public Sub MostrarDatos(Datos as DataSet)&lt;br /&gt; If Me.InvokeRequired = True Then&lt;br /&gt;  Me.Invoke(New MostrarDatos_Delegate(AddressOf MostrarDatos), Datos)&lt;br /&gt; Else&lt;br /&gt;  Me.DatagridView1.DataSource = ds&lt;br /&gt;  Me.DatagridView1.DataMember = ds.Tables(0).TableName&lt;br /&gt; End If&lt;br /&gt;End Sub&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Como se puede ver, el código queda más legible y no deja de ser eficiente, además de ahorrarnos un par de líneas... que en un formulario muy extenso puede ayudarnos bastante.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-3883691899106874881?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/3883691899106874881/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=3883691899106874881' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/3883691899106874881'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/3883691899106874881'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2009/01/recursividad-invoke-procedimiento.html' title='Recursividad + Invoke = Procedimiento Thread Safe'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-8878236110210117936</id><published>2008-12-23T14:57:00.000-08:00</published><updated>2008-12-23T15:16:25.762-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tipos Anónimos'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>Tipos anónimos en .Net</title><content type='html'>Los &lt;strong&gt;tipos anónimos&lt;/strong&gt; son una nueva característica de .Net que utilizada junto a &lt;a href="http://aprendiendonet.blogspot.com/search/label/LINQ"&gt;LINQ&lt;/a&gt; nos brinda grandes ventajas a la hora de escribir nuestro código.&lt;br /&gt;&lt;br /&gt;Primero que nada, deberemos chequear que la opción &lt;strong&gt;Option Infer&lt;/strong&gt; esté habilitada en nuestro proyecto. Para ello iremos a Propiedades del proyecto, en la pestaña Compilación. Por supuesto, al principio podremos tener algunos problemas si también utilizamos la opción &lt;strong&gt;Option Srtict&lt;/strong&gt;, pero es cuestión de costumbre.&lt;br /&gt;&lt;br /&gt;Volviendo a los tipos anónimos, al escribir una sentencia en &lt;strong&gt;LINQ&lt;/strong&gt;, podremos definirnos una variable sin tipo y a pesar de ello tener intellisense.&lt;br /&gt;&lt;br /&gt;Por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;//C#&lt;br /&gt;var hola = from x in myDdatacontext.table1&lt;br /&gt;            where x.id &gt; 20&lt;br /&gt;            select x;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;'VB.Net&lt;br /&gt;&lt;br /&gt;Dim Hola = From x in MyDataContext.Table1 _&lt;br /&gt;            Where x.Id &gt; 20 _&lt;br /&gt;            Select x&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;En realidad nuestras variables Hola, tomarán, en este caso el tipo &lt;strong&gt;IQueriable(Of Table1)&lt;/strong&gt; con lo cual podremos ir navegando a través de los items devueltos por la consulta.&lt;br /&gt;&lt;br /&gt;Suponiendo que Table1 tiene los campos Id, Nombre y Apellido, al escribir &lt;code&gt;x.&lt;/code&gt; el intellisense nos mostrará como proiedades Id, Nombre y Apellido. Y de igual manera, cuando recorremos nuestras variables de tipos anónimos podremos ver el intellisense y acceder a cada propiedad, por ejemplo:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;'VB.Net&lt;br /&gt;For Each x in Hola&lt;br /&gt;     Console.Writeline(String.Format("ID: {0}   Nombre: {1}    Apellido: {2}", x.Id, x.Nombre, x.Apellido))&lt;br /&gt;Next&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Otra forma, sería si quisiéramos devolver el primer elemento del resultado de la consulta, entonces:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;' VB.Net&lt;br /&gt;Return Hola.First&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-8878236110210117936?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/8878236110210117936/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=8878236110210117936' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8878236110210117936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8878236110210117936'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/12/tipos-anonimos-en-net.html' title='Tipos anónimos en .Net'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-9170647819393438948</id><published>2008-11-22T08:39:00.000-08:00</published><updated>2008-11-22T08:47:43.601-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cursos online'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Microsoft Beginner Developer Learning Center</title><content type='html'>Microsoft ha publicado una serie de tutoriales y videos orientados a los nuevos programadores, la idea es enseñarles programación utilizando la serie Express de herramientas para programar .Net.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://msdn.microsoft.com/es-ar/beginner/default.aspx" title="Microsoft Beginner Developer Learning Center"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 97px;" src="http://2.bp.blogspot.com/_61c_vpZbWyk/SSg3amohrNI/AAAAAAAAAQI/4WaWTgrsQaU/s320/microsoft-learning-center.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5271524294023818450" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-9170647819393438948?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/9170647819393438948/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=9170647819393438948' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/9170647819393438948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/9170647819393438948'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/11/microsoft-beginner-developer-learning.html' title='Microsoft Beginner Developer Learning Center'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_61c_vpZbWyk/SSg3amohrNI/AAAAAAAAAQI/4WaWTgrsQaU/s72-c/microsoft-learning-center.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-1594013358803786416</id><published>2008-09-11T07:13:00.000-07:00</published><updated>2008-09-11T07:46:54.345-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cursos online'/><category scheme='http://www.blogger.com/atom/ns#' term='Microsoft'/><title type='text'>Nueva Academia Virtual de Microsoft</title><content type='html'>&lt;a href="http://www.mslatam.com/latam/technet/mva/" title="Click para visitar la Microsoft Virtual Academy"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_61c_vpZbWyk/SMko4gjqqbI/AAAAAAAAAOI/KsnKYryDo1Y/s320/microsoft-virtual-academy.jpg" border="0" alt="Microsoft Virtual Academy - mva"id="BLOGGER_PHOTO_ID_5244768192326969778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Microsoft ha lanzado una nueva &lt;strong&gt;Academia Virtual&lt;/strong&gt; llamada &lt;strong&gt;Microsoft Virtual Academy&lt;/strong&gt;. En la misma presentan cursos para aprender y para actualizarse seleccionando una carrera, igual que una academia real.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;MVA&lt;/strong&gt; es una forma gratuita de capacitarse, puediendo anotarte en varios cursos y carreras, en los cuales irás obteniendo puntos según tu desempeño con los cuales podrás solicitar una membresía, obtener descuentos y varios beneficios más.&lt;br /&gt;&lt;br /&gt;Enlace: &lt;a title="Microsoft Virtual Academy" href="http://www.mslatam.com/latam/technet/mva/"&gt;mva&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-1594013358803786416?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/1594013358803786416/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=1594013358803786416' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/1594013358803786416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/1594013358803786416'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/09/nueva-academia-virtual-de-microsoft.html' title='Nueva Academia Virtual de Microsoft'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_61c_vpZbWyk/SMko4gjqqbI/AAAAAAAAAOI/KsnKYryDo1Y/s72-c/microsoft-virtual-academy.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-4893314423195846888</id><published>2008-08-28T11:50:00.000-07:00</published><updated>2008-08-28T12:12:57.065-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eventos'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Dialogos'/><category scheme='http://www.blogger.com/atom/ns#' term='Confirmación'/><title type='text'>Como mostrar un dialogo de confirmación antes de cerrar la ventana</title><content type='html'>Es lo más común, se va a cerrar una ventana, pero se han editado datos y no se han guardado. En ese caso es muy conveniente utilizar un diálogo con los botones Si, No, Cancelar, los cuales utilizaremos para Guardar los cambios, Descartarlos o cancelar el cerrado de la ventana respectivamente.&lt;br /&gt;&lt;br /&gt;Lo primero que necesitamos es alguna rutina o bandera que nos indique si se han realizado cambios en nuestra ventana, para este ejemplo será una variable de tipo Boolean que se seteará en True cada vez que se modifique un dato.&lt;br /&gt;&lt;br /&gt;Luego escribiremos una rutina en el manejador del evento &lt;strong&gt;FormClosing&lt;/strong&gt; de nuestro Form que mostrará el diálogo y dependiendo de la respuesta del usuario realizará una acción:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing&lt;br /&gt;        If Me.HayCambios Then&lt;br /&gt;            Dim respuesta As DialogResult = MessageBox.Show("Hay cambios pendientes, desea guardarlos antes de salir?", "Cambios pendientes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)&lt;br /&gt;            Select Case respuesta&lt;br /&gt;                Case Windows.Forms.DialogResult.Yes&lt;br /&gt;                    Me.GuardarArchivoComo()&lt;br /&gt;                Case Windows.Forms.DialogResult.No&lt;br /&gt;                    'Descartar los cambios &lt;br /&gt;                Case Windows.Forms.DialogResult.Cancel&lt;br /&gt;                    e.Cancel = True&lt;br /&gt;            End Select&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_61c_vpZbWyk/SLb4flFprvI/AAAAAAAAALw/WgPaaEzLP0k/s1600-h/dialogo-guardar-cambios-pendientes.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_61c_vpZbWyk/SLb4flFprvI/AAAAAAAAALw/WgPaaEzLP0k/s320/dialogo-guardar-cambios-pendientes.png" border="0" alt="Mostrar un diálogo de confirmación antes de cerrar la ventana"id="BLOGGER_PHOTO_ID_5239648437907599090" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-4893314423195846888?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/4893314423195846888/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=4893314423195846888' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/4893314423195846888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/4893314423195846888'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/08/como-mostrar-un-dialogo-de-confirmacin.html' title='Como mostrar un dialogo de confirmación antes de cerrar la ventana'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_61c_vpZbWyk/SLb4flFprvI/AAAAAAAAALw/WgPaaEzLP0k/s72-c/dialogo-guardar-cambios-pendientes.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-4135029212679382813</id><published>2008-08-21T10:59:00.000-07:00</published><updated>2008-08-21T11:11:24.520-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilidades'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Recursividad'/><title type='text'>Función recursiva para limpiar todas las cajas de texto de un Form</title><content type='html'>Siempre es necesario &lt;strong&gt;limpiar cajas de texto&lt;/strong&gt; en un form, por ejemplo después de cierta acción queremos dejar &lt;strong&gt;todas las cajas de texto vacías&lt;/strong&gt;... pues qué mejor que tener una función que las busque todas??&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;Public Sub LimpiarCajas(Controls as System.Windows.Forms.Control.ControlCollection)&lt;br /&gt; For each c as Control in Controls&lt;br /&gt;  If Not c.Controls Is Nothing AndAlso c.Controls.Count &gt; 0 Then&lt;br /&gt;   LimpiarCajas(c.Controls)&lt;br /&gt;  ElseIf c.GetType().Equals(GetType(TextBox)) Then&lt;br /&gt;   CType(c, TextBox).Text = ""&lt;br /&gt;  End If&lt;br /&gt; Next&lt;br /&gt;End Sub&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Este procedimiento puede ser muy útil si se lo ubica en un módulo público, de manera que pueda ser utilizado desde cualquier parte de nuestra aplicación. Aunque si trabajan con el framework 3.5 pueden utilizar &lt;strong&gt;métodos de extensión&lt;/strong&gt; como explican en &lt;a href="http://nuevosprogramadores.com/2008/08/metodos-de-extension-en-vbnet-extension-methods/" title="NuevosProgramadores.com - Métodos de Extensión en VB.NET"&gt;Nuevos Programadores&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-4135029212679382813?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/4135029212679382813/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=4135029212679382813' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/4135029212679382813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/4135029212679382813'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/08/funcion-recursiva-para-limpiar-todas.html' title='Función recursiva para limpiar todas las cajas de texto de un Form'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-569147809155247438</id><published>2008-08-13T10:49:00.000-07:00</published><updated>2008-08-13T12:56:33.548-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Componentes'/><category scheme='http://www.blogger.com/atom/ns#' term='ErrorProvider'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><title type='text'>Como usar ErrorProviders para informar al usuario</title><content type='html'>Un &lt;strong&gt;ErrorProvider&lt;/strong&gt; es un componente que se utiliza para informar al usuario de manera gráfica que ha ocurrido un error, en lo personal me gusta utilizarlo para &lt;strong&gt;mostrar errores de validación&lt;/strong&gt;, por ejemplo cuando el usuario deja en blanco un campo obligatorio, ingresa letras en un campo numérico, etc.&lt;br /&gt;&lt;br /&gt;Lo que hacemos es agregar un &lt;strong&gt;ErrorProvider&lt;/strong&gt; a nuestro Form, desde el tab &lt;em&gt;"Componentes"&lt;/em&gt; nuestra &lt;strong&gt;Toolbox&lt;/strong&gt;. Luego cada vez que hacemos una validación, o cuando deseemos mostrar que hubo un error en cierto control, utilizamos el método &lt;strong&gt;SetError(control as System.Windows.Forms.Control, value as String)&lt;/strong&gt; del objeto &lt;strong&gt;ErrorProvider&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_61c_vpZbWyk/SKM4q4fM7OI/AAAAAAAAAI4/huFlIf1O6yM/s1600-h/toolbox-components-error-provider.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_61c_vpZbWyk/SKM4q4fM7OI/AAAAAAAAAI4/huFlIf1O6yM/s320/toolbox-components-error-provider.png" border="0" alt="Donde ubicar el componente ErrorProvider"id="BLOGGER_PHOTO_ID_5234089501303565538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Por lo tanto una función de validación de 2 campos obligatorios que muestre un &lt;strong&gt;ErrorProvider&lt;/strong&gt; cuando el usuario no complete un campo se vería de la siguiente manera:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;Private Function ValidarDatos() As Boolean&lt;br /&gt; Dim resultado As Boolean = False&lt;br /&gt;&lt;br /&gt; Me.ErrorProvider1.Clear() ' "Limpliamos" el ErrorProvider para que oculte los errores anteriores&lt;br /&gt;&lt;br /&gt; If Me.ComboBox1.SelectedIndex &lt;&gt; -1 Then ' Si seleccionó un item del ComboBox&lt;br /&gt;  If Me.TextBox1.Text &lt;&gt; "" Then ' Si ingresó algo en la TextBox&lt;br /&gt;   'Hacer más validaciones o controles&lt;br /&gt;   resultado = True&lt;br /&gt;  Else&lt;br /&gt;   Me.ErrorProvider1.SetError(Me.TextBox1, "Debe ingresar un valor.") ' Muestra el ErrorProvider asociado al control TextBox1&lt;br /&gt;  End If&lt;br /&gt; Else&lt;br /&gt;  Me.ErrorProvider1.SetError(Me.cmbField1, "Debe seleccionar una propiedad.")&lt;br /&gt; End If&lt;br /&gt; &lt;br /&gt; Return resultado&lt;br /&gt;End Function&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_61c_vpZbWyk/SKMe_NLeGPI/AAAAAAAAAIw/q4tIdgg-jik/s1600-h/ejemplo-error-provider.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_61c_vpZbWyk/SKMe_NLeGPI/AAAAAAAAAIw/q4tIdgg-jik/s320/ejemplo-error-provider.png" border="0" alt="Como usar un ErrorProvider en VB.NET"id="BLOGGER_PHOTO_ID_5234061263153010930" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-569147809155247438?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/569147809155247438/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=569147809155247438' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/569147809155247438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/569147809155247438'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/08/como-usar-errorproviders-para-informar.html' title='Como usar ErrorProviders para informar al usuario'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_61c_vpZbWyk/SKM4q4fM7OI/AAAAAAAAAI4/huFlIf1O6yM/s72-c/toolbox-components-error-provider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-2565207004341041194</id><published>2008-07-30T08:24:00.000-07:00</published><updated>2008-07-30T08:49:54.848-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Delegates'/><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Threads'/><category scheme='http://www.blogger.com/atom/ns#' term='Invoke'/><title type='text'>Inicializar un thread, capturar eventos y usar Invoke (VB.NET)</title><content type='html'>En este ejemplo haremos una aplicación que al presionar un botón creará un thread aparte que &lt;em&gt;"hará algo"&lt;/em&gt;, en este caso no hará nada, solo hará tiempo, pero éste thread lanzará un evento al inicio y otro al fin de su ejecución, nosotros capturaremos esos eventos y los mostraremos en pantalla.&lt;br /&gt;&lt;br /&gt;Como la interfaz de usuario y el thread obviamente pertenecen a distintos hilos, será necesario utilizar un Delegate con el método Invoke del control que utilizaremos, de lo contrario tendremos una &lt;strong&gt;InvalidOperationException &lt;/strong&gt;por &lt;strong&gt;CrossThread&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Lo primero que haremos será asignar los manejadores a los eventos que hemos declarado anteriormente, para eso utilizaremos &lt;strong&gt;AddHandler&lt;/strong&gt; y &lt;strong&gt;AddressOf&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;#Region " Eventos de Thread y sus handlers"&lt;br /&gt;    Private Event InicioThread(ByVal Inico As DateTime)&lt;br /&gt;    Private Event FinThread(ByVal Fin As DateTime)&lt;br /&gt;&lt;br /&gt;    Private Trabajando As Boolean = False&lt;br /&gt;&lt;br /&gt;    Public Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load&lt;br /&gt;        AddHandler InicioThread, AddressOf App_InicioThread&lt;br /&gt;        AddHandler FinThread, AddressOf App_FinThread&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub App_InicioThread(ByVal Inicio As DateTime)&lt;br /&gt;        Trabajando = True&lt;br /&gt;        If TextBox1.InvokeRequired Then&lt;br /&gt;            TextBox1.Invoke(New MostrarEnTextBox_Delegate(AddressOf MostrarEnTextBox), TextBox1, Inicio.ToString())&lt;br /&gt;        Else&lt;br /&gt;            MostrarEnTextBox(TextBox1, Inicio.ToString())&lt;br /&gt;        End If&lt;br /&gt;        If TextBox2.InvokeRequired Then&lt;br /&gt;            TextBox2.Invoke(New MostrarEnTextBox_Delegate(AddressOf MostrarEnTextBox), TextBox2, "Todavía haciendo algo...")&lt;br /&gt;        Else&lt;br /&gt;            MostrarEnTextBox(TextBox2, "Todavía haciendo algo...")&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub App_FinThread(ByVal Fin As DateTime)&lt;br /&gt;        Trabajando = False&lt;br /&gt;        If TextBox2.InvokeRequired Then&lt;br /&gt;            TextBox2.Invoke(New MostrarEnTextBox_Delegate(AddressOf MostrarEnTextBox), TextBox2, Fin.ToString())&lt;br /&gt;        Else&lt;br /&gt;            MostrarEnTextBox(TextBox2, Fin.ToString())&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;#End Region&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Como se puede ver en los maejadores de eventos utilizamos un &lt;strong&gt;Delegate&lt;/strong&gt; del método que inserta el texto en las TextBox, eso es porque requiere parámetros, sino lo hubiésemos podido hacer directamente usando &lt;strong&gt;AddressOf&lt;/strong&gt;.&lt;br /&gt;Así que lo siguiente será crear el método que ingresa texto en las TextBox y su correspondiente &lt;strong&gt;Delegate&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;#Region " Delegate para Invoke "&lt;br /&gt;    Private Delegate Sub MostrarEnTextBox_Delegate(ByVal txt As TextBox, ByVal str As String)&lt;br /&gt;&lt;br /&gt;    Private Sub MostrarEnTextBox(ByVal txt As TextBox, ByVal str As String)&lt;br /&gt;        txt.Text = str&lt;br /&gt;    End Sub&lt;br /&gt;#End Region&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Como dice al principio del post, ésta aplicación tiene un botón que es el que inicia un nuevo hilo, así que agregaremos el botón y en el evento click llamaremos a un método que creará e iniciará el nuevo &lt;strong&gt;Thread&lt;/strong&gt;. Adicionalmente, tenemos un flag para que no permitir la creación de más de un hilo por vez, su valor se cambia con los eventos del &lt;strong&gt;Thread&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click&lt;br /&gt;        If Not Trabajando Then&lt;br /&gt;            InicializarThread()&lt;br /&gt;        Else&lt;br /&gt;            MessageBox.Show("Hay un 'hilo haciendo' algo aún. Intente nuevamente en unos segundos.", "Hilo trabajando", MessageBoxButtons.OK, MessageBoxIcon.Information)&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;#Region " Thread "&lt;br /&gt;    Private Sub InicializarThread()&lt;br /&gt;        Dim t As New Thread(AddressOf HacerAlgo)&lt;br /&gt;        t.Name = "Thread_HacerAlgo"&lt;br /&gt;        t.IsBackground = True&lt;br /&gt;        t.Start()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Private Sub HacerAlgo()&lt;br /&gt;        RaiseEvent InicioThread(DateTime.Now)&lt;br /&gt;        For i As Byte = 0 To 254&lt;br /&gt;            Thread.Sleep(30)&lt;br /&gt;        Next&lt;br /&gt;        RaiseEvent FinThread(DateTime.Now)&lt;br /&gt;    End Sub&lt;br /&gt;#End Region&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_61c_vpZbWyk/SJCNhQi85nI/AAAAAAAAAGc/Ij9eY-Sza-s/s1600-h/ejemplo-threads-vbnet.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_61c_vpZbWyk/SJCNhQi85nI/AAAAAAAAAGc/Ij9eY-Sza-s/s320/ejemplo-threads-vbnet.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228834769893910130" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-2565207004341041194?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/2565207004341041194/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=2565207004341041194' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2565207004341041194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2565207004341041194'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/07/inicializar-un-thread-capturar-eventos.html' title='Inicializar un thread, capturar eventos y usar Invoke (VB.NET)'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_61c_vpZbWyk/SJCNhQi85nI/AAAAAAAAAGc/Ij9eY-Sza-s/s72-c/ejemplo-threads-vbnet.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-2110816156631164221</id><published>2008-07-29T09:33:00.001-07:00</published><updated>2008-07-29T09:49:32.191-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LinkLabel'/><category scheme='http://www.blogger.com/atom/ns#' term='Process'/><title type='text'>Como abrir una web en el navegador por defecto</title><content type='html'>Este es un tip pequeño, simplemente lanzaremos un proceso con la URL a abrir, el Sistema Operativo se encargará de usar la aplicación por defecto para manejar la URL, en nuestro caso un navegador web.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Para probarlo crearemos una nueva aplicación de Winforms y en el form que se crea por defecto agregaremos un LinkLabel, al cual pondremos como texto la URL que queremos abrir, aunque puede ser cualquier texto, en nuestro ejemplo utilizaremos el texto de la etiqueta para ejecutar el proceso.&lt;br /&gt;&lt;a href="http://bp3.blogger.com/_61c_vpZbWyk/SI9JU3dDFHI/AAAAAAAAAGU/Q83Y1EK2eYc/s1600-h/form-abrir-proceso-url-net.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5228478315232433266" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://bp3.blogger.com/_61c_vpZbWyk/SI9JU3dDFHI/AAAAAAAAAGU/Q83Y1EK2eYc/s320/form-abrir-proceso-url-net.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ahora nos resta programar el evento Click del LinkLabel para que lance el proceso:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Private Sub lnkAprendiendoNet_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lnkAprendiendoNet.LinkClicked&lt;br /&gt;&lt;span style="PADDING-LEFT: 22px"&gt;Process.Start(lnkAprendiendoNet.Text)&lt;/span&gt;&lt;br /&gt;End Sub&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-2110816156631164221?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/2110816156631164221/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=2110816156631164221' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2110816156631164221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2110816156631164221'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/07/como-abrir-una-web-en-el-navegador-por.html' title='Como abrir una web en el navegador por defecto'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_61c_vpZbWyk/SI9JU3dDFHI/AAAAAAAAAGU/Q83Y1EK2eYc/s72-c/form-abrir-proceso-url-net.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-7410296309536339331</id><published>2008-07-23T05:35:00.000-07:00</published><updated>2008-07-23T05:39:59.984-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones'/><category scheme='http://www.blogger.com/atom/ns#' term='Delegates'/><category scheme='http://www.blogger.com/atom/ns#' term='Threads'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Invoke'/><title type='text'>Implementación de Singleton y manejo de hilos en C#</title><content type='html'>Via &lt;a href="http://nuevosprogramadores.com/"&gt;NuevosProgramadores.com&lt;/a&gt; me encuentro con 2 artículos, uno donde explican como implementar el &lt;strong&gt;patrón Singleton&lt;/strong&gt; y otro donde explican el &lt;strong&gt;manejo de hilos&lt;/strong&gt; y &lt;strong&gt;delegates&lt;/strong&gt;. Todo está implementado en &lt;strong&gt;C#&lt;/strong&gt; y se puede descargar el código fuente del ejemplo.&lt;br /&gt;&lt;br /&gt;Link: &lt;a href="http://nuevosprogramadores.com/2008/07/implementacion-de-singleton-en-c/"&gt;Implementación de Singleton en C#&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Link: &lt;a href="http://nuevosprogramadores.com/2008/07/manejo-de-hilos-en-c-shar-parte-1/"&gt;Manejo de hilos en C# + delegates + invoke&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-7410296309536339331?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/7410296309536339331/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=7410296309536339331' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/7410296309536339331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/7410296309536339331'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/07/implementacin-de-singleton-y-manejo-de.html' title='Implementación de Singleton y manejo de hilos en C#'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-2497037474186980460</id><published>2008-07-17T10:37:00.000-07:00</published><updated>2008-07-17T11:02:00.740-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VB.Net'/><category scheme='http://www.blogger.com/atom/ns#' term='Aplicaciones de Consola'/><title type='text'>Hola Mundo, la primera aplicacion</title><content type='html'>Como es clásico en el mundo de la programación, lo primero que haremos será el clásico &lt;strong&gt;Hola Mundo!&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;En esta ocasión utilizaremos una &lt;strong&gt;Aplicación de Consola&lt;/strong&gt; en lenguaje &lt;strong&gt;VB.Net&lt;/strong&gt;, para ello iremos a crear un nuevos proyecto y seleccionaremos &lt;strong&gt;Visual Basic&lt;/strong&gt; y &lt;strong&gt;Console Application&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a title="Click sobre la imagen para agrandarla" href="http://bp1.blogger.com/_61c_vpZbWyk/SH-FH_SR1GI/AAAAAAAAAGE/p98i-lJ2L1I/s1600-h/New-Console-Application.jpg" target="_self"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224040465066742882" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="Nueva aplicación de consola" src="http://bp1.blogger.com/_61c_vpZbWyk/SH-FH_SR1GI/AAAAAAAAAGE/p98i-lJ2L1I/s200/New-Console-Application.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Eso nos creará la aplicación y automáticamente agregará un módulo con el procedimiento que se ejecutará al iniciar la aplicación.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Module Module1&lt;br /&gt;&lt;br /&gt;&lt;span style="PADDING-LEFT: 18px"&gt;&lt;/span&gt;Sub Main()&lt;br /&gt;&lt;br /&gt;&lt;span style="PADDING-LEFT: 18px"&gt;&lt;/span&gt;End Sub&lt;br /&gt;&lt;br /&gt;End Module&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;A continuación agregaremos 2 líneas, la primera se encargará de escribir en nuestra consola el texto &lt;strong&gt;Hola Mundo!&lt;/strong&gt;, y la segunda esperará a que el usuario presione una tecla para continuar la ejecución del código... que en este caso llevará al final de la aplicación.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Module Module1&lt;br /&gt;&lt;br /&gt;&lt;span style="PADDING-LEFT: 18px"&gt;&lt;/span&gt;Sub Main()&lt;br /&gt;&lt;span style="PADDING-LEFT: 36px"&gt;&lt;/span&gt;Console.WriteLine("Hola Mundo!")&lt;br /&gt;&lt;span style="PADDING-LEFT: 36px"&gt;&lt;/span&gt;Console.Read()&lt;br /&gt;&lt;span style="PADDING-LEFT: 18px"&gt;&lt;/span&gt;End Sub&lt;br /&gt;&lt;br /&gt;End Module&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Y así de simple hemos escrito &lt;strong&gt;nuestra primera aplicación en .Net&lt;/strong&gt;, ahora sólo resta ejecutarla, para lo cual presionaremos la tecla &lt;strong&gt;F5&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a title="Click sobre la imagen para agrandarla" href="http://bp1.blogger.com/_61c_vpZbWyk/SH-HqHOIacI/AAAAAAAAAGM/Jn6vwFnGKh8/s1600-h/console-application-hola-mundo.jpg" target="_self"&gt;&lt;img id="BLOGGER_PHOTO_ID_5224043250335640002" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="Hola Mundo, nuestra primera aplicación de consola" src="http://bp1.blogger.com/_61c_vpZbWyk/SH-HqHOIacI/AAAAAAAAAGM/Jn6vwFnGKh8/s200/console-application-hola-mundo.jpg" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-2497037474186980460?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/2497037474186980460/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=2497037474186980460' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2497037474186980460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/2497037474186980460'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/07/hola-mundo-la-primera-aplicacion.html' title='Hola Mundo, la primera aplicacion'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_61c_vpZbWyk/SH-FH_SR1GI/AAAAAAAAAGE/p98i-lJ2L1I/s72-c/New-Console-Application.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3398533864216934520.post-8460664739069328934</id><published>2008-07-11T17:56:00.000-07:00</published><updated>2008-07-11T18:35:33.244-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net framework'/><title type='text'>Que es el .net framework?</title><content type='html'>&lt;i&gt;Sólo una breve introducción, por si alguien aún no está familiarizado con ésta tecnología.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;.Net Framework&lt;/strong&gt; es una plataforma de desarrollo de software que Microsoft lanzó al mercado como respuesta a la creciente couta del mercado que está tomando la tecnología Java de Sun Microsystems.&lt;br /&gt;&lt;br /&gt;Se trata de un conjunto de utilidades que gracias a la norma, &lt;i&gt;(incluída en ECMA-335, ISO/IEC 23271)&lt;/i&gt;, que define la implementación de &lt;abbr title="Base Class Library"&gt;BCL&lt;/abbr&gt;, permite su implementación en varias plataformas; una de ellas es Mono, un proyecto que pretende ser la implementación libre de .Net para GNU/Linux.&lt;br /&gt;&lt;br /&gt;A grandes rasgos, el framework permite el desarrollo de aplicaciones en varios lenguajes gracias al &lt;abbr title="Common Langage Runtime"&gt;CLR&lt;/abbr&gt;. Básicamente, todo se compila en un lenguaje intermedio, que es compatible con CLR, llamado &lt;abbr title="Microsoft Intermediate Language"&gt;MSIL&lt;/abbr&gt;, el cuál está basado en &lt;abbr title="Common Language Specification"&gt;CLS&lt;/abbr&gt;.&lt;br /&gt;&lt;br /&gt;Luego para ejecutar las aplicaciones se utiliza un compilador &lt;abbr title="Just In Time"&gt;JIT&lt;/abbr&gt; el cual ejecuta el código máquina real en la máquina del cliente, lo cual permite independencia con respecto a la arquitectura.&lt;br /&gt;&lt;br /&gt;En la imagen se puede ver la estructura básica del .Net Framework.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_61c_vpZbWyk/SHgJu_drTnI/AAAAAAAAAFY/kefrQqJiJtQ/s1600-h/estructura-net-framework.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_61c_vpZbWyk/SHgJu_drTnI/AAAAAAAAAFY/kefrQqJiJtQ/s200/estructura-net-framework.jpg" alt="Estructura básica del framework" id="BLOGGER_PHOTO_ID_5221934470850629234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Fuente: &lt;a href="http://es.wikipedia.org/wiki/.NET_de_Microsoft" target="_blank" title=".NET - Wikipedia"&gt;Wikipedia&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3398533864216934520-8460664739069328934?l=aprendiendonet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aprendiendonet.blogspot.com/feeds/8460664739069328934/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3398533864216934520&amp;postID=8460664739069328934' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8460664739069328934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3398533864216934520/posts/default/8460664739069328934'/><link rel='alternate' type='text/html' href='http://aprendiendonet.blogspot.com/2008/07/que-es-el-net-framework.html' title='Que es el .net framework?'/><author><name>Pablo R</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_61c_vpZbWyk/TGImNX-F5vI/AAAAAAAAAzo/a0q055hgzyc/S220/IMG_1171.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_61c_vpZbWyk/SHgJu_drTnI/AAAAAAAAAFY/kefrQqJiJtQ/s72-c/estructura-net-framework.jpg' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
