Reputation: 489
I need to know where and how application settings (connections string) could be stored so that they can be changed at run time and saved.
I know in VS you can configure settings under Project>Properties and these get stored in the appname.exe.config file under apps install directory.But the "application scope" ones are not read/write at run time and if you change the ones under user scope a copy of the config file is created under users directory and wont be accessed by other users of the application.
I need to have a way so that the user can configure connection string, stored in a common config file, as per their needs from within the app and then have all other users(on that machine) can use that too. how can I achieve this?
Upvotes: 2
Views: 3303
Reputation:
Simplest, fastest solution is to create a configuration file in a shared location where normal users have rights to read/write.
Create a class with public properties for your configuration data, then serialize it to xml in this shared location.
public class Configuration
{
// config filename
private static _name = Path.Combine(
System.Environment.GetFolderPath(
Environment.SpecialFolder.CommonApplicationData),
@"MyApp\MyConfig.xml");
// the connection string
public string ConnectionString {get;set;}
// load the configuration from disk
public static Configuration Load()
{
using (var f = File.OpenRead(name))
{
var x = new System.Xml.Serialization.XmlSerializer(typeof(Configuration));
return x.Deserialize(f) as Configuration;
}
}
// save the configuration to disk
public static Save(Configuration config)
{
using (var f = File.OpenWrite(name))
{
var x = new System.Xml.Serialization.XmlSerializer(typeof(Configuration));
x.Serialize(f, config);
}
}
}
Upvotes: 9
Reputation: 22492
Application scope connection strings are writable, but you have to go about it differently from just getting the string for usage. For example:
Configuration c = ConfigurationManager
.OpenExeConfiguration(ConfigurationUserLevel.None);
c.ConnectionStrings.ConnectionStrings["myConnectionString"]
.ConnectionString = "theConnectionString";
c.Save();
You should also refresh the section so that the change is properly retrieved. Immediately afterward:
string sectionName = c.ConnectionStrings.SectionInformation.SectionName;
ConfigurationManager.RefreshSection(sectionName);
Upvotes: 5
Reputation: 106796
As other have pointed out you need to create a shared location on the computer that is writable by all users of your application. This location can be a folder, a file or the registry. However, Windows actually have a location for this. You can read more about this on MSDN. The folder you need is for common application data:
CSIDL_COMMON_APPDATA
This folder should be used for application data that is not user specific. For example, an application may store a spell check dictionary, a database of clip-art or a log file in the CSIDL_COMMON_APPDATA folder. This information will not roam and is available to anyone using the computer. By default, this location is read-only for normal (non-admin, non-power) Users. If an application requires normal Users to have write access to an application specific subdirectory of CSIDL_COMMON_APPDATA, then the application must explicitly modify the security on that sub-directory during application setup. The modified security must be documented in the Vendor Questionnaire.
You can get the location of this folder by calling
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
in your .NET application. On Vista this folder is normally C:\ProgramData
.
You have to create your own vendor and application specific folder inside the shared folder and this should be done by an install program running with elevated privileges. This install program should also make sure that users have the necessary privileges to get write access as seen in the quote above.
Upvotes: 2
Reputation: 2089
The way I did it was I saved an XML file that was serialized from a POCO object that had the SQL Connection information into isolated storage. Since there are no real restrictions on the user account that can read and write from there, you don't have to worry about user permissions.
I then modified the settings events so that when the connection string property was read from the app settings file, I instead deserialized the XML file in isolated storage, built the connection string, and then put that into the app settings connection string property. Since I was doing this inside the settings class itself, I was able to write to it (but not save back to the file).
When my app runs, if it can't connect to the server I just pop up a window asking for the sql server info and they type it in and it saves it to the isolated storage, never to ask them for it again (even through upgrades).
If you have a client application (WPF or WinForms), users on other machines will not be able to use this and quite frankly you probably will not find a solution for that, unless you look into .Net Remoting or something of that nature. However, if you have multiple users on the SAME machine in a WinForms App, you can use the IsolatedStorage and it will work for all users.
In the settings class, add this event handler:
VB:
Private Sub MySettings_SettingsLoaded(ByVal sender As Object, ByVal e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded
Me.Item("MyAppConnectionString") = MyLibrary.BuildConnectionString()
End Sub
C#:
protected override void OnSettingsLoaded(object sender, System.Configuration.SettingsLoadedEventArgs e)
{
base.OnSettingsLoaded(sender, e);
this["MyAppConnectionString"] = MyLibrary.BuildConnectionString();
}
Upvotes: 1
Reputation: 415600
You have some conflicting elements in your question:
application settings (connections string) could be stored so that they can be changed at run time and saved.
.
application scope" ones are not read/write at run time and if you change the ones under user scope a copy of the config file is created under users directory and wont be accessed by other users of the application.
Best practices dictate that settings (like connection strings) that you want to apply to every user of a system should not be changeable by any random user of the system. That kind of setting should only be changed by someone qualified to administer the system.
Therefore, the behavior you describe is exactly what's intended. If you really want to allow users to change this, then make it a user setting so if a user screws it up they only screw it up for their own account.
Upvotes: 0
Reputation: 75296
Reading and writing to the Registry used to be the recommended way of storing user settings, and you can still do this easily (using Microsoft.Win32.Registry), but there are issues with this approach (mainly due to varying permissions levels among your users - some users aren't allowed to write to some parts of the registry or create new keys).
Upvotes: 0