views:

1030

answers:

5

The following code has two flaws, I can't figure out if they are bugs or by design. From what I have seen it should be possible to write back to the app.config file using the Configuration.Save and according to http://www.codeproject.com/KB/cs/SystemConfiguration.aspx the code should work.

The bugs are shown in the source below and appear when you try to set the property or save the config back out.

Imports System.Configuration

Public Class ConfigTest
    Inherits ConfigurationSection
<ConfigurationProperty("JunkProperty", IsRequired:=True)> _
Public Property JunkProperty() As String
    Get
        Return CStr(Me("JunkProperty"))
    End Get
    Set(ByVal value As String)
        ' *** Bug 1, exception ConfigurationErrorsException with message "The configuration is read only." thrown on the following line.
        Me("JunkProperty") = value
    End Set
End Property

Public Sub Save()
    Dim ConfigManager As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)

    ' The add / remove is according to http://www.codeproject.com/KB/cs/SystemConfiguration.aspx
    ConfigManager.Sections.Remove("ConfigTest")
    ' *** Bug 2, exception InvalidOperationException thrown with message "Cannot add a ConfigurationSection that already belongs to the Configuration."
    ConfigManager.Sections.Add("ConfigTest", Me)
    ConfigManager.Save(ConfigurationSaveMode.Full, True)

End Sub

Public Shared Sub Main()
    Dim AppConfig As ConfigTest = TryCast(ConfigurationManager.GetSection("ConfigTest"), ConfigTest)

    AppConfig.JunkProperty = "Some test data"
    AppConfig.Save()

End Sub

' App.Config should be:
'    <?xml version="1.0" encoding="utf-8" ?>
    '<configuration>
    '  <configSections>
    '    <section name="ConfigTest" type="ConsoleApp.ConfigTest, ConsoleApp" />
    '  </configSections>
    '  <ConfigTest JunkProperty="" />
    '</configuration>

End Class

I'd like to do it this way so that on the first run of the app I check for the properties and then tell the user to run as admin if they need to be set, where the UI would help them with the settings. I've already 'run as admin' to no effect.

A: 

Maybe you don't know Portuguese or c# but this is you want http://www.linhadecodigo.com.br/Artigo.aspx?id=1613

using BuildProvider from asp.net

pho3nix
Ryan ONeill
A: 

After loading a configuration it is readonly by default, principally because you have not overriden the IsReadOnly property. Try to override it.

¿Is there something that prevents you from using a setting?

Wilhelm
Nope, overriding the IsReadOnly property does not have any effect.
Ryan ONeill
A: 

Looks like it is not possible by design. App.config is normally protected as it resides along with the app in the Program Files directory so must be amended at installation time by the installer.

Pity really, I'd like the app to have settings that an admin can set.

Ryan ONeill
+1  A: 

Your code doesn't really make any sense. I took your example code and turned it into a simple example that works. Please note this is not best practise code, merely an example to aid you on your journey of learning the configuration API.

Public Class ConfigTest
    Inherits ConfigurationSection
    <ConfigurationProperty("JunkProperty", IsRequired:=True)> _
    Public Property JunkProperty() As String
        Get
            Return CStr(Me("JunkProperty"))
        End Get
        Set(ByVal value As String)
            ' *** Bug 1, exception ConfigurationErrorsException with message "The configuration is read only." thrown on the following line.
            Me("JunkProperty") = value
        End Set
    End Property

    Public Overrides Function IsReadOnly() As Boolean
        Return False
    End Function



    Public Shared Sub Main()
        Dim config As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
        Dim AppConfig As ConfigTest = config.GetSection("ConfigTest")

        AppConfig.JunkProperty = "Some test data"
        config.Save()
    End Sub
End Class

This code will open the config file, modify the attribute JunkProperty and persist it back it the executable's configuration file. Hopefully this will get you started- it looks like you need to read about the configuration API a bit more.

I've used the API to create configuration sections for large scale enterprise apps, with several 1000 of lines of custom hierarchical config (my config was readonly though). The configuration API is very powerful once you've learnt it. One way I found out more about its capabilities was to use Reflector to see how the .NET framework uses the API internally.

RichardOD
Thanks, that works. I was nearly there but confused by that damn CodeProject article that insisted I had to add and remove the config section to resave.
Ryan ONeill
Actually, it does not work. The new property value is not saved out to the config file.
Ryan ONeill
Ryan it worked on my machine. Please check...
RichardOD
A: 

Sorry if I didn't understand your case, but yes, you can change App.config at runtime.

Actually, you will need to change YourApp.exe.config, because once your app is compiled, App.config contents are copied into YourApp.exe.config and your application never looks back at App.config.

So here's what I do (C# code - sorry, I still haven't learnt VB.Net)

 public void UpdateAppSettings(string key, string value)
    {

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
        foreach (XmlElement item in xmlDoc.DocumentElement)
        {
            foreach (XmlNode node in item.ChildNodes)
            {

                if (node.Name == key)
                {
                    node.Attributes[0].Value = value;
                    break;
                }
            }
        }

        using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile))
        {
            xmlDoc.Save(sw);
        }
born to hula