Force all user settings to save - c#

I have a C# program with various setting stored in the program project settings. As it is a command line program, these settings will be changed by the user in the user.config file. I can't work out how to force it to save all the default values.
Calling Properties.Settings.Default.Save(); only seems to work when I update a property in the program, which defeats the point of a persistent settings file.
If I run
Properties.Settings.Default.SomeSetting = "Help";
Properties.Settings.Default.Save();
In the config file I will see something like
< setting name="SomeSetting" serializeAs="String">
<value>Help</value>
< /setting>
What I want to happens is if the config file doesn't exist, create it and store all the settings. Then the user can change them if needed.

The way I managed to solve it was by modifying some existing code I had in a different project to handle version upgrades.
When the program runs:
if (PropertiesSettings.Default.UpgradeRequired)
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.UpgradeRequired = false;
Properties.Settings.Default.Save();
reloadSettings();
}
// Assign settings to themselves and save
// This keeps settings the same as the defaults even when upgrading but ensures all settings appear in the config file
private void reloadSettings()
{
Properties.Settings.Default.Setting1 = Properties.Settings.Default.Setting1;
Properties.Settings.Default.Setting2 = Properties.Settings.Default.Setting2;
//etc
Properties.Settings.Default.Save();
}
The UpgradeRequired setting should be set to True by default, so a new version with no config will be forced to run the first if statement. The .NET Properties.Settings.Default.Upgrade(); should then take care of finding old config files and loading the old settings.

Settings are saved somewhere in user AppData folder specifically for a given process. For example, when the application is run under the debugger, you get different settings than when running stand-alone.
I would guess that there is no easy way to share settings across application using those properties settings. That code is quite old (.NET 2.0 or even before) so I think it is not designed to be easily customizable as it is often the case with more recent code.
I think that settings are good for things that are specific to a given application and if data need to be shared across application, then you should manage your own files.
Usually, one would use either XML or JSON based file and the data would be stored (by default) either under a subdirectory of My Documents if the data is intended to be visible to users or under a subdirectory of user application data directory if a regular user should not see those files.

Related

Update user settings from outside the application

I have a C# application (a VSTO office addin) running on clients' machines, and I need to make a setup project or any other EXE that can overwrite and update the user settings in the user.config files with my own values.
It seems that I can't know exactly where the user.config is- it seems to create different folders under AppData\Local\Microsoft_Corporation with different names and numbers. I can try to iterate every subfolder I find but I was hoping for something better.
I can't get the path by using ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal) because I'm not inside the application, and I tried it inside the application and it actually returned a different, wrong path.
I can overwrite the app.config because I know where the application sits, from the registry, but overwriting it doesn't change user settings if the user settings were already saved in user.config too.
Can I force .NET to write the user.config into a predetermined location and store it in the registry, so I would have it for my setup?
Any ideas how to complete this objective? Is there some common practice for this? Thank you
Don't update the settings from your installer. The installer can save new options locally (HKLM, local folder, etc.) visible to every local user. When your addin is loaded, it can grab the new settings from that location and update its local settings as necessary.

Load a different MyExeName.config XML (Project Settings file) to the default one?

I see this question asked many times about the ASP.NET style of application settings where the loading is done and then the code contains calls to ConfigurationManager.AppSettings["MySettingHere"] ..
..but my WinForms app doesnt use this method. Instead it uses the Project Settings route (i.e. I call Properties.Settings.Default.MySettingName to get my value, and I edit my settings by getting properties on the project and choosing the Settings tab)
App.config as a file is present in the root of the project/solution, but there is also Settings.settings and Settings.Designer.cs and I think these are the ones used and transformed into compiled code that gets the data
Essentially Visual Studio provides a type safe wrapper around the settings load/save/value getting process, and what I'd like to do is supply a path of the settings file to load rather than have it stuck at taking the default MyExeName.config file from the application directory
I assume you want to load custom configuration file from desired location rather than loading the default config, then try this,
NOTE : You can't have more than one App.config in a project.The app will use the config file named YourExcecutable.exe.config which is by
default the file App.config. But you can have multipe configuration
files and load then as you need using code. But you can't keep all of
them loaded at the same time. you can only switch between the files as
you need.
System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap("path to new file");
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
OR
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", #"Config file path");
The only solution I have found so far is rather a poor man's solve..
When we use the Settings tab inside a project's properties, the solution will gain a Settings.Settings, Settings.Designer.cs under the project's Properties node and possibly also an app.config in the root of the project. Edits to these files directly seem to be copied/updated /synchronised by VS itself. It also maintains some code in the background to ensure data-typed access to these settings. Likely it's based on Configmanager.AppSetings["propertyName"] but because VS is used to set up the property, and you tell it it's an int (or whatever) then VS can write wrapper code that exposes a namespace/class/member chain of ProjectNamespace.Properties.Settings.Default.PROPERTYNAME
Seemingly this code relies on the settingsfile being called THE_EXE_NAME.exe.config and being stored alongside the EXE itself..
..so I just take the the settings file that I want to use, copy it over the top of the one stored on disk, and call ProjectNamespace.Properties.Settings.Default.Reload() which does reload the values I want to use out of the new file. I can think of countless reasons why this isn't ideal but it's all I've been able to come up with so far

How to get an Application Settings shared to all users that could be changed at run time

I need some setting of an application that will be shared among all users of the computer, but could also be changed at at run time. That seam simple, but according to the Application Settings MSDN article, it's either one or the other.
There are two types of application settings, based on scope:
Application-scoped settings can be used for information such as a URL for a Web service or a database connection string. These values are associated with the application. Therefore, users cannot change them at run time.
User-scoped settings can be used for information such as persisting the last position of a form or a font preference. Users can change these values at run time.
I could write code to edit the app.config XML file, but since it's located in the program directory, it's protected under windows 7. So this is not possible without elevating the program or playing with NTFS rights.
So I need the configuration file to be written in a common folder like System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData).
But this is a fairly common requirement!
So, I'm wondering if there a simple way of achieving this without reinventing the wheel, or if I have to write my own Setting Manager.
After reading the answers here and playing with the ConfigurationManager.Open methods I ended up with the following:
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MyApp", "MyApp.config");
Configuration MyAppConfig = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = path }, ConfigurationUserLevel.None);
The nice part is the file doesn't have to exist, and if you call Save() on it, it will create the folder and the file for you. AppSettings["key"] didn't work though so I had to use
MyAppConfig.AppSettings.Settings["key"].Value
to read and write an existing value and
MyAppConfig.AppSettings.Settings.Add("key", value)
to add a new value.
I have had a similar problem and ended up writing my own settings class. It was very basic. I created a Settings class with the properties I needed, and a SettingsManager with Save() and Load() methods that simply serialized/deserialized the object via XmlSerializer into/from a file.
Yes, it is your own code, but it is very simple code, takes less time than trying to figure out whether there is a component providing what you need and how to customize it.
The Application Settings infrastructure does not support this - only non-editable application data and user-scoped data are supported. You can easily read and write your own XML into the CommonApplicationData folders, however, instead of using the application data.

Letting users edit config file after deployment

I have a program which I'm going to deploy using the package for deployment built into VS.
Now I have an app.config file which I want the user to be able to modify (even after running the program), but I have no idea where exactly the installer dumps the files, and I'm not expecting the users to root around their filesystem.
What I was thinking is - I ask the user to specify some directory (which needs to happen anyway since its a game) - I check for the config file there, and if its not there, I copy it from the root directory the program can see - then read the one in the 'save' folder.
That said, its sounding like a very ugly and hacky solution - is there a better one?
I wouldn't be encouraging users to modify the app.config. The app.config is copied into the same directory as your app exe and usually contains settings which your app depends on to run correctly e.g. DB connection strings, system defaults etc. Your playing a dangerous game by letting users change settings in there directly.
A safer approach would be to export another XML file into the users documents folder where they can override app settings. Have your app load in the app.config first then override those values with any settings found in the users own config file.
I would also recommend implementing some sort of UI for this, even if its really basic. Your average user isn't going to be comfortable editing XML directly, too much margin for error.
You could use the application (or user) settings to persist any changes that the user might want to make in the configuration. See the ApplicationSettingsBase class and this article.
Say your application contains a user setting called Score, managed internally by a class called MyUserSettings:
public class MyUserSettings : ApplicationSettingsBase
{
[UserScopedSetting()]
[DefaultSettingValue(0)]
public int Rank
{
get
{
return (int)this["Score"];
}
set
{
this["Score"] = value;
}
}
}
You can save the current values, usually when the main form is closing, using the Save method:
myUserSettings.Save();
If you want users to modify some settings directly, you can use a property grid or your own form that binds the instance of MyUserSettings class.
If the settings are marked as "User", then the values would be stored in the user.config file, in %InstallRoot%\Documents and Settings\username\Local Settings or %InstallRoot%\Documents and Settings\username\Application Data (for roaming profiles).

Remembering fileName after application closes

In my C# WPF application, I want to incorporate something like 'last used file remember feature'
So, if previously the user has opened some file (and remembered it), the next time on opening the application, the file should open automatically.
Other than writing the path of the file, is there any other way to this?
If I have to write the path to the file, what's the location mostly used to store these temp remembered file paths and keep away from user? (some environment folder?)
You can specify User Settings to store some information. In the Solution Explorer go to your project and in the folder Properties, double-click the settings-file. In here you can set the Name, Type, Scope and Value. Just set the Name to "FileName", Type to "string", scope to "User" and leave the Value empty or set a default value if you want. Save the settings-file. In code you can set and get the value like this:
//get
var name = Properties.Settings.Default.FileName;
//set
Properties.Settings.Default.FileName = "....";
Properties.Settings.Default.Save();
Hope this helps!
I think you can use ont of this .NET features:
User Settings
Application Settings
They save settings with different scope. I guess you can use application settings.
Usually there are three location available for this kind of configuration.
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
The first is to be used if the configuration applies to the whole application
The second is to be used if the configuration applies only to the current user (roaming)
The third is to be used if the configuration applies only to the current user (local)
In each case you should create a subfolder in these paths with the name of your company and then the name of your product. Never save directly there.
I prefer to stay away from changing config files from code although I must admit it is very convenient

Categories

Resources