/// <summary>
        /// Busca una directiva en el INI, si no la encuentra la crea
        /// en la sección por defecto que se pase. Se usa para directivas multivalor
        /// como las extensiones!
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public void UpdateOrCreateMultivalueDirective(string key, string value, string defaultSection, bool isCommented = false, string hostname = null)
        {
            if (!string.IsNullOrWhiteSpace(hostname) && this.DirectivesNotWorkingOnHostnameSections.Contains(key))
            {
                throw new Exception(string.Format("Directiva {0} no válida en sección HOST={1}", key, hostname));
            }

            // this.Logger.LogInfo(true, "[{3}] PHP.ini: {2}{0} = {1}", key, value, isCommented ? "; " : "", defaultSection);

            IniFileLine line = null;

            // Todas las posibles lineas, pueden haber directivas duplicadas y alguna de ellas comentada...
            var lines = (from p in this.GetAllLines(hostname)
                         where
                         p.Type == IniFileLineType.Directive &&
                         string.Equals(key, p.Key, StringComparison.CurrentCultureIgnoreCase) &&
                         string.Equals(value, p.Value, StringComparison.CurrentCultureIgnoreCase)
                         select p);

            // La última no comentada.
            var uncommented = lines.Where((i) => i.IsCommented == false);

            if (uncommented.Any())
            {
                line = uncommented.Last();
            }

            if (line == null && lines.Any())
            {
                // La última
                line = lines.Last();
            }

            var sections = this.GetSections(hostname);

            // Esto es que no hay nada de nada....
            if (line == null)
            {
                if (!sections.ContainsKey(defaultSection))
                {
                    sections.Add(defaultSection, new IniFileSection(defaultSection, false));
                }

                sections[defaultSection].lines.Add(new IniFileLine(key, value, defaultSection, false));
            }
            else
            {
                // Solo hay que descomentar tanto key como value son iguales!!
                line.IsCommented = isCommented;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="key">Clave</param>
        /// <param name="value">Valor</param>
        /// <param name="defaultSection">Nombre de la sección en la que se creará la directiva si no existe.</param>
        /// <param name="isCommented">Si la directiva debe estar o no comentada.</param>
        /// <param name="hostname">Si usas hostname, la seccion "default section" será ignorada.</param>
        public void UpdateOrCreateDirective(string key, string value, string defaultSection = CST_SEC_GLOBAL, bool isCommented = false, string hostname = null)
        {
            if (!string.IsNullOrWhiteSpace(hostname) && this.DirectivesNotWorkingOnHostnameSections.Contains(key))
            {
                throw new Exception($"Directiva {key} no válida en sección HOST={hostname}");
            }

            // logger.LogInfo(true, "[{3}] PHP.ini: {2}{0} = {1}", key, value, isCommented ? "; " : "", defaultSection);

            IniFileLine line = null;

            // Todas las posibles lineas, pueden haber directivas duplicadas y alguna de ellas comentada...
            var lines = (from p in this.GetAllLines(hostname)
                         where
                         p.Type == IniFileLineType.Directive &&
                         string.Equals(key, p.Key, StringComparison.CurrentCultureIgnoreCase)
                         select p);

            var sections = this.GetSections(hostname);

            // Comentar todas las de otras secciones
            foreach (var l in lines)
            {
                if (!string.Equals(l.Section, defaultSection, StringComparison.CurrentCultureIgnoreCase))
                {
                    l.IsCommented = true;
                }
                else
                {
                    line = l;
                }
            }

            // La última no comentada.
            var uncommented = lines.Where((i) => i.IsCommented == false);

            // Preventively comment all, and keep only one
            foreach (var u in uncommented)
            {
                u.IsCommented = true;
                line          = u;
            }

            // Only consider lines in my own section...
            if (line == null && lines.Any())
            {
                foreach (var l in lines)
                {
                    if (string.Equals(l.Section, defaultSection, StringComparison.CurrentCultureIgnoreCase))
                    {
                        line = l;
                        break;
                    }
                }
            }

            // Esto es que no hay nada de nada....
            if (line == null)
            {
                if (!sections.ContainsKey(defaultSection))
                {
                    sections.Add(defaultSection, new IniFileSection(defaultSection, false));
                }

                sections[defaultSection].lines.Add(new IniFileLine(key, value, defaultSection, false));
            }
            else
            {
                line.IsCommented = isCommented;
                line.Value       = value;
            }
        }