@VB1963 Ich hab das ganze mal nach C# übertragen.
Ergebnis: Die Settings in C# funktionieren etwas anders als in VB.NET. Das ist vielleicht für den @ErfinderDesRades interessant.
Der linear übersetzte Code generiert auch mit
Deswegen bin ich da wieder auf die Lösung mit
UserSettingsProvider
Ergebnis: Die Settings in C# funktionieren etwas anders als in VB.NET. Das ist vielleicht für den @ErfinderDesRades interessant.
Der linear übersetzte Code generiert auch mit
SetDataFile()
den DLL-Namen als Settings-File.Deswegen bin ich da wieder auf die Lösung mit
GetModuleFileName()
zurückgegangen. Vielleicht findetr ja jemand da auch noch eine elegante Lösung ohne explizite separate Initialisierung.
UserSettingsProvider.cs
MySettings.cs
C#-Quellcode
- using System;
- using System.Configuration;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.IO;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.Text;
- namespace MyProvider
- {
- /// <summary>
- /// Dieser Provider speichert die betroffenen Settings-Einstellungen in eine eigene .exe.config.xml-Datei.
- /// Diese Datei liegt im Arbeitsverzeichnis der Anwendung.
- /// HINWEISE:
- /// Die ApplicationName-Property erstellt die ProduktName-Eigenschaft von der My.Application.Info.ProduktName
- /// Hier sollte in den Projekteigenschaften/Anwendung/Assemblyinformationen die Eigenschaft ProduktName = AssemblyName gestellt sein!
- /// </summary>
- public class UserSettingsProvider : SettingsProvider, IApplicationSettingsProvider
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- [PreserveSig]
- public static extern uint GetModuleFileName
- ([In]IntPtr hModule, [Out]StringBuilder lpFilename, [In][MarshalAs(UnmanagedType.U4)] int nSize);
- public override string ApplicationName { get; set; }
- // hier wird der Produktname von der Assembly angegeben
- public override string Name { get { return "UserSettingsProvider"; } }
- private Dictionary<string, object> Datas;
- private FileInfo DataFile { get; set; }
- private string AppPath { get; set; }
- public UserSettingsProvider()
- {
- // Will write the current executable's complete path into exePath
- StringBuilder sb = new StringBuilder(1024);
- uint pathLen = UserSettingsProvider.GetModuleFileName(IntPtr.Zero, sb, sb.Capacity);
- if (pathLen >= 1024)
- {
- throw new ArgumentOutOfRangeException("StringBuilder() too small");
- }
- string exePath = sb.ToString();
- FileInfo fi = new FileInfo(exePath);
- this.ApplicationName = System.IO.Path.GetFileNameWithoutExtension(exePath);
- // in der Debug-Version auf dieselben Settings zugreifen
- if (ApplicationName.ToLower().EndsWith(".vshost"))
- {
- this.ApplicationName = System.IO.Path.GetFileNameWithoutExtension(this.ApplicationName);
- }
- this.AppPath = fi.DirectoryName;
- this.DataFile = new FileInfo(Path.Combine(this.AppPath, string.Concat(ApplicationName, ".exe.config.dat")));
- this.Datas = new Dictionary<string, object>();
- }
- public override void Initialize(string name, NameValueCollection config)
- {
- base.Initialize(this.ApplicationName, config);
- }
- /// <summary>
- /// SetPropertyValues wird erst abgearbeitet, wenn ApplicationSettingsBase.Save durchgeführt wird.
- /// ApplicationSettingsBase stellt sicher, dass für jeden einzelnen Provider nur seine markierten Werte herangenommen werden.
- /// Egal, ob der Provider auf einer Einzel-Einstellung angesetzt ist oder ob klassenweit die Einstellung angegeben wurde.
- /// Wenn Einstellungen nicht verändert wurden, müssen sie nicht gespeichert werden!
- /// Anwendungsspezifische Einstellungen können nicht geändert werden und werden daher auch nicht gespeichert!
- /// </summary>
- /// <param name="context"></param>
- /// <param name="collection"></param>
- public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
- {
- foreach (SettingsPropertyValue prpValue in collection)
- {
- if (!prpValue.IsDirty || (prpValue.SerializedValue == null))
- {
- continue;
- }
- if (this.IsApplicationScoped(prpValue.Property))
- {
- continue;
- }
- this.Datas[prpValue.Name] = prpValue.SerializedValue;
- }
- this.SaveBinary(this.DataFile, this.Datas);
- }
- public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
- {
- if (this.DataFile.Exists)
- {
- this.Datas = this.LoadBinary(DataFile);
- }
- SettingsPropertyValueCollection col = new SettingsPropertyValueCollection();
- foreach (SettingsProperty prp in collection)
- {
- SettingsPropertyValue Value = new SettingsPropertyValue(prp);
- if (this.Datas.ContainsKey(prp.Name))
- {
- Value = GetPropertyValue(prp);
- }
- // Wert von Datas einlesen
- col.Add(Value);
- }
- return col;
- }
- /// <summary>
- /// Nur benutzerspezifische Eigenschaften sind zulässig.
- /// Wenn eine Eigenschaft keinen Wert hat, wird der Defaultwert geladen.
- /// </summary>
- /// <param name="prp"></param>
- private SettingsPropertyValue GetPropertyValue(SettingsProperty prp)
- {
- SettingsPropertyValue value = new SettingsPropertyValue(prp);
- if (this.IsUserScoped(prp))
- {
- value.SerializedValue = this.Datas[prp.Name];
- }
- value.IsDirty = false;
- return value;
- }
- /// <summary>
- /// Test auf anwendungsspezifische Eigenschaft
- /// </summary>
- /// <param name="prop"></param>
- private bool IsApplicationScoped(SettingsProperty prop)
- {
- return this.HasSettingScope(prop, typeof(ApplicationScopedSettingAttribute));
- }
- /// <summary>
- /// Test auf benutzerdefinierte Eigenschaft
- /// </summary>
- /// <param name="prop"></param>
- private bool IsUserScoped(SettingsProperty prop)
- {
- return this.HasSettingScope(prop, typeof(UserScopedSettingAttribute));
- }
- /// <summary>
- /// prüft auf erlaubte Einstellung, so wie es der LocalFileSettingsProvider auch macht ...
- /// </summary>
- /// <param name="prop"></param>
- /// <param name="attributeType"></param>
- private bool HasSettingScope(SettingsProperty prop, Type attributeType)
- {
- bool isAppScoped = prop.Attributes[typeof(ApplicationScopedSettingAttribute)] != null;
- bool isUserScoped = prop.Attributes[typeof(UserScopedSettingAttribute)] != null;
- if (isUserScoped && isAppScoped)
- {
- throw new ConfigurationErrorsException("BothScopeAttributes: " + prop.Name);
- }
- if (!isUserScoped && !isAppScoped)
- {
- throw new ConfigurationErrorsException("NoScopeAttributes: " + prop.Name);
- }
- if (object.ReferenceEquals(attributeType, typeof(ApplicationScopedSettingAttribute)))
- {
- return isAppScoped;
- }
- if (object.ReferenceEquals(attributeType, typeof(UserScopedSettingAttribute)))
- {
- return isUserScoped;
- }
- return false;
- }
- /// <summary>
- /// Daten binär speichern
- /// </summary>
- /// <param name="DataFile"></param>
- /// <param name="Datas"></param>
- private void SaveBinary(FileInfo DataFile, Dictionary<string, object> Datas)
- {
- this.DeleteLocalPathUserSettings();
- using (Stream fs = File.Create(DataFile.FullName))
- {
- BinaryFormatter binfmt = new BinaryFormatter();
- binfmt.Serialize(fs, Datas);
- }
- }
- /// <summary>
- /// falls der LocalUserAppDataPath vorhanden ist,
- /// wird der Ordner mit allen untergeordneten Verzeichnissen gelöscht
- /// </summary>
- private void DeleteLocalPathUserSettings()
- {
- DirectoryInfo di = new DirectoryInfo(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath);
- di = di.Parent.Parent.Parent;
- if (di.Exists)
- {
- di.Delete(true);
- }
- }
- /// <summary>
- /// binäre Daten laden
- /// </summary>
- /// <param name="DataFile"></param>
- private Dictionary<string, object> LoadBinary(FileInfo DataFile)
- {
- using (Stream fs = File.Open(DataFile.FullName, FileMode.Open))
- {
- BinaryFormatter binfmt = new BinaryFormatter();
- return (Dictionary<string, object>)binfmt.Deserialize(fs);
- }
- }
- #region "IApplicationSettingsProvider Members"
- /// <summary>
- /// Abrufen der letzten Version der Settingseigenschaft
- /// </summary>
- /// <param name="context"></param>
- /// <param name="property"></param>
- public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property)
- {
- SettingsPropertyValue prpValue = new SettingsPropertyValue(property);
- if (this.Datas.ContainsKey(property.Name))
- {
- prpValue.PropertyValue = this.Datas[property.Name];
- }
- return prpValue;
- }
- /// <summary>
- /// wieder auf die Defaultwerte der Settings zurücksetzen!
- /// </summary>
- /// <param name="context"></param>
- public void Reset(SettingsContext context)
- {
- if (this.DataFile.Exists)
- {
- this.Datas.Clear();
- this.SaveBinary(this.DataFile, this.Datas);
- }
- }
- /// <summary>
- /// ErfinderDesRades
- /// fehlende Settings werden sofort der Sammlung entfernt
- /// neue hinzugekommene Settings werden beim nächsten Speichervorgang gesichert
- /// </summary>
- /// <param name="context"></param>
- /// <param name="properties"></param>
- public void Upgrade(SettingsContext context, SettingsPropertyCollection properties)
- {
- if (this.Datas.Count == 0 && this.DataFile.Exists)
- {
- this.Datas = this.LoadBinary(this.DataFile);
- }
- List<string> toDelete = this.Datas.Keys.Except(
- from SettingsProperty prop in properties
- select prop.Name).ToList<string>();
- toDelete.ForEach(delegate(string str)
- {
- this.Datas.Remove(str);
- });
- }
- #endregion
- }
- }
C#-Quellcode
- namespace TestApplication.Properties
- // Der Name dieses Namespaces muss an die Applikationangepasst werden
- {
- /// <summary>
- /// mit diesem Verweis wird der eigene UserSettingsProvider dem Programm untergeschoben
- /// </summary>
- [System.Configuration.SettingsProvider(typeof(MyProvider.UserSettingsProvider))]
- internal sealed partial class Settings
- {
- }
- }
Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert!
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert!