6

The .NET configuration settings feature is not as flexible as I would like. If I understand Application Settings correctly, I am limited as to when I can change/edit settings. In C#, Application Settings are divided into two different types or scopes ("Application" and "User"), but both have limitations in regard to how they can be changed or modified. The following table demonstrates the differnce:

   SCOPE:   |  EDIT AT DESIGN-TIME: |     EDIT AT RUN-TIME:     |  EDIT BETWEEN SESSIONS:
---------------------------------------------------------------------------------------
   User     |   Setings.settings    |  Settings.Default.Save()  |     *Not supported*       
Application |   Setings.settings    |      *Not supported*      |  edit  app.exe.config   

Is there any "built-in" settings functionality that will allow me to edit settings by all three mechanisms? One of the primary motivations for using a configuration file is to allow users to change default values without re-building the source code (as can be done with Application-scoped settings). However, the user shouldn't be forced to edit a .config file; they should also be able to make a change at run-time that persists across settings (as can be done with User-scoped settings). Surely there must be some sort of mechanism that provides both functionalities.

BOTTOM LINE: Why can't Application Settings (app.exe.config) be edited at Run-Time? That would solve all my problems. I understand that this could cause problems for users who share the same machine. But who does that anymore?

POTENTIAL WORKAROUND: Is there anyway to change the default storage location for the User Settings config file into a non-hidden folder?


UPDATE (for clarification): What I'm saying is that I want to be able to change a default setting at Design-time, at Run-time, or in-between sessions (i.e., by editing a config file). But when using the built-in C# persistence mechanisms provided by Settings.settings, I must choose at most 2 out of the 3. Am I missing something? Is there another alternative that I am not aware of?

[Use Case: I want to store a "default" database name for the connection string, but I want the user to be able to specify a different database at runtime (and thereby become the "new" default for that user). But I also want to be able to over-write the default in the config file without re-running or re-building the application.]

[BETTER Use Case: (In response to comments)

I have a computational model with a config file that contains the default values for parameters in the model. User A starts up the model and decides to change the value of several of the parameters. That change needs to persist for all future sessions for that user (i.e., Edit at RunTime). Subsequently, that user wants to share that modified configuration file with his team (via version control repository, for example, or email). This would allow User B to update her default parameter values (to match User A's) without having to manually change them in the application (i.e., Edit Between Sessions). All of these mods should happen AFTER Design-Time.]

*I realize that I can "technically" edit user-scoped settings in the app.exe.config file located in the hidden AppData folder, but this is a hidden file and not all users may have sufficient privileges to view it. (BUT see "Potential Workaround" above.)

kmote
  • 16,095
  • 11
  • 68
  • 91
  • As my lack of knowledge ,I haven't overcome such situations.But using app.config you can define your setting in the name value pairs and can choose the name at runtime accordingly. – Hameed Syed Sep 01 '16 at 14:15
  • 1
    One of the first thing I learn shortly after knowing about `C#` was serialization. While dictionaries are nice, they aren't any good to contain complex data, require casting every time you access data, prone to contain error (especially due user edits)... Serializing/deserializing is so simple with `XmlSerializer` so why bother with `Settings` at all? I found json to be the best format to hold settings. – Sinatr Sep 01 '16 at 14:42
  • 2
    Without administrator elevation, an user should not be able to update settings that apply to all users as one user might do undesirable changes that would affect other users. So it make perfect sense that it is harder to change application settings... – Phil1970 Sep 01 '16 at 17:44
  • @kmote: Editing of User settings between sessions is possible! The only difference is that the user settings get stored in the users folder. See also: http://stackoverflow.com/q/982354/6439999 – Thomas Voß Sep 11 '16 at 05:53
  • @ThomasVoß, understood. But I was hoping there was a mechanism that didn't require looking in hidden folders. – kmote Sep 13 '16 at 15:16
  • 1
    I feel like this is a solution looking for a problem. Why would you allow any user to change app behavior for ALL users? Sounds like chaos to me. Do you have an actual use case? – Paul Swetz Sep 14 '16 at 14:23
  • @PaulSwetz: No, the only changes intended for ALL users happens at design time. I'll add a clarifying Use Case to the post. – kmote Sep 14 '16 at 17:46
  • Given the case you pointed out you just use user settings, you would NOT want to update the default value in the config as that would be for ALL users, for what you are saying you would want a unique config file for EVERY user... Why is it important that the value be reflected in the config file? if you are actually trying to read the config file manually to see individual user settings just give up and use a database and track the individual users settings, again this is a solution looking for a problem. – Paul Swetz Sep 14 '16 at 17:50
  • @PaulSwetz- the issue you mention is only a problem if users share the same computer. But that will never be the case in our situation (scientific lab). The database solution (which we are using now), is proving to be much more difficult to manage from a collaboration and version control standpoint. (Difficulties that would simply vanish if `app.exe.config` could be modified at runtime.) We're not *looking* for a problem; we've got one. – kmote Sep 14 '16 at 18:17

2 Answers2

0

All you need to do is combine the two techniques!

At the start of a session, read the configured setting from a config file, and store it into a global static variable (or any form of persistence) that is writeable.

Then when a user decides to change this setting, simply change the value of the setting.

public static Program {

    public static string ConnectionString { get; set; }

    void Main(string connectionString) {
         ConnectionString = connectionString;
    }

}

public class SomeOtherClass {
     public void SomeOtherMethod () {
         Program.ConnectionString = "new value";
     }
}

This is just a very trivial example of how you'd use this. Note that instead of passing the string as an argument to the program you'd probably choose to read the default value from the application settings. You'd also probably store the user-configured connectionstring into some sort of database so that for each user the database could be different.

Glubus
  • 2,819
  • 1
  • 12
  • 26
  • I'm afraid this doesn't seem to address my question at all. I fail to see how this approach differs from the "User Scope" described in my original post. Plus, I'm not sure how it would make sense to store a database connection string in a database. (Refer to the Use Case in my post.) – kmote Sep 01 '16 at 18:20
  • So you are saying that you want to be able to change a default setting as the application is started? Also, you're right about the connectionstring of course, so this example is kindof crooked. The point I was trying get across though is that you can choose any means of persistence when it comes to storing the user-configured setting (unless access to the storage is dependent on the setting). – Glubus Sep 02 '16 at 07:49
  • What I'm saying is that I want to be able to change a default setting at Design time, at Runtime (i.e., when application is started), _or_ in-between sessions. – kmote Sep 06 '16 at 14:25
  • Well for changes during design time, and in between sessions, my answer provides an answer to your problem. So when it comes to changes during runtime you will have to write code to do this. In this case you'll probably have to use a socket layer in your application so that you can signal a change to your clients. I read in your question that you want to only use built in techniques. I do not think you'll be able to implement what you want without writing some code yourself. – Glubus Sep 07 '16 at 13:12
  • 1
    " I'm not sure how it would make sense to store a database connection string in a database" most larger apps do this, they have a single config file connection to the settings database which contains the connection strings to various other DBs for work. – Paul Swetz Sep 14 '16 at 18:12
0

What if you tried the following in the case study and you might generalize it?

  1. As long as the user can change the default Database name, so this Key should be defined under the User Scope and not the Application scope
  2. Upon installing the application which I assume a windows application, and on the first run, check if the user.config has the value of Database name, if yes proceed in loading the application, otherwise, move to step 3.
  3. Show the user a screen with the database name has a default value and the user can change the settings and make sure to do some validations here, after finishing the settings page, store them in the user.config file, so your application on the next run, it will find the required settings in order to run normally.
  4. For admin privileges, you can show a button to change the settings at run time.

I use this technique for all applications that needs from the user to define some important details like " where to store images, the database name , the connection string, ... etc"

hope this will give you a hint or something

Monah
  • 6,714
  • 6
  • 22
  • 52
  • Thanks, Hadi. That is essentially the process I am using now (although without the check in step 2). I was hoping to find a solution that allowed users to change the default without running the program. – kmote Sep 13 '16 at 15:17