VB.Net’s My.Settings and custom objects/classes; Part One: requirements for your class

This article is the culmination of many months’ struggle, on and off, with using a somewhat complex object/class I wrote to store user settings into VB.Net’s My.Settings permanent storage provider. The information required to do so is out there, but it’s fragmented and often contradictory, and some articles/forum posts contain inaccuracies; so I set out to gather all the required information in one place, to save others the headaches I encountered.

Part One will cover the requirements for the class you create; Part Two will cover getting your object into My.Settings.

What’s “My.Settings”?

settings1

My.Settings is a Windows Forms feature in VB.Net that allows the programmer to store user-specific settings, such as the last location of the application’s window on the screen, user application preferences, etc., into permanent storage on the user’s hard drive, in a quick and easy manner.

There are application-specific settings, which are the same for all users on a given PC, and user settings, which are different for each user. We will be looking only at the latter here.

You can actually bind form and control settings, such as last form location or the form’s title bar text, to My.Settings directly in Visual Studio’s WinForms designer. What we’re going to look at here is a bit more complex.

Where is the data actually stored on the user’s hard drive?

configFile

The actual file containing the saved settings is named user.config; it is an XML file, and its location depends on your version of Windows: generally,

  • Under Windows Vista (and, I would think, Windows 7, though I haven’t tested it):
    C:\Users<user id>AppDataLocalApplication Data<companyname><appdomainname>[etc.]
  • Under Windows XP:
    C:\Documents and Settings><username>[Local Settings]Application Data<companyname><appdomainname>[etc.]

<companyname> is the name of the Company you entered in the Project settings; <appdomainname> may or may not appear.

The [etc.] in the above paths may include a build-specific hash etc. depending on whether you have strong-named the assembly; and there will be an additional directory for the version number of the build, again controlled by the setting in the applications Properties.

My Needs

For an application I was writing, I needed to save approximately a dozen user-specified options of various datatypes into permanent storage. These were to be available to the user for editing in a fairly standard options dialog.

Having some positive experience using My.Settings for simple datatypes, as well as some experience using Binary Serialization for similar purposes, I decided to investigate whether I could use My.Settings for my needs.

It was simple enough to create several individual settings of various datatypes in the Settings editor in the Properties for my application, and manually load them into each control at app startup. However, as the number and complexity of settings began to increase, I decided that I wanted a single location for the settings that was not hidden away in a Visual Studio editor. I also wanted to take advantage of the drag-and-drop databinding available in VS 2005 (which was the current version when I first started the project). The answer seemed obvious—the documentation claimed that custom objects were supported. I was to learn that that support was fairly weak and severely under-documented; but it is possible to use even a pretty complex, nested class with My.Settings. It just takes a lot of detective work, and a bit of sweat!

Requirements for your class

You must meet the below requirements for the class you create, or it simply will not work with My.Settings, no matter what you try. I went down many dead ends, trying a dozen different unnecessary approaches, simply because I did not pay strict enough attention to the following simple rules.

The basic requirements for a class that will be used to hold settings in My.Settings are largely the same as for any XML-serializable:

  • Your class must be decorated with the <Serializable()> attribute
  • Your class must have a Public default constructor (New() sub) that takes no parameters
  • Read-Only, Write Only, or Private Properties and/or Properties lacking Getters and Setters will not be saved to My.Settings
  • Any Property in your class of a type from the .Net framework must be labeled as Serializable in the documentation

And, finally:

  • Any other class contained in your class must adhere to the above requirements as well

The last item is particularly important; it tripped me up for several days before I realized that a class contained within my main settings class had two Read Only properties, and it was this fact that was causing the properties within that class to not be saved to disk.

Beyond the above, there are not many restrictions. My main settings class contains a Generic List of objects which are themselves a separate class, and you can generally include any datatype that can be represented as XML. My class contains a Hotkey combo class, which in turn includes System.Windows.Forms.Keys.

Additional thoughts

If you run into problems with datatypes beyond the basic string, integer, etc., you may need to implement the ISerializable interface within your class, and specify how the XML serialization should occur.

If so, make sure you have implemented the GetObjectData() and SetObjectData() ISerializable methods, and have .AddValue() and .GetValue() statements which map to all of your properties. You’ll also want the additional constructor with the signature:

Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)

Most of the above should be created for you in skeletal form once you hit the <Enter> key after typing in Implements ISerializable, though you will need to fill in the lines for each of your Properties. There are many examples in MSDN and on the Web.

I did not find this approach necessary, and I had several contained classes in my settings class, which included a few non-basic datatypes. I mainly include this for completeness.

Next, at least in VS 2008, make liberal use of the poorly-named “Synchronize” button in the Settings tab of your project’s Properties editor:

synch

despite the misleading name, clicking this button will erase all saved My.Settings/settings files, returning your project to a known state with no saved data. This makes it much simpler to determine whether the settings data you are looking at are current or not. Your mileage may vary in VS 2005, as I have heard reports of problems with this tool in VS 2005.

Finally, I will add this: tackle any problems by temporarily simplifying your object: comment out everything other than a simple string Property, and get that working. Add the others back one by one until everything is working.

Now available: Part Two: Getting My.Settings to recognize your custom object


Advertisements
  1. #1 by MrBW on April 13, 2017 - 11:52 am

    Thanks for these instruction, it worked for me 🙂
    But I would like to have a collection (list) as an object in my settings.
    I’ve tried to put in a list in my MySettingsObject class, with or without new but couldn’t get it to work 😦

  2. #2 by andrewcushen on August 17, 2011 - 9:10 pm

    I would start with the basics. First, you don’t generally need to implement ISerializable except in special cases; it’s only necessary when you need to take control of how your object is serialized to XML. Just decorate your class with the Serializable() attribute.

    As I said above, start with a really basic class like this:

    ‘——————————————————————

    _
    Public Class MySettingsObject()

    Private _TestProperty as String

    Public Property TestProperty as String
    Get
    Return _TestProperty
    End Get
    Set(ByVal value as String)
    _TestProperty = value
    End Set
    End Property

    Public Sub New()

    End Sub

    End Class
    ‘——————————————————————

    Follow my notes above and in part 2, and see if you can get this simple settings class working. If you can’t, you are doing something basic wrong, and will never get a more complex class to work. Make sure you have either set the option in the project settings that automatically saves My.Settings on app close, or are manually calling the save function on My.Settings in a place where it will always fire when a user performs the action you want, like a button click event.

    Once you have the simple class above working, add in the more complex properties one by one so troubleshooting is simpler. You may find that one particular data type is causing the problem.

    I should also add that getting .NET to recognize when you have changed your My.Settings object’s class can be challenging. You may need to do a Clean, followed by a Rebuild of your entire solution; at times I had to do that, followed by closing Visual Studio, or even a re-boot. You may even have to copy your object out to a text file, delete it from the project, rebuild, then add it back in. It can be frustrating at times. It definitely seems as though the more complex your object, the more difficult. You should make sure you can serialize the object “manually” by writing some test serialization code; you may at some point decide to keep that serialization code and use it as a complete replacement for My.Settings if it winds up being less work. The advantage of My.Settings is that you don’t have to worry about permissions for writing your file in a particular location, and the fact that .NET is handling things for you. You have to decide if the trade-off is no longer worth it, and that will largely depend on the complexity of your object and the difficulty you experience.

    Again, start with a simple class and only implement ISerializable if you must; it’s not usually necessary, and I never did get it to work, as I discovered I didn’t need it for my scenario. Make sure your simple class is being written out to disk before you consider the simple class above to be working.

    Good luck.

  3. #3 by David on August 16, 2011 - 4:58 pm

    What would help me greatly is seeing a class you made for the my.settings. I have created my class and it is nothing when I hit it. How do I make the actual object from the class?
    THis is the class I made…

    Imports System.Runtime.Serialization

    _
    Public Class FormStatus
    Implements ISerializable
    Private _size As Drawing.Size
    Private _location As Drawing.Point
    Private _windowState As System.Windows.Forms.FormWindowState
    Private _loadComplete As Boolean

    Public Sub New()

    End Sub

    Public Property Location() As Drawing.Point
    Get
    Return _location
    End Get
    Set(ByVal value As Drawing.Point)
    _location = value
    End Set
    End Property

    Public Property Size() As Drawing.Size
    Get
    Return _size
    End Get
    Set(ByVal value As Drawing.Size)
    _size = value
    End Set
    End Property

    Public Property WindowState() As System.Windows.Forms.FormWindowState
    Get
    Return _windowState
    End Get
    Set(ByVal value As System.Windows.Forms.FormWindowState)
    _windowState = value
    End Set
    End Property

    Public Property loadComplete() As Boolean
    Get
    Return _loadComplete
    End Get
    Set(ByVal value As Boolean)
    _loadComplete = value
    End Set
    End Property

    Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) _
    Implements ISerializable.GetObjectData

    If (info Is Nothing) Then Throw New ArgumentNullException(“info”)

    info.AddValue(“size”, _size)
    info.AddValue(“location”, _location)
    info.AddValue(“windowState”, _windowState)
    info.AddValue(“loadComplete”, _loadComplete)

    End Sub

    End Class

  1. sql wildcard,sql wildcards,sql rollback,rollback sql,sql copy table,sql sum,sql mirroring,sum sql,sql cluster,sql server performance,truncate in sql,backup sql,backup sql database,backup sql server,sql performance,date functions in sql,sql over,truncate s

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: