I have myapp.somenamespace.exe.config file with a connectionStrings section, which I need to encrypt. Also there are some other config settings that I want intact. So I wrote this small tool that would do just that:
class Program
{
static void Main(string[] args)
{
EncryptSection("myapp.somenamespace.exe.config", "connectionStrings");
}
static void EncryptSection(string fileName, string sectionName)
{
var config = ConfigurationManager.OpenExeConfiguration(fileName);
var section = config.GetSection(sectionName);
if (section.SectionInformation.IsProtected) return;
secction.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
config.Save();
}
}
What happens, it creates a new config file named myapp.somenamespace.exe.config.config - adding a duplicate .config extension, which only contains the encrypted section. It does not modify the original config file.
Any ideas why such an odd behavior and how I could fix that?
Change this line:
EncryptSection("myapp.somenamespace.exe.config", "connectionStrings");
to this:
EncryptSection("myapp.somenamespace.exe", "connectionStrings");
the documentation on MSDN states that the first parameter is in fact he path of the executable (exe) file and thus it's tacking on an additional .config during Save.
Related
I have added multiple app.config (each with a differet name) files to a project, and set them to copy to the output directory on each build.
I try and access the contents of each file using this:
System.Configuration.Configuration o = ConfigurationManager.OpenExeConfiguration(#"app1.config");
The code runs, but o.HasFile ends up False, and o.FilePath ends up "app1.config.config". If I change to code:
System.Configuration.Configuration o = ConfigurationManager.OpenExeConfiguration(#"app1");
Then the code bombs with "An error occurred loading a configuration file: The parameter 'exePath' is invalid. Parameter name: exePath".
If I copy/paste the config file (so I end up with app1.config and app1.config.config) then the code runs fine, however, I posit this is not a good solution. My question is thus: how can I use ConfigurationManager.OpenExeConfiguration to load a config file corretly?
I can't remember where I found this solution but here is how I managed to load a specific exe configuration file:
ExeConfigurationFileMap map = new ExeConfigurationFileMap { ExeConfigFilename = "EXECONFIG_PATH" };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
According to http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/3943ec30-8be5-4f12-9667-3b812f711fc9 the parameter is the location of an exe, and the method then looks for the config corresponding to that exe (I guess the parameter name of exePath makes sense now!).
To avoid this problem altogether, you can read in the config file as an XML file, for example:
using System.Xml;
using System.Xml.XPath;
XmlDocument doc = new XmlDocument();
doc.Load(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\..\\..\\..\\MyWebProject\\web.config");
string value = doc.DocumentElement.SelectSingleNode("/configuration/appSettings/add[#key='MyKeyName']").Attributes["value"].Value;
using System.Reflection;
try
{
Uri UriAssemblyFolder = new Uri(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
string appPath = UriAssemblyFolder.LocalPath;
//Open the configuration file and retrieve
//the connectionStrings section.
Configuration config = ConfigurationManager.
OpenExeConfiguration(appPath + #"\" + exeConfigName);
ConnectionStringsSection section =
config.GetSection("connectionStrings")
as ConnectionStringsSection;
}
At least, this is the method I use when encrypting and decrypting the connectionStrings section for my console/GUI apps. exeConfigName is the name of the executable including the .exe.
The user.config file of an application can be accessed in C# by
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath
Now, I need to get the user.config of a DIFFERNT application, identified by the fullpath to its exe in order replace current applications user.config by that one.
Any suggestions how to do so?
Edit: Please notice that I am interested in the user.config (ConfigurationUserLevel.PerUserRoamingAndLocal), not the application level settings like app.config or Application.exe.config. The latter is accessable by the OpenExeConfiguration(string), but is not what I want.
What about the overload that accepts a string?
var config = ConfigurationManager.OpenExeConfiguration(pathToAssebmly);
Anyway it´s a bad idea to bind your assembly that way to another one. You should consider to copy the config-file into all your assemblies and change the parts that are specific to a given one.
EDIT: As you´re interested in the user-specific setting you may use the following which is taken from here:
string configFile = string.Concat(appName, ".config");
// Map the new configuration file.
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap
{
ExeConfigFilename = configFile
};
var config = ConfigurationManager.OpenMappedExeConfiguration(
configFileMap,
ConfigurationUserLevel.PerUserRoamingAndLocal);
My requirement is to update the appsettings file at run time when the application is started. But encountered with a problem where web config is getting replaced every minute with the new appsettings. How can I stop replacing every minute?
I have gone through different solutions here and implemented as below:
In web config we have default path for appsettings:
appSettings file="C:\Config\MyProj\Appsettings.Config"
In the Global.asax.cs, I am calling the following method to replace the my appsettings file dynamically.
public void ChangeAppSettings(string path)
{
System.Configuration.Configuration configuration = null;
if (System.Web.HttpContext.Current != null)
{
configuration =
System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
}
else
{
configuration =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
}
// update appconfig file path
configuration.AppSettings.File = path;
// Save the configuration file.
configuration.Save(ConfigurationSaveMode.Modified);
// Force a reload in memory of the changed section.
ConfigurationManager.RefreshSection("appSettings");
}
Or is there a better way to implement?
Following code did the trick, for somereason every time we refresh the config ChangeAppSettings method is called. So I just added to check if the config is already modified then don't refresh anymore.
if (!path.Equals(configuration.AppSettings.File))
{
// update appconfig file path
configuration.AppSettings.File = path;
// Save the configuration file.
configuration.Save(ConfigurationSaveMode.Modified);
// Force a reload in memory of the changed section.
ConfigurationManager.RefreshSection("appSettings");
}
I am using .NET 4.0 and I would like to use the app.config file to store same parameter settings. I do the following. I use the Settings tab in the project properties to create my parameters.
This add the information in the app.config file like this:
<MyApp.Properties.Settings>
<setting name="param1" serializeAs="String">
<value>True</value>
</setting>
<MyApp.Properties.Settings>
In my view model (in my code) I can access to the information in this way:
bool myBool = MyApp.Properties.Default.param1;
When I try to change the value in the config file, I try this:
Properties.Settings.Default.param1 = false;
But this causes an error, that param1 is read-only.
So how can I update my config file from my code?
Here's my function to update or add an entry into the app.config for "applicationSettings" section. There might be a better way, but this works for me. If anyone can suggest a better method please share it, we'll always looking for something better.
static string APPNODE = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Properties.Settings";
static DateTime now = DateTime.Now;
Utilities.UpdateConfig(APPNODE, "lastQueryTime", now.ToString());
static public void UpdateConfig(string section, string key, string value)
{
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ClientSettingsSection applicationSettingsSection = (ClientSettingsSection)config.SectionGroups["applicationSettings"].Sections[section];
SettingElement element = applicationSettingsSection.Settings.Get(key);
if (null != element)
{
applicationSettingsSection.Settings.Remove(element);
element.Value.ValueXml.InnerXml = value;
applicationSettingsSection.Settings.Add(element);
}
else
{
element = new SettingElement(key, SettingsSerializeAs.String);
element.Value = new SettingValueElement();
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
element.Value.ValueXml = doc.CreateElement("value");
element.Value.ValueXml.InnerXml = value;
applicationSettingsSection.Settings.Add(element);
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("applicationSettings");
}
Well, I read the link of Hari Gillala, in which one user suggested to edit directly the app.config file, that is a xml file.
So in project properties-->settings I create the parameters that I need. Then, to load a parameter in code I do the following:
_myViewModelProperty = MyApp.Properties.Settings.Default.MyParam1;
In this way, I can read easily the information of the config parameter. Is typed, so in disign time I can see if the asign is correct or not.
To update de config file, I edit the app.config file with the xml libraries of .NET.
System.Xml.XmlDocument xml = new System.Xml.XmlDocument();
xml.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
System.Xml.XmlNode node;
node = xml.SelectSingleNode("configuration/applicationSettings/MyApp.Properties.Settings/setting[#name='myparam1']");
node.ChildNodes[0].InnerText = myNewValue;
xml.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
In this way, I create a xml document (xml variable) and load the information of the app.config file. Then, I search for the node that I want to update, update its information (InnerText property) and finally I save the changes.
In this way, I can update the app.config. It is what I want, because in a portable application, only one user will use it, and I want that the configuration is applied in any computer in which I run the application.
You should use Properties.Settings to perform this action.
You can look at this documentation for more information.
//modify
Properties.Settings.Default.param1 = false;
//save the setting
Properties.Settings.Default.Save();
Note that if your settings have the Scope of User, which they must be to be writeable, then the properties are saved somewhere else and not in your local config file. See here for the details.
EDIT after discussion in comment and further searches:
My suggestion to achieve the desired result would be to switch to AppSettings.
That is because, after some searches, i found out that appsettings changes the .config file in the Application Data folder (running some tests on my machine confirm that).
Look at comment in the answer to this question .
I am not sure if there is some work around, but if you want your application to have a portable app.config file, i think the only way is to switch to AppSettings which i'm sure can save changes in the app.config found in the program folder.
EDIT 2: Possible solution
I found out a possible solution to make your app portable!
You can change the Provider used by Settings to save the application's settings creating a custom Provider.
The answer to this question provide a link to a code to make applicationsettings portable. I think you give it a try
Mark your setting as usersetting.
Detailed article: http://www.codeproject.com/Articles/25829/User-Settings-Applied
I have an application that stores single username and password on the app.config file.
I currently have the app.config writable on runtime so that the user will be able to change it.
problem begins upon installation using a setup project , the app.config is installed on the program files which is not writable for any user.
So , i have changed the app.config location upon installation to the common files folder so it will be accessible for reading and writing for all users.
Now, upon installation it seems that the data stored there is inaccessible at all , using ConfigurationManager.AppSettings["networkPath"] for example returns empty strings.
what am i doing wrong ?
You can do it in two ways:
Give special permission to app config file in program files by your installer. We do it using innosetup. If you are incapable of it, then do it from your program startup:
static void Main()
{
GrantAccess()
}
private static bool GrantAccess()
{
FileInfo fInfo = new FileInfo(Assembly.GetEntryAssembly().Location + ".config");
FileSecurity dSecurity = fInfo .GetAccessControl();
fSecurity.AddAccessRule(new FileSystemAccessRule("everyone",
FileSystemRights.FullControl,
AccessControlType.Allow));
fInfo .SetAccessControl(fSecurity);
return true;
}
Else you can choose another location to place your appconfig file, and then read it like this:
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), Assembly.GetEntryAssembly().GetName().Name) + ".exe.config";
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap,
ConfigurationUserLevel.None);
return config.AppSettings.Settings["Key"].Value);
This is a poor choice in my opinion.