Tag Archives: C#

Incrustar archivos en un ejecutable

0
Filed under .NET Development

La idea de este artículo es mostrar cómo incrustar archivos en un ejecutable y para esto haremos de cuenta que queremos incrustar imágenes.

Generalmente tenemos que mostrar imágenes en nuestra aplicación. Imágenes que no cambiarán en tiempo de ejecución pero que sí podrán cambiar en versiones futuras de la aplicación.
Muchos de ustedes estarán imaginando posibles soluciones a este problema. Por ejemplo:

- Poner las imágenes en una carpeta dentro de la carpeta de la aplicación.
- Poner las imágenes en una tabla en una base de datos.
- Incrustar las imágenes en el ejecutable.

Como siempre en esto del desarrollo de software, no hay una solución que sea la mejor y la única para todas las situaciones posibles de negocio. Veámos algunas de las ventajas y desventajas de las soluciones propuestas anteriormente:

- Poner las imágenes en una carpeta dentro de la carpeta de la aplicación:
- Ventaja: si queremos cambiar las imágenes, digamos que para dar una nueva apariencia a la aplicación sin tener que recompilarla, simplemente vamos a la carpeta en donde están las imágenes y las remplazamos.
- Ventaja: ya que las imágenes no estarán incrustadas en el ejecutable, el tamaño del ejecutable será menor.
- Desventaja: cualquier usuario puede borrar las imágenes de la carpeta. Para hacer la aplicación más robusta, habría que validar si las imágenes no fueron borradas.
- Desventaja: cualquier usuario podría ir a la carpeta en donde tenemos las imágenes almacenadas y podría remplazarlas por otras, dejando nuestra aplicación con una apariencia inconsistente.

- Poner las imágenes en una tabla en una base de datos:
- Ventaja: las imágenes quedarían almacenadas en un solo lugar.
- Desventaja: habría que tener una base de datos con una tabla que sirva exclusivamente para almacenar las imágenes. Esto puede ser bastante molesto y hasta podría llegar a enlentecer el proceso de desarrollo de la aplicación, así como también podría agregar complejidad, etc.

- Incrustar las imágenes en el ejecutable:
- Ventaja: las imágenes quedarían almacenadas en un solo lugar.
- Ventaja: un "usuario común" no podrá cambiar fácilmente las imágenes.
- Desventaja: el tamaño del ejecutable será mayor dependiendo de la cantidad de imágenes que tengamos.
- Desventaja: si queremos cambiar las imágenes tendríamos que recompilar el ejecutable.

En el caso de querer incrustar imágenes, podemos utilizar el control "ImageList".

1 – En el explorador de solución buscamos nuestro proyecto. Para agregar un archivo de recursos, hacemos clic derecho sobre él y elegimos la opción "Add" -> "New Item…". Cuando aparezca el cuadro "Add New Item", buscamos la plantilla "Resources File" y la seleccionamos. De nombre le ponemos "Imagenes.resx" y hacemos clic en "Add". Se abrirá "Imagenes.resx".

[Haga clic en la imagen para ampliar]


2 – En "Imagenes.resx", elegimos la opción "Images". Por último, desplegamos "Add Resource" y elegimos "Add Existing File..". Buscamos una imagen y la abrimos.

[Haga clic en la imagen para ampliar]

[Haga clic en la imagen para ampliar]

[Haga clic en la imagen para ampliar]


3 – Guardamos los cambios.

Para mostrar la imagen en un botón por ejemplo, podemos utilizar el siguiente código:

    using System.Drawing;
    using System.Windows.Forms;

    public partial class Form1 : Form
    {
        public Form1()
        {
            this.InitializeComponent();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            Button boton = new Button();
            boton.AutoSize = true;
            boton.Image = Imagenes.button_ok;
            boton.ImageAlign = ContentAlignment.MiddleLeft;
            boton.Text = "¡Hola mundo!";
            boton.TextImageRelation = TextImageRelation.ImageBeforeText;
            this.Controls.Add(boton);
        }
    }

[Haga clic en la imagen para ampliar]


Para reproducir un sonido cuando el usuario haga clic en el botón, podemos agregar un nuevo archivo de recursos llamado "Sonidos.resx" y en lugar de elegir la categoría "Images" elegimos "Audio".

[Haga clic en la imagen para ampliar]

[Haga clic en la imagen para ampliar]

    using System.Drawing;
    using System.Media;
    using System.Windows.Forms;

    public partial class Form1 : Form
    {
        public Form1()
        {
            this.InitializeComponent();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            Button boton = new Button();
            boton.AutoSize = true;
            boton.Image = Imagenes.button_ok;
            boton.ImageAlign = ContentAlignment.MiddleLeft;
            boton.Text = "¡Hola mundo!";
            boton.TextImageRelation = TextImageRelation.ImageBeforeText;
            boton.Click += new System.EventHandler(this.Boton_Click);
            this.Controls.Add(boton);
        }

        private void Boton_Click(object sender, System.EventArgs e)
        {
            using (SoundPlayer windowsShutdown = new SoundPlayer(Sonidos.Windows_Shutdown))
            {
                windowsShutdown.Play();
            }
        }
    }

¿Cómo?: dibujar texto sobre una imagen (GDI+)

0
Filed under .NET Development

Requisitos:
- .NET Framework 2.0
- Tener una referencia en nuestro proyecto al ensamblado "System.Drawing".

Código:

using System.Drawing;

//Creamos un objeto Image especificando la imagen que queremos modificar.
Image imagen = Image.FromFile(@"C:\Imagen.png");
//Creamos un objeto Graphics (superficie de dibujo) a partir de la imagen cargada anteriormente.
Graphics superficieDibujo = Graphics.FromImage(imagen);
//Creamos un objeto Font para la fuente Verdana con un tamaño de 24.
Font fuente = new Font("Verdana", 24F);
//Dibujamos la cadena de texto "¡Hola mundo!", de color verde, en la ubicación 0,0.
superficieDibujo.DrawString("¡Hola mundo!", fuente, Brushes.Green, PointF.Empty);
//Guardamos la imagen.
imagen.Save(@"C:\Imagen_modificada.png");
//Liberamos recursos.
fuente.Dispose();
superficieDibujo.Dispose();
imagen.Dispose();

¿Cómo?: validar las credenciales (nombre de usuario y contraseña) del usuario contra Windows y/o Active Directory Domain Services

0
Filed under .NET Development

Requisitos:
- .NET Framework 3.5
- Tener una referencia en nuestro proyecto al ensamblado "System.DirectoryServices.AccountManagement".

Código:

using System.DirectoryServices.AccountManagement;

Para validar las credenciales del usuario contra Windows (MSAM):

using (PrincipalContext samContext = new PrincipalContext(ContextType.Machine))
{
    if (samContext.ValidateCredentials("Nombre de usuario", "Contraseña"))
    {
        //Las credenciales sí son válidas.
    }
    else
    {
        //Las credenciales no son válidas.
    }
}

Para validar las credenciales del usuario contra Active Directory Domain Services (AD DS):

using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain))
{
    if (domainContext.ValidateCredentials("Nombre de usuario", "Contraseña"))
    {
        //Las credenciales sí son válidas.
    }
    else
    {
        //Las credenciales no son válidas.
    }
}

Permitir sólo una instancia en ejecución de una aplicación (How to run a single instance of an application)

1
Filed under .NET Development

Para esto, pueden utilizar la siguiente clase:

using System;
using System.Threading;

namespace NicolasFerreira.Utilities
{
    //* **************************************************
    //* Author: Nicolás Ferreira (http://nicolasferreira.com/)
    //* **************************************************
    /// <summary>
    /// This class uses EventWaitHandle. It lets you know if another instance of your application is already running. Also, if there is already a running instance of your application and someone try to start another, the main one will be notified.
    /// </summary>
    public static class SingleInstanceApplication
    {
        private static EventWaitHandle _EventWaitHandle;
        private static object _lock = new object();
        private static bool _Opened;
        private static Thread _WaitOneHandlerThread;
        private static bool _RaiseAnotherTriedToRunEvent;
        public delegate void AnotherTriedToRunEventHandler();
        public static event AnotherTriedToRunEventHandler AnotherTriedToRun;
        /// <summary>
        /// Gets a value that indicates whether single instance application monitor is open.
        /// </summary>
        public static bool Opened
        {
            get
            {
                return _Opened;
            }
        }
        /// <summary>
        /// Opens the single instance application monitor.
        /// </summary>
        /// <param name="uniqueInstanceName">A name that identifies your application as unique.</param>
        /// <returns>true if the system-wide EventWaitHandle could be created (the calling instance is single). false if the calling instance should terminate.</returns>
        public static bool Open(string uniqueInstanceName)
        {
            return Open(uniqueInstanceName, false);
        }
        /// <param name="local">true if each terminal server session can run an instance of your application. Otherwise, false.</param>
        public static bool Open(string uniqueInstanceName, bool local)
        {
            if (string.IsNullOrEmpty(uniqueInstanceName))
                throw new ArgumentException("uniqueInstanceName cannot be blank.");
            else if (_Opened)
                throw new InvalidOperationException("Single instance application monitor is open.");
            lock (_lock)
            {
                bool createdNew;
                _EventWaitHandle = new EventWaitHandle(
                    false,
                    EventResetMode.AutoReset,
                    string.Concat(local ? "Local\\" : "Global\\", uniqueInstanceName),
                    out createdNew);
                if (createdNew)
                {
                    _Opened = true;
                    _RaiseAnotherTriedToRunEvent = true;
                    _WaitOneHandlerThread = new Thread(new ThreadStart(EventWaitHandleHandler));
                    _WaitOneHandlerThread.Start();
                }
                else
                {
                    _Opened = false;
                    _RaiseAnotherTriedToRunEvent = false;
                    _EventWaitHandle.Set();
                    _EventWaitHandle.Close();
                    _EventWaitHandle = null;
                }
            }
            return _Opened;
        }
        private static void EventWaitHandleHandler()
        {
            if (_EventWaitHandle != null)
            {
                while (_Opened)
                {
                    _EventWaitHandle.WaitOne();
                    if ((_RaiseAnotherTriedToRunEvent) && (AnotherTriedToRun != null))
                        ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
                        {
                            AnotherTriedToRun();
                        }));
                }
            }
        }
        /// <summary>
        /// Closes the single instance application monitor and frees resources.
        /// </summary>
        public static void Close()
        {
            lock (_lock)
            {
                if (!_Opened)
                    throw new InvalidOperationException("Single instance application monitor is not open.");
                _Opened = false;
                _RaiseAnotherTriedToRunEvent = false;
                _EventWaitHandle.Set();
                _EventWaitHandle.Close();
                _EventWaitHandle = null;
            }
        }
    }
}

Ejemplo en una aplicación consola:

        static void Main(string[] args)
        {
            SingleInstanceApplication.AnotherTriedToRun += new SingleInstanceApplication.AnotherTriedToRunEventHandler(SingleInstanceApplication_AnotherTriedToRun);
            if (!SingleInstanceApplication.Open("{63BAA9C4-849C-4b4a-8B9C-FC1D640F09E2}"))
            {
                Console.WriteLine("Another instance of this application is currently running.");
            }
            else
            {
                Console.WriteLine("This is the main instance of your application.");
                Console.ReadLine();
                if (SingleInstanceApplication.Opened)
                {
                    SingleInstanceApplication.Close();
                }
            }
        }
        static void SingleInstanceApplication_AnotherTriedToRun()
        {
            Console.WriteLine(string.Format("{0}: Another instance of this application tried to run.",
                DateTime.Now.ToString()));
        }

Ejemplo en una aplicación Windows Forms:

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            if (SingleInstanceApplication.Open("{4C8C7928-55FD-45e8-A13E-895C5EE4D0C3}"))
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
                if (SingleInstanceApplication.Opened)
                {
                    SingleInstanceApplication.Close();
                }
            }
            else
            {
                MessageBox.Show("Another instance of this application is currently running.");
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            SingleInstanceApplication.AnotherTriedToRun += new SingleInstanceApplication.AnotherTriedToRunEventHandler(SingleInstanceApplication_AnotherTriedToRun);
        }

        void SingleInstanceApplication_AnotherTriedToRun()
        {
            MessageBox.Show(string.Format("{0}: Another instance of this application tried to run.",
                DateTime.Now.ToString()));
        }

Descargar el código.