public void Load()
        {
            if (File.Exists(_settingsFile))
            {
                lock (this.SettingsLock)
                {
                    XmlReaderSettings readerSettings = new XmlReaderSettings();
                    readerSettings.CheckCharacters  = true;
                    readerSettings.CloseInput       = true;
                    readerSettings.ConformanceLevel = ConformanceLevel.Document;
                    readerSettings.IgnoreComments   = true;
                    readerSettings.IgnoreWhitespace = true;

                    using (XmlReader reader = XmlReader.Create(_settingsFile, readerSettings))
                    {
                        while (reader.Read())
                        {
                            if (reader.IsStartElement())
                            {
                                switch (reader.Name)
                                {
                                case ElementXml:
                                case ElementSettings:
                                    // do nothing
                                    break;

                                case ElementIsLoggingEnabled:
                                    try
                                    {
                                        this.IsLoggingEnabled = Convert.ToBoolean(reader.ReadString(), CultureInfo.InvariantCulture);
                                    }
                                    catch
                                    {
                                        this.IsLoggingEnabled = false;
                                    }
                                    break;

                                case ElementRegistrationEmail:
                                    try
                                    {
                                        this.RegistrationEmail = CatfoodCrypto.DecryptString(reader.ReadString(), _appName);
                                    }
                                    catch
                                    {
                                        this.RegistrationEmail = null;
                                    }
                                    break;

                                case ElementRegistrationKey:
                                    try
                                    {
                                        this.RegistrationKey = Convert.ToInt32(reader.ReadString(), CultureInfo.InvariantCulture);
                                    }
                                    catch
                                    {
                                        this.RegistrationKey = 0;
                                    }
                                    break;

                                case ElementUseProxyServer:
                                    try
                                    {
                                        this.UseProxyServer = Convert.ToBoolean(reader.ReadString(), CultureInfo.InvariantCulture);
                                    }
                                    catch
                                    {
                                        this.UseProxyServer = false;
                                    }
                                    break;

                                case ElementUseProxyServerCredentials:
                                    try
                                    {
                                        this.UseProxyServerCredentials = Convert.ToBoolean(reader.ReadString(), CultureInfo.InvariantCulture);
                                    }
                                    catch
                                    {
                                        this.UseProxyServerCredentials = false;
                                    }
                                    break;

                                case ElementProxyAddress:
                                    try
                                    {
                                        this.ProxyAddress = reader.ReadString();
                                    }
                                    catch
                                    {
                                        this.ProxyAddress = null;
                                    }
                                    break;

                                case ElementProxyDomain:
                                    try
                                    {
                                        this.ProxyDomain = CatfoodCrypto.DecryptString(reader.ReadString(), _appName);
                                    }
                                    catch
                                    {
                                        this.ProxyDomain = null;
                                    }
                                    break;

                                case ElementProxyPass:
                                    try
                                    {
                                        this.ProxyPass = CatfoodCrypto.DecryptString(reader.ReadString(), _appName);
                                    }
                                    catch
                                    {
                                        this.ProxyPass = null;
                                    }
                                    break;

                                case ElementProxyPort:
                                    try
                                    {
                                        this.ProxyPort = Convert.ToInt32(reader.ReadString(), CultureInfo.InvariantCulture);
                                    }
                                    catch
                                    {
                                        this.ProxyPort = 8080;
                                    }
                                    break;

                                case ElementProxyUser:
                                    try
                                    {
                                        this.ProxyUser = CatfoodCrypto.DecryptString(reader.ReadString(), _appName);
                                    }
                                    catch
                                    {
                                        this.ProxyUser = null;
                                    }
                                    break;

                                case ElementInstanceId:
                                    try
                                    {
                                        this.InstanceId = new Guid(reader.ReadString());
                                    }
                                    catch
                                    {
                                        this.InstanceId = Guid.Empty;
                                    }
                                    break;

                                case ElementInstallDate:
                                    try
                                    {
                                        this.InstallDate = new DateTime(Convert.ToInt64(reader.ReadString(), CultureInfo.InvariantCulture));
                                    }
                                    catch
                                    {
                                        this.InstallDate = DateTime.Now;
                                    }
                                    break;

                                case ElementNextUpdateCheck:
                                    try
                                    {
                                        this.NextUpdateCheck = new DateTime(Convert.ToInt64(reader.ReadString(), CultureInfo.InvariantCulture));
                                    }
                                    catch
                                    {
                                        this.NextUpdateCheck = DateTime.Now;
                                    }
                                    break;

                                default:
                                    // give derrived class a chance to handle elements not related to us
                                    try
                                    {
                                        LoadFromXmlElement(reader.Name, reader.ReadString());
                                        LoadFromXmlReader(reader.Name, reader);
                                    }
                                    catch { }
                                    break;
                                }
                            }
                        }
                    }
                }

                UpdateProxyServer();
            }

            // generate an instance Id if needed
            if (this.InstanceId == Guid.Empty)
            {
                this.InstanceId = Guid.NewGuid();
            }
        }
        public void Save()
        {
            Exception lastException = null;
            int       retryAttempt  = 0;
            int       sleepFor      = SaveRetryWaitMS;

            while (retryAttempt <= SaveRetryLimit)
            {
                lastException = null;

                try
                {
                    lock (this.SettingsLock)
                    {
                        // create the settings folder if necessary
                        if (!Directory.Exists(_settingsFolder))
                        {
                            Directory.CreateDirectory(_settingsFolder);
                        }

                        XmlWriterSettings writerSettings = new XmlWriterSettings();
                        writerSettings.CheckCharacters  = true;
                        writerSettings.CloseOutput      = true;
                        writerSettings.ConformanceLevel = ConformanceLevel.Document;
                        writerSettings.Indent           = true;

                        using (XmlWriter writer = XmlWriter.Create(_settingsFile, writerSettings))
                        {
                            writer.WriteStartDocument();
                            writer.WriteStartElement(ElementSettings);

                            // save base settings
                            writer.WriteStartElement(ElementIsLoggingEnabled);
                            writer.WriteValue(_isLoggingEnabled);
                            writer.WriteEndElement();

                            if (!string.IsNullOrEmpty(_registrationEmail))
                            {
                                writer.WriteStartElement(ElementRegistrationEmail);
                                writer.WriteString(CatfoodCrypto.EncryptString(_registrationEmail, _appName));
                                writer.WriteEndElement();

                                writer.WriteStartElement(ElementRegistrationKey);
                                writer.WriteValue(_registrationKey);
                                writer.WriteEndElement();
                            }

                            writer.WriteStartElement(ElementUseProxyServer);
                            writer.WriteValue(_useProxyServer);
                            writer.WriteEndElement();

                            writer.WriteStartElement(ElementUseProxyServerCredentials);
                            writer.WriteValue(_useProxyServerCredentials);
                            writer.WriteEndElement();

                            if (!string.IsNullOrEmpty(_proxyAddress))
                            {
                                writer.WriteStartElement(ElementProxyAddress);
                                writer.WriteString(_proxyAddress);
                                writer.WriteEndElement();
                            }

                            if (!string.IsNullOrEmpty(_proxyDomain))
                            {
                                writer.WriteStartElement(ElementProxyDomain);
                                writer.WriteString(CatfoodCrypto.EncryptString(_proxyDomain, _appName));
                                writer.WriteEndElement();
                            }

                            if (!string.IsNullOrEmpty(_proxyPass))
                            {
                                writer.WriteStartElement(ElementProxyPass);
                                writer.WriteString(CatfoodCrypto.EncryptString(_proxyPass, _appName));
                                writer.WriteEndElement();
                            }

                            writer.WriteStartElement(ElementProxyPort);
                            writer.WriteValue(_proxyPort);
                            writer.WriteEndElement();

                            if (!string.IsNullOrEmpty(_proxyUser))
                            {
                                writer.WriteStartElement(ElementProxyUser);
                                writer.WriteString(CatfoodCrypto.EncryptString(_proxyUser, _appName));
                                writer.WriteEndElement();
                            }

                            writer.WriteStartElement(ElementInstanceId);
                            writer.WriteString(_instanceId.ToString());
                            writer.WriteEndElement();

                            writer.WriteStartElement(ElementInstallDate);
                            writer.WriteValue(_installDate.Ticks);
                            writer.WriteEndElement();

                            writer.WriteStartElement(ElementNextUpdateCheck);
                            writer.WriteValue(_nextUpdateCheck.Ticks);
                            writer.WriteEndElement();

                            // save derived class settings
                            SaveToXmlWriter(writer);

                            writer.WriteEndElement();
                            writer.WriteEndDocument();
                        }
                    }

                    // if we get this far save succeeded
                    break;
                }
                catch (Exception ex)
                {
                    lastException = ex;
                }

                retryAttempt++;

                LogException(LogSeverity.Warning,
                             string.Format(CultureInfo.CurrentCulture,
                                           "Failed to save settings, retrying (attempt {0} of {1})",
                                           retryAttempt,
                                           SaveRetryLimit),
                             lastException);

                // sleep for a bit in case the settings file is locked, and
                // bump up the sleep interval for the next save attempt
                Thread.Sleep(sleepFor);
                sleepFor += SaveRetryWaitMS;
            }

            // throw the last exception if we reached the retry limit and still didn't save
            if ((retryAttempt == SaveRetryLimit) && (lastException != null))
            {
                LogMessage(LogSeverity.Error, "Failed to save settings");
                throw lastException;
            }
            else
            {
                UpdateProxyServer();

                // fire the settings saved event
                if (SettingsSaved != null)
                {
                    SettingsSaved(this, EventArgs.Empty);
                }
            }
        }