【问题标题】:Custom Configuration Section can only be saved/modified while running as administrator?自定义配置部分只能在以管理员身份运行时保存/修改?
【发布时间】:2016-09-01 18:31:25
【问题描述】:

我编写了一个自定义配置部分、集合和元素以添加/修改到我的 app.config。一切似乎进展顺利,它在 Visual Studio 中完美运行。但是,当我安装应用程序并且需要将新数据保存到自定义配置部分时,会引发以下异常:

System.Configuration.ConfigurationErrorsException: Unable to save config to file '{path to config file}'

有趣的是,如果我以管理员模式运行应用程序,一切正常。有什么理由只能作为管理员工作吗?

编辑:

我应该注意,我不认为这是一个权限问题,因为 a)我们有其他应用程序可以修改其 app.configs 的<applicationSettings>,并且 b)log4net 能够很好地写入其日志文件在那里。

自定义配置元素:

public class AuditorColorElement : ConfigurationElement
{
    public AuditorColorElement()
    {
    }

    public AuditorColorElement(Color color, string auditor)
    {
        Color = color;
        Auditor = auditor;
    }

    [ConfigurationProperty(nameof(Color), IsRequired = true, IsKey = true)]
    public Color Color
    {
        get { return (Color)base[nameof(Color)]; }
        set { this[nameof(Color)] = value; }
    }

    [ConfigurationProperty(nameof(Auditor), IsRequired = true)]
    public string Auditor
    {
        get { return (string)base[nameof(Auditor)]; }
        set { this[nameof(Auditor)] = value; }
    }
}

自定义配置部分:

[ConfigurationCollection(typeof(AuditorColorElement))]
public class AuditorColorElementCollection : ConfigurationElementCollection, IEnumerable<AuditorColorElement>
{
    internal const string PropertyName = "AuditorColors";

    public AuditorColorElementCollection() : base()
    {
    }

    public AuditorColorElementCollection(AuditorColorElementCollection collection)
    {
        foreach (AuditorColorElement element in collection)
        {
            Add(element);
        }
    }

    public override ConfigurationElementCollectionType CollectionType
    {
        get
        {
            return ConfigurationElementCollectionType.AddRemoveClearMapAlternate;
        }
    }

    protected override string ElementName
    {
        get
        {
            return PropertyName;
        }
    }

    public AuditorColorElement this[int idx]
    {
        get { return (AuditorColorElement)BaseGet(idx); }
    }

    protected override bool IsElementName(string elementName)
    {
        return elementName.Equals(PropertyName,
        StringComparison.InvariantCultureIgnoreCase);
    }

    public override bool IsReadOnly()
    {
        return false;
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new AuditorColorElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((AuditorColorElement)(element)).Color;
    }

    public void Add(AuditorColorElement element)
    {
        BaseAdd(element);
    }

    public void Clear()
    {
        BaseClear();
    }

    public void Remove(AuditorColorElement element)
    {
        BaseRemove(element.Color);
    }

    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }

    public void Remove(Color color)
    {
        BaseRemove(color);
    }

    public object GetKey(object key)
    {
        return BaseGet(key);
    }

    public bool ContainsKey(object key)
    {
        return GetKey(key) != null ? true : false;
    }

    public new IEnumerator<AuditorColorElement> GetEnumerator()
    {
        foreach (var key in this.BaseGetAllKeys())
        {
            yield return (AuditorColorElement)BaseGet(key);
        }
    }
}

自定义配置部分

public class AuditorColorSection : ConfigurationSection
{
    [ConfigurationProperty(nameof(AuditorColors), IsRequired = true, IsDefaultCollection = true)]
    [ConfigurationCollection(typeof(AuditorColorElementCollection),
        AddItemName = "add",
        ClearItemsName = "clear",
        RemoveItemName = "remove")]
    public AuditorColorElementCollection AuditorColors
    {
        get { return ((AuditorColorElementCollection)(base[nameof(AuditorColors)])); }
        set { base[nameof(AuditorColors)] = value; }
    }

    public AuditorColorSection()
    {
        AuditorColors = new AuditorColorElementCollection();
    }
}

【问题讨论】:

  • 你写信给哪里?身体在哪里?运行您的应用的用户是否有权在此处写入?
  • @mariocatch 写入 ProgramData,但我们套件中的其他应用程序可以很好地修改也存储在那里的配置文件。正在修改的 部分(适用于我们的其他应用程序)与自定义部分在权限方面是否有区别?此外,我的应用程序使用 log4net,它似乎没有将日志写入该位置的问题。
  • 你的 app.config 是什么样的?只是部分声明部分
  • @mariocatch 好吧,它是一个自定义部分,所以它在第一次运行时不存在,但是当它成功创建(调试模式或以管理员身份运行)时,它看起来像这样:&lt;section name="AssignedColors" type="TMIAuditorTerritoryExtract.AuditorColorSection, TMIAuditorTerritoryExtract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /&gt;

标签: c# configuration app-config configuration-files


【解决方案1】:

我不喜欢使用 System.Configuration 命名空间中的方法来写入 配置文件。 使用 System.Configuration 命名空间中的方法读取值绝不是问题。

改用 LinqToXML,至少检查一下是否是问题所在。

我猜你的应用程序安装在 C:\Program Data 中,所以虽然它可能与权限相关,但我怀疑 System.Configuration.ConfigurationErrorsException: Unable to save config to file 的根本原因是 lock on the file, use this code to check,如果该假设正确的话。

【讨论】:

  • 所以我没有使用 System.Configuration 命名空间来编写实际文件(文件是由 VS 本身中的 Add-->New Item 创建并设置为复制到输出),但这只是一个标准标签为&lt;configuration&gt; 的空配置文件。如前所述,尝试打开文件并保存更改时发生错误。我最终解决问题的方法是使用 XML Writer 在代码中创建 XML 文件,并用它编写顶级 &lt;configuration&gt; 标记。其余的代码没有改变,但这次它可以工作了。这是否表明您认为它被锁定了?
  • 您使用的所有属性都在System.Configuration 命名空间中,例如ConfigurationProperty。我在使用这些类型的方法写入配置文件时遇到了很多问题。这只是一种预感/假设/猜测它失败的根本原因是因为文件被锁定。如果它与权限无关,也不是找不到文件,那么下一个合乎逻辑的选择是文件被锁定。重点是改用 LinqToXML 或 XML Writer。我很高兴你能成功。
  • 也谢谢我,我很困惑,我仍然看不出使用 System.Configuration 编辑文件在编译时创建的文件(不起作用)与在运行时创建的文件(起作用通过 XMLWriter),但怀疑它与权限有关,但过去只是猜测。
猜你喜欢
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2023-03-07
  • 2012-11-22
  • 2019-10-27
  • 2011-01-15
相关资源
最近更新 更多