¿Cómo leer y escribir parámetros de configuración en C#?

Toda aplicación que se respete debe incluir algún modo de persistir su configuración de una ejecución a la otra.  Aún si esto no fuera necesario, es buena práctica no codificar dentro de la aplicación los valores que utilizará por defecto, o parámetros que cambian de una máquina a otra, por ejemplo, las cadenas de conexión a las bases de datos.  En C# esto es super sencillo de lograr a partir de:

  1. Archivos de configuración estilo XML: en aplicaciones web se nombran “web.config” y en desktop “app.config”.  En general, contienen un conjunto de pares parámetro-valor.
  2. Un grupo de funciones suministradas por el namespace System.Configuration.

Ejemplo de archivo de configuración:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings file="">
    <clear />
    <add key="miParametro" value="Mi valor" />
  </appSettings>
</configuration>

Paso a paso:

  • Añadir al proyecto una referencia a “System.Configuration” (Project -> Add Reference …).
  • Añadir al código:  “using System.Configuration”.
  • Para leer un parámetro de configuración:
string miValor = ConfigurationManager.AppSettings["miParametro"];
  • Para añadir un parámetro nuevo al archivo de configuración:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings.Add("miParametro", "Mi valor");
config.Save(ConfigurationSaveMode.Modified);
  • Para modificar y persistir un parámetro de configuración:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["miParametro"].Value = "Mi valor";
config.Save(ConfigurationSaveMode.Modified);

Nota: en las operaciones de escritura (añadir y modificar) desde Visual Studio, el instinto nos lleva inmediatamente a revisar los cambios en el archivo original “app.config” (asumiendo aplicación desktop).  Este contiene los parámetros iniciales de configuración; el archivo que se modifica realmente es nombre_de_app.exe.Config que está en la carpeta bin\Debug que es el archivo real de configuración cuando se distribuye la aplicación.

Aquí he mostrado el método de trabajo más sencillo con configuraciones en .NET.  Los archivos de configuración pueden llegar a ser muy sofisticados permitiendo la categorización de los parámetros en secciones, por ejemplo <connectionStrings> para las cadenas de conexión a bases de datos.  Realmente, los ejemplos anteriores operan sobre los parámetros correspondientes a una sección específica <appSettings>, lo cual es suficiente para una gran mayoría de las aplicaciones prácticas.

Anuncios

24 Responses to ¿Cómo leer y escribir parámetros de configuración en C#?

  1. Ingeleo says:

    Muy buena esa la usare, en mi soft actual…. pero tengo por aca una propia mia arraigandome al pasado de vb5 y 6, jajaja

    //**** hice una clase

    // declaro esto
    IniClass Ini = new IniClass();

    //para usarla uso estas funciones
    //salvar
    Ini.SaveSetting(“C:\test.config”, “Key”, “Value”, “Data”);

    //esto genera este texto dentro del archivo
    // [KEY]
    // Value=data

    //Ahora Leemos
    string ValorEnElConfig = Ini.GetSetting(“c:\test.config”, “Key”, “value”,”Default”);
    // valor = Data // si existe esa key y ese value dentro de esa key de lo contrario devuelve Default

    //solo el valor de DATA es case sencitive, el de key y value no 😉

    //****************************************************************************

    using System;
    using System.IO;

    class IniClass
    {
    public bool SaveSetting(string FileName, string Key, string Value, string Data) //static void Main(string[] args)
    {
    string IniData=””;

    try
    {
    //primero que nada leo el archivo a ver si que datos tiene
    StreamReader streamReader = new StreamReader(@FileName);
    IniData = streamReader.ReadToEnd();
    streamReader.Close();
    }
    catch
    {}

    if (IniData != “”)
    {//tiene datos lo proceso
    //busco ese key
    int x = IniData.ToUpper().IndexOf(“[” + Key.ToUpper() + “]”,0);
    if (x != -1)
    {// encontre ese key busco ahora ese value

    x += Key.Length + 4; // muevo x al final del ky 2 por [] y 2 por \r\n,justo ahi
    int z = x;

    x = IniData.ToUpper().IndexOf(Value.ToUpper(),z);
    if (x != -1)
    {// encontre ese value ahora busco si tiene ese data
    // leo el data actual para luego remplazarlo
    z = x + Value.Length + 1; // 1 por el =

    x = IniData.IndexOf(“\r\n”,z);
    if (x == -1) { return (false); } // error no encontre el dato

    string dataActual = IniData.Substring(z, x – z);

    if (dataActual == Data)
    {
    return (true); // me salgo no tengo que salvar es el mismo dato a guardar
    }
    else
    { // actualizo el dato
    string inicio = IniData.Substring(0, z);
    string final = IniData.Substring(x, IniData.Length – x);

    if (final.Substring((final.Length-2), 2) == “\r\n”) { final = final.Substring(0, final.Length – 2); }

    IniData = inicio + Data + final;
    }
    }
    else
    { // no encontre ese value agrego ese value para ese key
    // guardo las 2 partes principio y final inserto el texto y luego lo sumo todo
    string inicio = IniData.Substring(0, z);
    string final = IniData.Substring(z, IniData.Length – z);

    if (final.Substring((final.Length – 2), 2) == “\r\n”) { final = final.Substring(0, final.Length – 2); }

    if(final !=””) // hay mas datos al final del archivo
    {
    IniData = inicio + Value + “=” + Data + “\r\n” + final;
    }
    else
    { // no hay mas datos al final del archivo para que sumar final, elimino el dbl enter
    IniData = inicio + Value + “=” + Data;
    }
    }
    }
    else
    { // no encontre ese key lo agrego al final de archivo
    IniData += “\r\n[” + Key.ToUpper() + “]\r\n” + Value + “=” + Data;
    }
    }
    else
    {// no tiene datos
    IniData = “[” + Key.ToUpper() + “]\r\n” + Value + “=” + Data;
    }

    try
    { //ahora salvo el ini nuevamente
    // create a writer and open the file
    TextWriter tw = new StreamWriter(@FileName);

    //quito el enter al principio
    if (IniData.Substring(0, 2) == “\r\n”) { IniData = IniData.Substring(2, IniData.Length – 2); }

    // write a line of text to the file
    tw.WriteLine(IniData);

    // close the stream
    tw.Close();
    return (true);
    }
    catch
    {
    return (false);
    }
    }

    public string GetSetting(string FileName, string Key, string Value, string Default)
    {
    string IniData = “”;

    try
    {
    //primero que nada leo el archivo a ver si que datos tiene
    StreamReader streamReader = new StreamReader(@FileName);
    IniData = streamReader.ReadToEnd();
    streamReader.Close();
    }
    catch
    {
    return (Default);
    }

    if (IniData != “”)
    {//tiene datos lo proceso
    //busco ese key
    int x = IniData.ToUpper().IndexOf(“[” + Key.ToUpper() + “]”, 0);
    if (x != -1)
    {// encontre ese key busco ahora ese value

    x += Key.Length + 4; // muevo x al final del ky 2 por [] y 2 por \r\n,justo ahi
    int z = x;

    x = IniData.ToUpper().IndexOf(Value.ToUpper(), z);
    if (x != -1)
    {// encontre ese value ahora busco si tiene ese data
    // leo el data actual para luego remplazarlo
    z = x + Value.Length + 1; // 1 por el =

    x = IniData.IndexOf(“\r\n”, z);
    if (x == -1) { return (Default); } // error no encontre el dato

    return (IniData.Substring(z, x – z)); // devuelvo el valor que busco
    }
    else
    { // no encontre ese value agrego ese value para ese key
    return (Default);
    }
    }
    else
    { // no encontre ese key lo agrego al final de archivo
    return (Default);
    }
    }
    else
    {// no tiene datos
    return (Default);
    }
    }
    }

    //*******************************************************************************

    • johnbarquin says:

      Hola Ingeleo, buen ejercicio de programación 🙂 , solo una observación, usando app.config y las funciones de System.Configuration, además de ahorrar esfuerzo de codificación, implica el uso de estándares y esto siempre es aconsejable. A partir de .NET, van quedando atrás las configuraciones por archivos .INI y por el registro de Windows.

  2. Carlos says:

    Gracias por el código, me ha ayudado mucho ya que soy principiante en C#.

    Lo que te quiero preguntar es como leo las variables de tipo string que creo en la lengüeta Setting de la propiedades del proyecto.

    Muchas gracias

    Carlos Pizzi

    • johnbarquin says:

      Si creaste de esta forma un parámetro llamado “miParametro”, puedes leerlo asi:

      string valor = Settings.Default.miParametro;

      Settings es una “concha” que crea propiedades tipificadas para cada parámetro que se define en tiempo de diseño. Si el parámetro fuera de tipo int, por ej. “altura” se lee asi:

      int altura = Settings.Default.altura;

      Con ConfigurationManager se leeria asi:

      int altura = Convert.ToInt32(ConfigurationManager.AppSettings[“altura”]);

      Observa el XML generado en App.config con Settings para que veas las diferencias de sintaxis entre ambos métodos.

      Saludos, John

  3. ariel says:

    hola estimado estoy tratando de usar tu clase pero me marca mo error esta linea cuando quiere hacer una resta.

    return (IniData.Substring(z, (x – z))); // devuelvo el valor que busco
    pint ade rojo el – . tenes idea que es?

    graciassss

  4. camila says:

    hola, hice la programacion como pusistes para escribir en el app.config, pero cuando reviso el archivo en el debug, persiste el valor inicial.
    porfis!!! ayudame

    • johnbarquin says:

      Si Camila, es que hay tres versiones del archivo de configuración. Supongamos que tu aplicación se llama MiApp.exe entonces tendrás:

      1- App.config (el original del código fuente). Este nunca se modifica por programa, solo si lo editas manualmente, y en este caso, se copia automaticamente a (2) y (3) a continuación.

      y cuando compilas, en bin\Debug Visual Studio te coloca dos más:

      2- App.exe.Config : este se usa cuando lo ejecutas como aplicación independiente, ej. desde Inicio -> Ejecutar
      Siempre se mantienen los cambios al salir de la aplicación, solo cambia si se edita el App.config original.

      3- App.vshost.exe.Config : se usa cuando lo ejecutas desde Visual Studio. Este se modifica según lo programes pero al terminar la ejecución VS lo restablece al original App.config. Quizás por eso no te des cuenta del cambio; puedes como comprobación colocar un Console.ReadKey() (suponiendo es una app de consola) antes que termine el programa y comprobar el cambio antes de salir.

      Espero esto te aclare lo que está sucediendo internamente, saludos

  5. ingeleo says:

    hoy por fin utilice la funcion y no tuve errores, me acabo de dar cuenta que el mundo evoluciona mas rapido que nosostros, tenia que haber usado esto antes, pero bueno…. hoy si lei y analice bien todo esto, jajaja, muy contento!!!, solo me tomo 8 min, jajaja y unas pocas lineas de codigo, eficiente esta funcion!!!, gracias!!!

  6. alexcuban says:

    El barco. jajja bueno solo quería decir que hoy en día el uso de las appconfig keys ya no esta muy de moda mas bien lo que se hace ahora es implementar clases con su respectiva configuracion de modo que cada modulo configurable estará bien localizado claro todo esto si se trata de un proyecto que se respete un ejemplo muy sencillo

    como .net sabe que en la seccion de configuracion ConnectionString es donde van a estar las cadenas de conexión globales a toda la aplicación? Pues muy simple ellos si crearon una clase que es la que se encarga de leer del web o app config ese nodo especifico del xml y la manera de leerlo etc. asi de sencillo.

    Saludos Barquin

  7. lvgstark says:

    Tengo una duda,

    Estoy haciendo una práctica de lo que has enseñado, y me sucede lo siguiente.

    1 – He creado un textbox donde guardo un parámetro y su valor

    2 – con un botón, puedo modificar el valor de ese parámetro

    3 – Quiero recuperar el valor modificado (que se ha guardado en el fichero .config) en otro textbox, pero no
    puedo recuperarlo. Solo funciona si cierro el form y lo vuelvo a ejecutar, però no me recupera las modificaciones en tiempo real.
    pregunta: ¿Me obliga a cerrar la aplicación para trabajar con modificaciones?

    un ejemplo sería si quiero guardar una cadena de conexión (le doy al botón guardar, pero no me lo deja recuperar despues de guardarla).

    Gracias

  8. Camilo Ruiz says:

    Yo hago algo como para intentar mantener un orden. Yo creo varias carpetas dentro de la solucion de visual studio, lógica, presentación y conexión. Dentro de la carpeta conexcion meti una clase que es la que se conecta con la base de datos y tambien cree el archivo xml. Yo hice esto:
    //xml

    //esta esta dentro de la carpeta de conexion
    //y esta clase esta dentro de esta misma carpeta pero no me retorna nada…
    class ConexionSQL
    {
    public string login;
    public string pass;
    public string IP;
    public string Database;
    public void CargarDatos(/*string Ruta*/)
    {
    this.IP = ConfigurationManager.AppSettings[“Ip”];
    System.Windows.Forms.MessageBox.Show(“la IP es “+this.IP);//no me retorna nada…

    }
    public void Abierta()
    {
    }
    public void Conectar()
    {
    }
    public void Cerrar()
    {
    }
    public void EjecutarComando(string Comando)
    {
    }
    public void ResultadoEjecutarComando(string Comando)
    {
    }
    }
    //no se cual sea el error

  9. Ivan says:

    Hola johnbarquin,
    Tu post ha sido de mucha ayuda, sin embargo tengo un problemita con una aplicación que estoy haciendo. Ésta tiene dos formularios. El formulario principal tiene un botón que sirve para desplegar el formulario secundario, el cual tiene tres pestañas o fichas. Utilizo un menú contextual para cambiar el título de dichas pestañas en tiempo de ejecución. Deseo que el nombre de esas pestañas persista utilizando el archivo de configuración.

    He seguido los pasos que mencionas en tu post y funciona, sin embargo, el nombre de las pestañas persiste solo si cierro toda la aplicación y la vuelvo a ejecutar. Si solo cierro el formulario secundario y lo vuelvo a mandar a llamar desde el formulario principal (sin terminar la aplicación), los nombres de las pestañas no persisten y no se porque.

    Este es mi archivo de configuración:

    Este evento del formulario secundario lo utilizo para cargar los datos:

    private void FrmCtrlSalidas_Load(object sender, EventArgs e)
    {
    // Cargar valores de configuración
    tabActuador1.Text = ConfigurationManager.AppSettings[“TituloTab1”];
    tabActuador2.Text = ConfigurationManager.AppSettings[“TituloTab2”];
    tabActuador3.Text = ConfigurationManager.AppSettings[“TituloTab3”];
    }

    Y este evento para guardarlos:

    private void FrmCtrlSalidas_FormClosing(object sender, FormClosingEventArgs e)
    {
    // Guardar valores de configuración
    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    config.AppSettings.Settings[“TituloTab1”].Value = tabActuador1.Text;
    config.AppSettings.Settings[“TituloTab2”].Value = tabActuador2.Text;
    config.AppSettings.Settings[“TituloTab3”].Value = tabActuador3.Text;
    config.Save(ConfigurationSaveMode.Minimal);
    }

    Espero que puedas ayudarme, de antemano, muchas gracias.

    • Ivan says:

      Bueno, ya lo resolví 🙂
      Aqui está lo que hice:

      1. Me fui al diseñador de proyectos (clic derecho sobre el proyecto -> propiedades) y seleccioné la pestaña Configuración. Me aparecía un texto que decia: “Este proyecto no contiene un archivo de configuración predeterminado. Haga clic para crear uno”. Le di clic y me creo uno nuevo archivo llamado Settings.settings, el cual me lo coloco dentro de la carpeta Propierties que viene por defecto al crear un nuevo proyecto. Creo que antes no me aparecía ese archivo porque sin querer lo borre.

      2. Si ya se dispone de un archivo Settings.settings, en la ventana del diseñador de proyectos, en el tab Configuración aparecerá una especie de DataGridView (una tabla) y en ella agregamos/editamos todas las configuraciones que querramos. En la columna nombre agregamos el nombre de la configuración (creo que no debe llevar espacios). En la columna tipo seleccionamos el tipo que datos que queremos agregar/recuperar. En la columna ámbito seleccionamos usuarios para tener lectura/escritura de las configuraciones. En la columna valor escribimos el valor por defecto de esa configuración.

      3. Guardamos los cambios.

      4. En mi código use:

      private void FrmCtrlSalidas_Load(object sender, EventArgs e)
      {
      // Cargar valores de configuración
      tabActuador1.Text = Settings.Default.TitleTab01;
      tabActuador2.Text = Settings.Default.TitleTab02;
      tabActuador3.Text = Settings.Default.TitleTab03;
      }

      private void FrmCtrlSalidas_FormClosing(object sender, FormClosingEventArgs e)
      {
      // Guardar valores de configuración
      Settings.Default.TitleTab01 = tabActuador1.Text;
      Settings.Default.TitleTab02 = tabActuador2.Text;
      Settings.Default.TitleTab03 = tabActuador3.Text;

      Settings.Default.Save();
      }

      Gracias de nuevo johnbarquin, use tu respuesta a Carlos (mayo 20, 2009 en 11:44 am)

  10. josemol says:

    gracias … me has ayudado.

  11. alexander lizano says:

    muy bien explicado!!! gracias men.

  12. ejrr1085 says:

    Implemente tu código en una biblioteca de clases para conectarme con una base de datos, cree el archivo App.config, el cual está en la raíz del proyecto y es el siguiente:

    Luego quise llamar a los datos de este archivo en una clase de esta manera:

    dataSource = ConfigurationManager.AppSettings[“dataSource”];
    initialCatalog = ConfigurationManager.AppSettings[“initialCatalog”];
    userID = ConfigurationManager.AppSettings[“userID”];password = ConfigurationManager.AppSettings[“password”];

    Pero no pasa ningún valor.

  13. Yelinna says:

    En la época del VB6 se escribían los datos de la aplicación en archivos .ini, o directamente en el registro. Esto era muy complicado y podía tirar excepciones si el usuario no tenía los privilegios necesarios. Con app.Config se resuelven estos problemas.

  14. oscar says:

    Hola, como puedo utilizar esto para cambiar el ConnectionStrings? he intentado el código que pones arriba pero como bien explicas, es solo para el appSettings, gracias por tu ayuda

  15. Roger says:

    Gracias men, codigo añadido a la libreria de mi proyecto 🙂

  16. Me fue de utilidad tu codigo; pero le falta esta linea ConfigurationManager.RefreshSection(“appSettings”);
    Para refrescar los cambios y no tener que cerrar el aplicativo para ver los cambios realizados.

  17. mauroldanr says:

    Hola si alguien sabe lo siguiente:
    tengo una clave como la siguiente:

    Lo que estoy tratando de hacer es en mi clase C# cuando leo el archivo .properties
    string key1= ConfigurationManager.AppSettings[“key1”];

    quiero enviar el valor del parametro que define {0} en el archivo .properties, para que luego el string final resutlante sea “name: yourName”

    Gracias

  18. Andres Hernandez says:

    Hola Muy buena tu información y la voy a poner en practica y cambiar de archivos ini a app.config pero tengo un problema que es que tengo unos servicios que se encargan de pasar la información de una BD a otra y tengo un modulo de configuración que lo corro desde un pendrive el cual me busca los servicio instalados en la maquina y me carga la información del archivo ini y la manipulo pero hasta ahora investigando no encuentro como leer el archivo app.config desde otra ubicación siempre me lee el que esta donde este el ejecutable. Gracias y espero que puedas ayudarme

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: