.Net可以通过app“B”读取应用“A”的用户设置吗?

时间:2015-04-02 18:43:51

标签: .net settings

标题类型说明了一切。 我在应用程序上定义了一些用户设置,最终由.NET存储在用户特定文件中,用于该应用程序。

我有一个密切相关的支持应用程序需要阅读其中一些相同的设置,但我不知道这是否可能以编程方式进行?我在阅读属性时看到的所有示例都会读出与正在运行的应用程序相关联的属性。

迈克尔

2 个答案:

答案 0 :(得分:0)

当我过去遇到这种情况时,我所做的就是使用我的设置将一个xml文件保存到CommonApplicationSettings中。然后,我将模型和读者/作者用于A和B共享的公共C.dll中的设置。

这是我制作的读者/作家的示例类。它保存属性中的设置,只要在硬盘驱动器上更改文件,就会加载新的设置副本并引发PropertyChanged事件。

两个程序都会创建Configuration的副本,然后收听PropertyChanged事件。如果它收到发生更改的信号,则程序会重新读取Configuration.Settings中的设置并将其用作活动值。

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
}

这是我的ConfigurationSettings类的样子。

/// <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;
        }
    }
}

答案 1 :(得分:0)

使用ConfigurationManager.OpenExeConfiguration方法可以非常直接地阅读其他应用的设置。

示例:

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