¿Cómo se mantienen las configuraciones de user.config en diferentes versiones de ensamblaje en .net?

Básicamente, el problema es que cada vez que cambia la versión del ensamblaje (es decir, el usuario instala una nueva versión de la aplicación) todas sus configuraciones se restablecen los valores predeterminados (o más exactamente, se crea un nuevo archivo user.config en una carpeta con una versión diferente número como el nombre)

¿Cómo puedo mantener la misma configuración al actualizar versiones, ya que parece desaconsejarse el uso de archivos ini o el registro?

Cuando usamos Clickonce, parecía ser capaz de manejar esto, así que parece que debería poder hacerse, pero no estoy seguro de cómo.

ApplicationSettingsBase tiene un método llamado Actualización que migra todas las configuraciones de la versión anterior.

Para ejecutar la fusión siempre que publique una nueva versión de su aplicación, puede definir un indicador booleano en su archivo de configuración que por defecto es verdadero. Nómbrelo UpgradeRequired o algo similar.

Luego, al inicio de la aplicación, comprueba si la bandera está configurada y, en caso afirmativo, llame al método de actualización , establezca la bandera en falso y guarde su configuración.

if (Settings.Default.UpgradeRequired) { Settings.Default.Upgrade(); Settings.Default.UpgradeRequired = false; Settings.Default.Save(); } 

Obtenga más información sobre el método de actualización en MSDN . La versión GetPreviousVersion también puede valer la pena si necesita realizar alguna combinación personalizada.

Sé que ha pasado un tiempo … En una aplicación de My.Settings.Upgrade() , simplemente llame a My.Settings.Upgrade() antes de cargarlos. Esto obtendrá la última configuración, ya sea la versión actual o una versión anterior.

Si sus cambios en los ajustes del usuario se realizan mediante progtwigción, ¿qué le parece mantener una copia de (solo) las modificaciones a los ajustes del usuario en un archivo separado, por ejemplo, ajustes de usuario.customized?

Probablemente aún desee mantener y cargar las configuraciones modificadas en user.settings también. Pero de esta manera, cuando instale una versión más nueva de su aplicación con su versión más nueva de user.settings, puede preguntar al usuario si desea continuar utilizando su configuración modificada copiándola nuevamente en el nuevo user.settings. Puede importarlos al por mayor, o ser más elegante y pedirle al usuario que confirme qué configuración desea seguir usando.

EDITAR: leo demasiado rápido sobre la parte “más precisa” sobre las versiones de ensamblaje, lo que provoca que se instalen nuevos ajustes de usuario en un nuevo directorio específico de la versión. Por lo tanto, la idea anterior probablemente no lo ayude, pero puede proporcionarle algo de reflexión.

Así es como lo manejé:

 public virtual void LoadSettings(ServiceFileFormBaseSettings settings = null, bool resetSettingsToDefaults = false) { if (settings == null) return; if (resetSettingsToDefaults) settings.Reset(); else { settings.Reload(); if (settings.IsDefault) settings.Upgrade(); } this.Size = settings.FormSize; 

}

y en la clase de configuración, definí la propiedad IsDefault:

 // SaveSettings always sets this to be FALSE. // This will have the default value TRUE when first deployed, or immediately after an upgrade. // When the settings exist, this is false. // [UserScopedSettingAttribute()] [DefaultSettingValueAttribute("true")] public virtual bool IsDefault { get { return (bool)this["IsDefault"]; } set { this["IsDefault"] = value; } } 

En SaveSettings, establezco IsDefault en falso:

 public virtual void SaveSettings(ServiceFileFormBaseSettings settings = null) { if (settings == null) // ignore calls from this base form, if any return; settings.IsDefault = false; settings.FormSize = this.Size; settings.Save(); } 

Aquí está mi investigación en caso de que alguien más esté teniendo problemas con la migración de las configuraciones que se han cambiado o eliminado. El problema básico es que GetPreviousVersion() no funciona si ha cambiado el nombre o eliminado la configuración en la nueva versión de su aplicación. Por lo tanto, debe mantener la configuración en su clase de Settings , pero agregue algunos atributos / artefactos para que no los use inadvertidamente en el código en otro lugar, por lo que es obsoleto. Un ejemplo de configuración obsoleta se vería así en VB.NET (puede traducirse fácilmente a C #):

  Public Property OldSettingName() As String Get Throw New NotSupportedException("This property is obsolete") End Get Set Throw New NotSupportedException("This property is obsolete") End Set End Property 

Asegúrese de agregar esta propiedad al mismo espacio de nombres / clase que tiene la configuración de su aplicación. En VB.NET, esta clase se llama MySettings y está disponible en My espacio de nombres. Puede utilizar la funcionalidad de clase parcial para evitar que su configuración obsoleta se mezcle con su configuración actual.

Crédito completo a jsharrison por publicar un excelente artículo sobre este tema. Puedes leer más detalles al respecto allí.

Aquí hay una variación de las soluciones presentadas aquí que encapsula la lógica de actualización en una clase abstracta de la que las clases de configuración pueden derivarse.

Algunas soluciones propuestas usan un atributo DefaultSettingsValue para especificar un valor que indica cuándo no se cargaron las configuraciones anteriores. Mi preferencia es simplemente usar un tipo cuyo valor predeterminado lo indique. Como un bono, un DateTime? es información de depuración útil.

 public abstract class UserSettingsBase : ApplicationSettingsBase { public UserSettingsBase() : base() { // Accessing a property attempts to load the settings for this assembly version // If LastSaved has no value (default) an upgrade might be needed if (LastSaved == null) { Upgrade(); } } [UserScopedSetting] public DateTime? LastSaved { get { return (DateTime?)this[nameof(LastSaved)]; } private set { this[nameof(LastSaved)] = value; } } public override void Save() { LastSaved = DateTime.Now; base.Save(); } } 

Derivar de UserSettingsBase:

 public class MySettings : UserSettingsBase { [UserScopedSetting] public string SomeSetting { get { return (string)this[nameof(SomeSetting)]; } set { this[nameof(SomeSetting)] = value; } } public MySettings() : base() { } } 

Y úsala:

 // Existing settings are loaded and upgraded if needed MySettings settings = new MySettings(); ... settings.SomeSetting = "SomeValue"; ... settings.Save();