My.Settings: Run-Time Added Properties don't save

JaedenRuiner

Well-known member
Joined
Aug 13, 2007
Messages
340
Programming Experience
10+
I found that there was the Settings.Properties collection as well as the Settings.PropertyValues collection, and hopefully i'm not doing extra work here, but i'm creating both, and then assigning a value to the Settings(PropName).

Defaultly, in my "static" settings (through the IDE designer window and such) I have 9 settings/properties, and at run time when I'm processing, the Settings.Properties.Count doeos indeed equal 9.

Now, in the process of my application I generate some "saved" control properties myself, and actively "add" them to the Settings:
VB.NET:
For Each prop As String In Me.Keys
         Try
            name = Layout & "." & _control.Name & "." & prop
            Try
               p = Settings.Properties(name)
            Catch
               p = Nothing
            End Try
            If p Is Nothing Then
               p = New Configuration.SettingsProperty(name)
               p.PropertyType = Me(prop).GetType
               Settings.Properties.Add(p)
               Settings.PropertyValues.Add(New Configuration.SettingsPropertyValue(p))
            End If
            Settings(name) = Me(prop)
         Catch ex As Exception
            Exit Sub
         End Try
      Next

This seems to work fine, and after the repetitive code (cycling through a collection) is finished, the Setting.Properties.Count does indeed equal 79, for the 70 new properties added.

I not only execute a My.Settings.Save() when the application exits, but I know I also have the SaveMySettingsOnExit set to true, but the next time i load up the app, my settings.properties.count is back to 9.

Any Ideas?
Thanks
 
Got It!

I forget who pointed me in the direction of Red-Gate's .Net Reflector but that is a lifesaver. And I'll post my solution here so that others who may want to do this can find it.

I found inside the ApplicationSettingsBase, (the ancestor of MySettings) it executes an overridden Save() method. That method comes from the SettingsBase class, whose Save() method calls SaveCore(). Nice and confusing, ain't it?

Well in the SaveCore() method I found this:
VB.NET:
For Each provider In Me.Providers
            Dim collection As New SettingsPropertyValueCollection
            Dim value2 As SettingsPropertyValue
            For Each value2 In Me.PropertyValues
                If (value2.Property.Provider Is provider) Then
                    collection.Add(value2)
                End If
            Next

Yes I know I didn't paste all of it, but that's the key, the provider.

So, In my code I had this:
VB.NET:
If p Is Nothing Then
               p = New Configuration.SettingsProperty(name)
               p.PropertyType = Me(prop).GetType
               Settings.Properties.Add(p)
               Settings.PropertyValues.Add(New Configuration.SettingsPropertyValue(p))
            End If
which did add the property to the Settings, but didn't tell it any provider, so when it came time to saving it, these properties had no provider, as well i found that they also needed an attribute to tell the setting where it was to be saved. The final result:

VB.NET:
dim p as Configuration.SettingsProperty

       p = New Configuration.SettingsProperty(name)
       p.Provider = Settings.Providers("LocalFileSettingsProvider") 
       p.Attributes.Add(GetType(Configuration.UserScopedSettingAttribute), _
                                   New Configuration.UserScopedSettingAttribute())
       p.PropertyType = Me(prop).GetType 
       Settings.Properties.Add(p)
       Settings.PropertyValues.Add(New Configuration.SettingsPropertyValue(p))

To Explain, the Settings.Providers Collection is a Keyed Collection, so you can enumerate it if necessary, but in the default application there is only one provider. Secondly, the Attribute Collection is also a Keyed collection, but it is keyed of of the System.Type, so you have to "GetType()" on the class you wish to add, in this case the UserScopedSettingAttribute, which basically tells the MySettings to save these setting to the User.Config file in the Local Settings\Application Data folder area.

hope this helps other people.
Cheers
 
Save Works but Won't Load

I actually just used My.Settings.Properties .Item Property and .Add Method. It handled detecting the lack of a Setting (i.e. via returning a Nothing value which oddly, the My.Settings.Items wouldn't do w/o a Try Statement) and allowed me to add a Setting to both the My.Settings .Properties and .Items Collections with one call AND saved to the appropriate User.Config File. However, when I restart my app, the Setting I just added to that File it doesn't get loaded into either the My.Settings .Properties and .Items Collection. I expect that it wouldn't have an actual My.Settings.<SettingName> Property, since that would require code generation at Design Time by the VS Designer in the My Project, Settings Tab or a Control's Properties, (Application Settings), (PropertyBinding) Property. However, I would've expected it to appear in the My.Settings .Properties and .Items Collections which it did before I restarted the App.

I need to create settings for each Form at run time, not just to reduce development time and errors (for the Designer-generated Forms) but also to automate the app since I'm also dynamically generating Forms at run time.
 
mmmmmmmmmMICROSOFT!!!

I think I figured out at least at a high level why it's not loading. Note that in the Settings Designer, you specify a Type and a (Default) Value. Neither of those are ever saved in the User.Config (even for Settings added via the Designer). So, just because you were able to add a Setting to the User.Config, doesn't mean it (My.Settings or whatever it Inherits from) will be able to load it.

I believe that's what MSDN was trying to say (albeit cryptically) in the statement "The get accessor of the Properties property reflects over the metadata of the settings wrapper class, which is derived from ApplicationSettingsBase, to dynamically determine the set of available application settings properties." in their docs for the ApplicationSettingsBase.Properties Property (see ApplicationSettingsBase.Properties Property (System.Configuration))

In mortal expert terms, I believe that means it (the ApplicationSettingsBase Class from which the My.Settings Class inherits) gets the list of Settings (and their Types and Default Values) that it'll even attempt to load (regardless of whether they are in the User.Config File from the code generated by the Designer (in the Settings.Designer.vb File under Solution Explorer, <ProjectName>, My Project, Settings.settings).

Ok, so at best that means it's doing what the doc claims it was "designed" to do. At worst, that's a lousy design if not a bug. Why tease us with the ability to dynamically add Settings to the My.Settings .Properties and .Items Collections and even allow them to be saved to the User.Config File if you're not going to do it in a way that allows them to be loaded? Even if there's a way to override / customize the My.Settings, ApplicationSettingsBase and / or SettingsBase Class'es to do so (all of which btw, should be documented as examples including how to add a Setting dynamically to begin with), why would you allow the "Save" to work without any override / customization but require it for the Load?
 
Back
Top