Skip to content

trabajando con variables 3/3 : Variables desechables

Muchas veces una variable es utilizada en un determinado contexto o porción de código y luego que es utilizada lo mas útil es deshacerse de ella, para ello se utiliza la interfaz Disposable y su método Dispose(). Este metodo permite gestionar programáticamente las acciones que deben realizarse para liberar los recursos de los objetos; aunque esto puede sonar  un poco enredado, es relativamente sencillo,  veámoslo con un ejemplo tomado de un artículo anterior donde revisabamos la forma de manejar una bitácora de eventos, esta bitácora al heredar de la clase Component implementa el método Dispose() . en nuestro artículo original (si no tienes el proyecto tratado en el artículo mencionado, no hay lío, lo puedse descargar) vimos anteriormente que se podía usar el eventLog de esta forma:

private void button1_Click(object sender, EventArgs e)
        {
          label1.Text = "hola mundo";
          if (_DEBUG)
              eventLog1.WriteEntry("se ha hecho click", System.Diagnostics.EventLogEntryType.Information,0);
         
        }

lo cual permite escribir en esa bitácora (para poderla visualizar en el visor de eventos de windows) cada vez que se presiona el botón, pero no controla si el objeto debe ser descartado, por lo que seguirá en memoria hasta que se invoque al método Dispose()  o se acabe el programa (lo que primero ocurra)

si queremos hacer un uso mas eficiente de memoria podemos crear y destruir el objeto eventlog bajo demanda logrando que el nuestro código quede así:

   private void button1_Click(object sender, EventArgs e)
        {
          label1.Text = "hola mundo";
        
         
         
              if (_DEBUG)
              {
                  eventLog1 = new System.Diagnostics.EventLog("", Environment.MachineName, "hola mundo");   //inicialización de eventLog1
                  eventLog1.WriteEntry("se ha hecho click", System.Diagnostics.EventLogEntryType.Information, 0);
                  eventLog1.Dispose(); // desechado de eventlog1 
              }
          
           }

esto hace que el código sea mas eficiente frente al uso de memoria aunque requiere que el desarrollador controle la creación y destrucción del código, una forma mas eficiente para esto es utilizando la palabra reservada using la cual automatiza un poco el proceso de creación y destrucción del objeto, para nuestro ejemplo esto quedaría de esta forma:

  private void button1_Click(object sender, EventArgs e)
        {
          label1.Text = "hola mundo";
        
         
         
              if (_DEBUG)
              {
                  using (eventLog1 = new System.Diagnostics.EventLog("", Environment.MachineName, "hola mundo"))   //inicialización de eventLog1
                  {
                  eventLog1.WriteEntry("se ha hecho click", System.Diagnostics.EventLogEntryType.Information, 0);
                  }
              }
         }

Este tipo de cláusula es muy frecuente en el manejo de archivos y conexiones a bases de datos puesto que libera al programador de estar pendiente de los eventos de creación y destruccción de este tipo de objetos.

Trabajando con variables (parte 2/3) tipos implícitos de datos

En algunos casos es posible que no sepamos el tipo de variable que nos retorna alguna función, por lo que lo mas conveniente es permitir al compilador que infiera el tipo de variable, para hacer esto se usa la palabra reservada var.

Esta palabra reservada solo es válida dentro del ámbito de método asì que partamos de una modificación del código creado en el artículo anterior:

using System;

namespace Pablito
{
    class Program
    {
        static void Main(string[] args)
        {
            //en primer lugar se define una variable para el dinero que carga pablito
            //y se asigna un valor (para este caso 50)
            var dineroPablito = 50;
            //el problema nos dice que el dinero de pablito se incrementa en 100
            dineroPablito = dineroPablito + 100;
            // luego el problema dice que gasta 50 en una golosina
            dineroPablito = dineroPablito - 50;
            // Se muestra la solución al problema
            Console.WriteLine("pablito al final queda con $" + dineroPablito);
        }
    }
}

Nótese que la definición de la variable se hace mediante var y al compilarla el propio compilador de C# convierte esta variable a int.

en otro ejemplo para crear variables de tipo básico son:

var i = 10; // i se compila como un int
var d = 10.5; // d se compila como un Double
var s = "Hola Mundo"; //s se compila como un String
var b = true; // b se compila como un boolean

pero el poder mas impresionante de esta palabra reservada está en los bucles foreach(que serán tema de la próxima serie) y en el uso de las variables “desechables” (las cuales trataremos en el pròximo artículo)

Trabajando con variables (parte 1/3) : Inicialización de datos básicos en C#

Este tema aunque muy básico se hace necesario puesto que muchas veces el desarrollador novato o intermedio a veces no logra el comportamiento esperado de su aplicación por fallas en el procedimiento de inicialización de variables. Para ilustrar esto partamos de un ejemplo cotidiano (tipo problema de aritmética de 2do de primaria).

Pablo recibe $100 para comprar golosinas, va a la tienda y compra un dulce que cuesta $50. ¿cúanto dinero tiene Pablo al salir de la tienda?

Muchos podrán decir que Pablo sale de la tienda con $50 y parece obvio, pero se han puesto a pensar que la condición fundamental para responder el problema es cuanto tenía Pablo antes de entrar a la tienda, Digamos que cargaba $200 antes de entrar, así que salió con $250.

Esto nos sucede muchas veces al desarrollar aplicaciones, omitimos esta parte de inicialización, generando errores de compilación (que se derivan en reprocesos de desarrollo), o peor aún en errores y excepciones en tiempo de ejecución.

Vamos entonces al grano, digamos que vamos a codificar una aplicación que muestre el problema planteado a continuación:

using System;

namespace Pablito
{
    class Program
    {
        static void Main(string[] args)
        {
            //en primer lugar se define una variable entera para el dinero que carga pablito
            int dineroPablito;
            //el problema nos dice que el dinero de pablito se incrementa en 100
            dineroPablito = dineroPablito + 100;
            // luego el problema dice que gasta 50 en una golosina
            dineroPablito = dineroPablito - 50;
            // Se muestra la solución al problema
            Console.WriteLine("pablito al final queda con $"+dineroPablito);
        }
    }
}

Al intentar compilar este código se obtiene un error:

Uso de la variable local no asignada ‘dineroPablito’

Lo cual indica que debemos asignar un valor (o inicializar) la variable 'dineroPablito' para lo cual tenemos dos opciones, la primera es usando la palabra clave new de la siguiente forma:

using System;

namespace Pablito
{
    class Program
    {
        static void Main(string[] args)
        {
            //en primer lugar se define una variable entera para el dinero que carga pablito y 
            //se asigna el valor por defecto
            int dineroPablito = new int();
            //el problema nos dice que el dinero de pablito se incrementa en 100
            dineroPablito = dineroPablito + 100;
            // luego el problema dice que gasta 50 en una golosina
            dineroPablito = dineroPablito - 50;
            // Se muestra la solución al problema
            Console.WriteLine("pablito al final queda con $" + dineroPablito);
        }
    }
}

Esta opción es válida cuando se desea asignar la variable a su valor por defecto (en el caso de int es 0) pero si se desea iniciar la variable con otro valor lo conveniente es hacer la asignación de forma explícita, es decir:

using System;

namespace Pablito
{
    class Program
    {
        static void Main(string[] args)
        {
            //en primer lugar se define una variable entera para el dinero que carga pablito
            //y se asigna un valor (para este caso 50)
            int dineroPablito = 50;
            //el problema nos dice que el dinero de pablito se incrementa en 100
            dineroPablito = dineroPablito + 100;
            // luego el problema dice que gasta 50 en una golosina
            dineroPablito = dineroPablito - 50;
            // Se muestra la solución al problema
            Console.WriteLine("pablito al final queda con $" + dineroPablito);
        }
    }
}

Este segundo método permite asignar valores iniciales a las variables.

Ya para concluir hay que tener en cuenta que el valor por defecto para los tipos de datos numéricos es 0 para los datos enteros y 0.0 para los datos de coma flotante; para los datos booleanos es false (Por lo cual recomiendo cuidado en el uso de estas variables), para String es una cadena vacía (o sea “”) y para objetos Null (a menos que se haya declarado explícitamente otra cosa en el constructor de la clase)

“depurando” tu aplicación en tiempo de ejecución (parte 2/2)

Tras el tutorial anterior hemos visto una forma para entrar a modo “depuración” en tiempo de ejecución . Sin embargo lo importante del modo de depuración es darse cuenta de los eventos que ocurren para determinar algún funcionamiento erroneo, para muchos es conocido el uso de:

MessageBox.show("mensaje");

Como herramienta que permite visualizar en un cuadro de diálogo emergente un mensaje cualquiera, esta opción es conveniente en algunos casos (que veremos en un post futuro) pero no es muy buena idea para un proceso de depuración puesto que es bastante invasivo y puede resultar molesto. Por esto haremos uso del componente EventLog el cual nos permitirá llevar registro de las actividades de nuestra aplicación de forma “silenciosa”, almacenar esa información y procesarla desde el visor de eventos de windows. Pero vamos por partes, primero se debe agregar el elemento eventlog a tu aplicación (para esto usaré la misma aplicación del tutorial anterior) y para esto debes arrastrar de la barra de componentes el control evenlog tal como se ve en el siguiente video:

Ahora el diseñador debe quedar de la siguiente manera:

namespace HolaMundoDebug
{
    partial class Form1
    {
        /// <summary>
        /// Variable del diseñador requerida.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Limpiar los recursos que se estén utilizando.
        /// </summary>
        /// <param name="disposing">true si los recursos administrados se deben eliminar; false en caso contrario, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Código generado por el Diseñador de Windows Forms

        /// <summary>
        /// Método necesario para admitir el Diseñador. No se puede modificar
        /// el contenido del método con el editor de código.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.eventLog1 = new System.Diagnostics.EventLog();
            ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(95, 105);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.button1.MouseLeave += new System.EventHandler(this.Button1_Mouseleave);
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(92, 52);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(35, 13);
            this.label1.TabIndex = 1;
            this.label1.Text = "label1";
            // 
            // eventLog1
            // 
            this.eventLog1.SynchronizingObject = this;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private System.Diagnostics.EventLog eventLog1; //este es la bitácora de eventos
    }
}

Donde puede verse que se ha agregado una instancia de la clase System.Diagnostics.EventLog llamada eventLog1 ese será el objeto que manipularemos para nuestra depuración. Como siempre que se trabaja con una clase nueva, es recomendable conocer su documentación, sin embargo algunas consideraciones se harán a lo largo de este documento.

pasando ya a la parte sustancial de este artículo iniciemos por el constructor, al iniciar la aplicación es muy buena práctica (en algunos casos es una obligación) inicializar los componentes, por lo tanto en el constructor de la aplicación debe hacerse lo propio con el eventlog1 que acabamos de crear, y antes de esto crear la fuente e eventos; entonces el constructor de la aplicación quedará así:

public Form1()
        {
            
            //inicialización de fuente
            if (!System.Diagnostics.EventLog.SourceExists("hola mundo"))
                            System.Diagnostics.EventLog.CreateEventSource("bitacora", "hola mundo");
         //inicialización de eventLog1
            eventLog1 = new System.Diagnostics.EventLog("", Environment.MachineName,"hola mundo");
                
            //esta línea convierte el valor de tu clave DEBUG, en un valor booleano
            _DEBUG = Convert.ToBoolean(ConfigurationManager.AppSettings["DEBUG"]);

            // ahora esta línea le agrega al título de la ventana el texto "(debug)" en caso que estés en modo de depuración.
            if (_DEBUG)
                this.Text += " (debug)";
            
        }

En primer lugar se verifica la fuente de eventos y en caso de no existir se crea mediante el método createEventSource , que recibe como parámetros el nombre del registro (en nuestro caso “bitacora” y el nombre de la fuente)

He usado el constructor mas largo de System.Diagnostics.EventLog , para dar a conocer todos los parámetros involucrados, si se hace un análisis detallado el constructor que se usó es de la forma:

new public EventLog (string logName, string machineName, string source)

Donde:
Source es el nombre de origen que se va a registrar y utilizar al escribir en el registro de eventos.
logName es el nombre del registro a manipular (se deja en blanco, porque ya se hozo la asociación entre el registro y la fuente en la creación de la segunda). y
machineName es el nombre del equipo en el que se van a leer o en el que se van a escribir los eventos.

Sobre la propiedad Source debe hacerse una claridad, el registro de sistema toma únicamente los 8 primeros caracteres, por lo que nombres de fuente como “hola Mundo” y “hola Mundial” serán considerados equivalentes y pueden originar conflictos.

Luego de inicializar la aplicación se puede proceder a hacer uso del registro de eventos, usando para esto el método

writeEntry(string message,EventLogEntryType type,int eventID )

Donde:
message es el mensaje que se quiere mostrar
type es el tipo de mensaje (éxito, error, advertencia, mensaje informativo)
y eventID es un número de identificación de mensaje (en caso tal que tengas una codificación numérica de los mensajes)

veamos el uso de esto en el método click de nuestra aplicación:

private void button1_Click(object sender, EventArgs e)
        {
          label1.Text = "hola mundo";
          if (_DEBUG)
              eventLog1.WriteEntry("se ha hecho click", System.Diagnostics.EventLogEntryType.Information, 0);
         

        }

Terminado esto, se procede a compilar el proyecto y para probar que todo esté bien, pueden orientarse por el siguiente video:

“depurando” tu aplicación en tiempo de ejecución (parte 1/2)

Muchas veces tras terminar nuestro proyecto debemos verificar que esté funcionando de manera correcta, bien sea en ambiente de pruebas o en algunos casos en ambiente de producción y a diferencia de tu ambiente de desarrollo no cuentas con un IDE para depurar tu app (aparte que se vería muy mal presentar una aplicación en un ambiente de producción corriendo en un IDE) así que veremos una téncica que particularmente utilizo para depurar las aplicaciones que realizo.

Emulando la compilación condicionada.

Si ya llevas cierto tiempo con visual studio (en cualquiera de sus versiones) has visto que en la parte superior hay una lista de selección con las opciones “debug” y “release”, estos sirven para seleccionar el ambiente en el que se va a compilar tu código (por eso cuando vas a buscar los ejecutables están repartidos en sendas carpetas “debug” y “release”). La compilación condicionada permite que se creen “objetos” de depuración (a los que puedes acceder mediante llamados a los métodos de la clase System.diagnostics.Debug ) cuando se procesa el ejecutable en modo de depuración (debug), labor que facilita mucho evaluar el proyecto en la etapa de desarrollo. Pero como dije en la introducción en los ambientes de prueba y/o producción lo mas probable es que no contemos con un IDE por lo que usaremos ciertas características para emular la compilación condicionada.

1. Creando la aplicación.

Nuestra aplicación de pruebas será una aplicación winforms muy sencilla, el código de diseñador es:

namespace HolaMundoDebug
{
    partial class Form1
    {
        /// <summary>
        /// Variable del diseñador requerida.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Limpiar los recursos que se estén utilizando.
        /// </summary>
        /// <param name="disposing">true si los recursos administrados se deben eliminar; false en caso contrario, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Código generado por el Diseñador de Windows Forms

        /// <summary>
        /// Método necesario para admitir el Diseñador. No se puede modificar
        /// el contenido del método con el editor de código.
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(95, 105);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.button1.MouseLeave += new System.EventHandler(this.Button1_Mouseleave);
            //
            // label1
            //
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(92, 52);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(35, 13);
            this.label1.TabIndex = 1;
            this.label1.Text = "label1";
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 262);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
    }
}

Y el código de los comportamientos será:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HolaMundoDebug
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "hola mundo";
        }

        private void Button1_Mouseleave(object sender, EventArgs e)
        {
            label1.Text = "nada";
        }
    }
}

2. Crear una clave en el app.config

¿app.config? Quizás se te haga un poco extraño si eres novato, pero es un archivo bastante común, en las aplicaciones comerciales, este archivo xml permite que se puedan cambiar los parámetros de configuración en tiempo de ejecución.

en primer lugar vamos a mostrar como se crea un archivo app.config dentro de tu solución:

Luego de crearlo debes modificarlo para que quede de la siguiente forma:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="DEBUG" value="True"/>
  </appSettings>
</configuration>

Al hacer eso haz creado una llave que se llama “DEBUG” y le haz puesto como valor “true”

3. cargar el valor de la clave en el app.config en la aplicación

Ahora queda un paso muy sencillo que es cargar el valor que tiene  la clave DEBUG en una variable dentro de la aplicación que estás construyendo para hacer esto debes,  en primer lugar crear una variable de tipo booleana llamada _DEBUG y luego modificarel código del constructor de tu forma (para mi caso es form1.cs) de tal forma que quede así:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;

namespace HolaMundoDebug
{
    public partial class Form1 : Form
    {
        private Boolean _DEBUG;
        public Form1()
        {
            InitializeComponent();
            //esta línea convierte el valor de tu clave DEBUG, en un valor booleano
            _DEBUG = Convert.ToBoolean(ConfigurationManager.AppSettings["DEBUG"]);

            // ahora esta línea le agrega al título de la ventana el texto "(debug)" en caso que estés en modo de depuración.
            if (_DEBUG)
                this.Text += " (debug)";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "hola mundo";
        }

        private void Button1_Mouseleave(object sender, EventArgs e)
        {
            label1.Text = "nada";
        }
    }
}

Hasta aquí va la primera parte de este tutorial, espero que les sea de utilidad y cualquier duda, con gusto la atenderé en los comentarios del post.

Creando un instalador en VS 2010 (parte 2)


Bien, al terminar de crear el instalador para tu aplicación (tal como se mostró en la primera parte de esta serie) aparece una plantilla de instalador en blanco y con unos valores predeterminados, así que en esta parte veremos el contenido del panel de propiedades del instalador, y como podemos editarlo, al crear nuestro instalador en el panel de propiedades tenemos un listado de propiedades cmo los que se muestran a continuación:


panel de propiedades (1/2)

panel de propiedades (2/4)

Panel de propiedades (3/4)

Panel de propiedades (4/4)Es una larga lista de propiedades pero el objetivo de este artículo es explicarlo de la forma mas sencilla posible, así que iremos por cada una de las propiedades.

AddRemoveProgramsIcon : Cómo lo deben suponer en esta propiedad se debe ubicar el ícono con el que deseas que tu aplicación se identifique en el panel de agregar y quitar programas, es opcional que pongas un ícono, puedes crearlos o buscarlos en colecciones como icongal o crystal project.

Author: Quien hace el software, allí puedes poner tu nombre o el de tu compañía. Esta propiedad aparece en la información que acompaña al ícono cuando estamos en el explorador de windows

Description: La descripción del software, también aparece en las propiedades del instalador.

DetectNewerInstalledVersion: una propiedad booleana, true indica que detecta si existe una versión mas reciente del programa y pide alguna opción para removerla; false dice que no realiza esa detección.

InstallAllUsers: propiedad booleana que al estar en true permite que el software se instale para todos los usuarios de la máquina, al estar en false, sólo deja instalar la aplicación para el usuario actual (muchos no lo tienen en cuenta, pero recuerden que a partir de windows XP microsoft implementó cuentas de usuarios con distintos privilegios y a partir de windows vista reforzó este punto con el UAC , así que tene en cuenta esto al generar tus instaladores)

Keywords: Son palabras claves que van en el instalador, en realidad no se como se usan.

Localization: Sirve para elegir el idioma en que aparecerán los mensajes de asistencia en el instalador.

Manufacturer: El nombre de la compañía que crea el instalador (muy útil porque por regla general define el nombre de la carpeta dentro de la carpeta “archivos de programa” donde se almacenará el ejecutable.

ManufacturerURL : La URL del fabricante, te puede ayudar a dar visibilidad.

PostBuildEvent: señala la acción que se debe realizar tras la compilación

PreBuildEvent: señala la acción que se debe realizar previo a la compilación.

ProductCode: el código del producto, generalmente se genera de forma automática.

ProductName: Como se llama el producto al que le estás haciendo el instalador.

RemovePreviousVesions: una propiedad booleana, si está en true dice que antes de instalar esa versión deberá remover las versiones anteriores.

TargetPlataform: en que plataforma se planea ejecutar el programa

Title: el título que llevará el instalador.

upgradeCode: es un código que se actualiza automáticamente respecto a la versión.

Version: La versión del software que va en la notación XX.YY.ZZZZ donde XX representa cambios mayores, YY cambios menores y ZZZZ el código de actualización.

Las propiedades que hicieron falta o bien no son necesarias o algunas no las conozco bien. para ver un poco mas en detalle estos parámetros he puesto un ejemplo en video:

Creando un instalador en VS2010 (parte 1)

Hoy abro este blog con el fin de compartir mis pequeñas experiencias como desarrollador de software. Puesto que a mi me ha tocado aprender de forma muy empírica y a veces se encuentran cosas que son muy sencillas pero que por desconocimiento se complican.

Sin mas preambulos voy a iniciar con el procedimiento para crear un instalador desde Visual Studio 2010.

para ejecutar este tutorial requeriremos:

  • Visual Studio 2010 (sirve la versión express) instalado y ejecutandose.
  • Una solución con al menos un proyecto ejecutable. (si no estás familiarizado con la creación de proyectos o con la interfaz de Visual Studio 2010 te recomiendo orientarte con esta cápsula de conocimiento)
Supongamos que ya hemos finalizado nuestro proyecto en VS2010 y requerimos distribuirlo, generalmente al compilarlo en la carpeta “bin/release” de tu proyecto queda el ejecutable de tu proyecto, sin embargo a veces requieres considerar algunas otras cosas (como por ejemplo el framework o el archivo de configuración de tu aplicación) por lo que se te facilitaría mucho mas el proceso de distribución solamente usando un archivo instalador que automatice todo el proceso.
Para efectos de este tutorial creé solo un winform( pero el mismo principio puede ser aplicado a una solución con mayor complejidad).
El algoritmo general para realizar el proceso es:
1. Al terminar tu proyecto compílalo y depuralo para comprobar que esté funcionando.
2. En el explorador de soluciones (generalmente está al lado derecho en Visual Studio) busca la solución donde está el programa que acabas de compilar.
3. Haz click con el botón secundario en la solución, debe aparecerte el menú contextual.
4. En ese menú contextual esocoge a opción de agregar>>Nuevo proyecto. Debe aparecerte el cuadro de diálogo de nuevo proyecto.
5. En el cuadro de diálogo de nuevo proyecto le das click a “otro tipo de proyecto”.
6. Allí escoges la opción de proyectos de despliegue y configuración.
7. Te debe aparecer un menú con múltiples proyectos, para el caso de este tutorial escogeremos el que dice “proyecto instalador”.
8. tienes un flamante instalador donde puedes poner tu proyecto.
Como dicen que un video vale mas que un millón de palabras, te adjunto un video que muestra estos pasos iniciales: