2015-04-02 2 views
1

Название типа говорит все. У меня есть приложение, которое определяет некоторые пользовательские настройки, которые в конечном итоге хранятся .NET в определенном пользователем файле для этого приложения..Net может приложение «В» читать настройки пользователя для приложения «А»?

У меня есть тесно связанное приложение поддержки, которое должно прочитать некоторые из этих же настроек, но я не знаю, возможно ли это программно? Все примеры, которые я видел, читальное свойство зачитывают свойства, связанные с запущенным приложением ..

Майклом

+0

Его можно, но если А, используя настройки по умолчанию, это не будет легко (есть трудно предсказать хэш в пути). Можно ли сделать A выписать собственный файл настроек в известную подпапку «Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData)»? –

+0

Да, я думаю, что это лучший подход. –

ответ

0

Когда я бежал, чтобы это в прошлом то, что я делаю, я экономлю, чтобы CommonApplicationSettings через xml с моими настройками. Затем у меня есть модель и читатель/писатель для настроек в общем C.dll, которые разделяют A и B.

Вот пример класса читателя/писателя, который я сделал. Он содержит настройки в свойстве, в любое время, когда файл был изменен на жестком диске, загружается новая копия настроек и возникает событие 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; 
     } 
    } 
} 
0

Существует очень прямой способ читать настройки другого приложения с методом ConfigurationManager.OpenExeConfiguration.

Пример:

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

Похоже, что он прочитает XML-файл из конфигурационного файла приложения - но я не думаю, что он подберет любые «переопределения», т. Е. Значения, измененные из значений файла конфигурации и сохраненные через Properties.Settings.Defaults .Сохранить(). –

Смежные вопросы