简体   繁体   中英

.Net can app “B” read the user settings for app “A”?

The title sort of says it all. I have on app that defines some user settings, which end up being stored by .NET in a user specific file, for that app.

I have a closely related support app that needs to read some of these same settings, but I don't know if this is possible programatically? All the examples I've seen of reading properties read out the properties associated with the running application..

Michael

When I have run in to this in the past what I do is I save in to CommonApplicationSettings a xml file with my settings. I then have the model and the reader/writer for the settings in a common C.dll that A and B both share.

Here is a example class of a reader/writer I made. It holds the settings in a property, any time the file is changed on the hard drive a new copy of the settings is loaded and the PropertyChanged event is raised.

Both programs create a copy of Configuration then listen to the PropertyChanged event. If it gets a signal that a change happened the programs re-read the settings out of Configuration.Settings and use them as their active values.

public sealed class Configuration : INotifyPropertyChanged, IDisposable
{
    private static readonly ILog Logger = LogManager.GetLogger(typeof(Configuration));


    private readonly FileSystemWatcher _fileSystemWatcher;
    public string SettingsPath { get; private set; }
    private ConfigurationSettings _settings;

    public Configuration()
    {
        const string settingsFileName = "Settings.xml";
        const string programName = "App A";

        SettingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), programName, settingsFileName);

        if (!File.Exists(SettingsPath))
        {
            CreateDefaultFile();
        }

        //Read in the settings.
        ReadSettingsFromFile();


        _fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(SettingsPath), settingsFileName);
        _fileSystemWatcher.BeginInit();
        _fileSystemWatcher.Changed += FileSystemWatcherOnChanged;
        _fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
        _fileSystemWatcher.EndInit();
        _fileSystemWatcher.EnableRaisingEvents = true;
    }

    public ConfigurationSettings Settings
    {
        get { return _settings; }
        private set
        {
            if (Equals(value, _settings))
            {
                return;
            }
            _settings = value;
            OnPropertyChanged("Settings");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void ReadSettingsFromFile()
    {
        Logger.Debug("Reading settings from the file.");

        var serializer = new XmlSerializer(typeof(ConfigurationSettings));
        using (FileStream settingsStream = File.Open(SettingsPath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            Settings = (ConfigurationSettings)serializer.Deserialize(settingsStream);
        }

    }

    private async void FileSystemWatcherOnChanged(object sender, FileSystemEventArgs fileSystemEventArgs)
    {
        _fileSystemWatcher.EnableRaisingEvents = false;

        Logger.Debug(new {fileSystemEventArgs.ChangeType, fileSystemEventArgs.FullPath, fileSystemEventArgs.Name});

        //Add a pause to allow for the file to be finished writing.
        await TaskEx.Delay(TimeSpan.FromSeconds(1));

        ReadSettingsFromFile();

        _fileSystemWatcher.EnableRaisingEvents = true;
    }

    /// <summary>
    ///     Creates the default settings file
    /// </summary>
    private void CreateDefaultFile()
    {

        var directoryInfo = Directory.CreateDirectory(Path.GetDirectoryName(SettingsPath));
        //add rights for other users to modify the directory.
        var security = directoryInfo.GetAccessControl();
        security.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), FileSystemRights.Modify, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
        directoryInfo.SetAccessControl(security);

        Settings = new ConfigurationSettings();
        Save();
    }

    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    public void Save()
    {
        bool oldState = false;

        if (_fileSystemWatcher != null)
        {
            oldState = _fileSystemWatcher.EnableRaisingEvents;
        }

        try
        {
            //Disable events while the value is written.
            if (_fileSystemWatcher != null)
            {
                _fileSystemWatcher.EnableRaisingEvents = false;
            }

            var serializer = new XmlSerializer(typeof(ConfigurationSettings));

            using (var filestream = new FileStream(SettingsPath, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                serializer.Serialize(filestream, Settings);
            }
        }
        finally
        {
            if (_fileSystemWatcher != null)
            {
                _fileSystemWatcher.EnableRaisingEvents = oldState;
            }
        }
    }

    #region IDisposable Pattern

    private bool _disposed;

    /// <summary>
    ///     Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    ///     Finalizes this instance (called prior to garbage collection by the CLR)
    /// </summary>
    ~Configuration()
    {
        Dispose(false);
    }

    private void Dispose(bool fromUserCode)
    {
        if (!_disposed)
        {
            if (fromUserCode)
            {
                if (_fileSystemWatcher != null)
                {
                    _fileSystemWatcher.Dispose();
                }
            }
        }
        _disposed = true;
    }

    #endregion
}

Here is what my ConfigurationSettings class looks like.

/// <summary>
/// Used as a container to represent the settings of the program
/// </summary>
[Serializable]
[XmlType(AnonymousType = false)]
public sealed class ConfigurationSettings : IEquatable<ConfigurationSettings>
{
    private TimeSpan _uploadInterval;
    private TimeSpan _pauseBetweenModules;
    private static readonly TimeSpan UploadIntervalDefault = new TimeSpan(0, 0, 30, 0);
    private static readonly TimeSpan PauseBetweenModulesDefault = new TimeSpan(0,0,0,5);
    private const int InitialBatchSizeDefault = 100;

    public ConfigurationSettings()
    {
        InitialBatchSize = InitialBatchSizeDefault;
        UploadInterval = UploadIntervalDefault;
        PauseBetweenModules = PauseBetweenModulesDefault;
        DatabaseInstances = new ObservableCollection<DatabaseInstance>();
        UploadPulseData = true;
    }

    /// <summary>
    /// Will upload the pulse finical data
    /// </summary>
    public bool UploadPulseData { get; set; }

    /// <summary>
    /// The batch size the auto windowing function will use for its initial value for the upload module.
    /// </summary>
    public int InitialBatchSize { get; set; }

    /// <summary>
    /// The ammount of time a pause should be inserted between modules to allow the program to do any work that
    /// has processing to do.
    /// </summary>
    [XmlIgnore] //Xml can not serialize a TimeSpan, so we use the hidden property PauseBetweenModulesInMilliseconds during serialization.
    public TimeSpan PauseBetweenModules
    {
        get { return _pauseBetweenModules; }
        set { _pauseBetweenModules = value; }
    }

    // Hidden property for serialization
    [XmlElement("PauseBetweenModulesInMilliseconds")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public long PauseBetweenModulesInMilliseconds
    {
        get { return _pauseBetweenModules.Ticks / TimeSpan.TicksPerMillisecond; }
        set { _pauseBetweenModules = new TimeSpan(value * TimeSpan.TicksPerMillisecond); }
    }

    /// <summary>
    /// The length of time between upload batches.
    /// </summary>
    [XmlIgnore] 
    public TimeSpan UploadInterval
    {
        get { return _uploadInterval; }
        set { _uploadInterval = value; }
    }

    // Hidden property for serialization
    [XmlElement("UploadIntervalInMinutes")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public long UploadIntervalInMinutes
    {
        get { return _uploadInterval.Ticks / TimeSpan.TicksPerMinute; }
        set { _uploadInterval = new TimeSpan(value * TimeSpan.TicksPerMinute);}
    }

    /// <summary>
    /// The databases to run uploads against.
    /// </summary>
    public List<DatabaseInstance> DatabaseInstances { get; set; }

    //We override Equals to make OnPropertyChanged less spammy, if the same file is loaded with the same settings it keeps the event from being raised.
    public bool Equals(ConfigurationSettings other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return _uploadInterval.Equals(other._uploadInterval) && 
               _pauseBetweenModules.Equals(other._pauseBetweenModules) &&
               InitialBatchSize == other.InitialBatchSize && 
               UploadPulseData == other.UploadPulseData &&
               DatabaseInstances.SequenceEqual(other.DatabaseInstances);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        return obj is ConfigurationSettings && Equals((ConfigurationSettings)obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = _uploadInterval.GetHashCode();
            hashCode = (hashCode*397) ^ _pauseBetweenModules.GetHashCode();
            hashCode = (hashCode*397) ^ InitialBatchSize;
            hashCode = (hashCode*397) ^ UploadPulseData.GetHashCode();
            if (DatabaseInstances != null)
            {
                foreach (var databaseInstance in DatabaseInstances)
                {
                    hashCode = (hashCode * 397) ^ (databaseInstance != null ? databaseInstance.GetHashCode() : 0);
                }
            }
            return hashCode;
        }
    }
}

There is a very straight-forward way to read another app's settings with the ConfigurationManager.OpenExeConfiguration method.

Example:

var config = System.Configuration.ConfigurationManager.OpenExeConfiguration(exePath);
var x = config.AppSettings.Settings["setting"].Value;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM