How to modify the App.Config section value - c#

I have an app.config like below,
<configuration>
<environment>
<add key="security" value="1"/> -- I want to change this value to 3
</environment>
</configuration>
I tried like below to get to environment section,
Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);
var environment = config.GetSection("environment");
environment variable doesn't give me enough options to get the child elements to modify the value. Could any one please help me out in this one.

Use user scope settings!! NEVER EVER change the application configuration that way. Any value that is changed within the application should be a user setting.
Usually, you access these settings through
Properties.Settings.Default.MyConfigurationValue = ....;
Properties.Settings.Default.Save();
EDIT
Sample for doing what I wrote in the comments. Create two user settings: FirstRun is a bool which is by default set to true. Environment is your value, by default set to 0.
Then, for example in the Main function in Program.cs you'd do the following:
if (Properties.Settings.Default.FirstRun)
{
Properties.Settings.Default.FirstRun = false;
if (myConditionIsTrue)
Properties.Settings.Default.Environment = 3;
Properties.Settings.Default.Save();
}
Later in your application it is enough to use Properties.Settings.Default.Environment. That's how the settings mechanism is intended to be used if you want to change configuration values from your application.
Under Windows 2000, XP, 7 and the Windows Server branch you would not even have the rights to modify the app.config in your Program Files folder, so don't!

Related

Make C# Console App recognize manually edited changes in .exe.config file

I successfully wrote a C# console application that collects .XML or .ZIP files from different locations and copies them to a single destination. Those locations are stored in the settings as User-scoped settings (for instance, "Folder01 C:\Data1\" and "Folder02:\Data2"). As you probably already know, building the project generates a [ProjectName].exe.config file in the /bin/Debug folder.
Now, the issue is that I cannot get the console app to recognize any changes that I made in the .exe.config file. Say, I want to add "Folder 03 C:\Data3\" to the settings or edit "Folder02" path to "C:\DataEdited\", the console app will still loop through the settings as initially set up in the code ("Folder01 C:\Data1\" and "Folder02 C:\Data2\").
I also noticed that the console app still runs even after deleting the .exe.config file, as if it does not rely on the file at all. I would like to make changes without having to open the project in Visual Studio and edit locally.
Is that possible?
EDIT:
In response to the request of the Settings that I created and code for getting folder paths, see image image below:
Here is the code:
string[] acceptedExtensions = new[] { ".xml", ".zip" };
string[] settingsToSkip = new[] { "RootFolder", "ArchiveFolder" };
// Collect data
var filteredSettings = Properties.Settings.Default.Properties
.Cast<SettingsProperty>()
.Where(p => !settingsToSkip.Contains(p.Name));
filteredSettings collects Folder01, Folder02, Folder03 and Folder04 and I loop through those to find files with acceptedExtensions.
I believe you expected this feature of c# ConfigurationManager. You might have deleted *.exe.config after your application is started. *.exe.config is not locked or needed after app starts unless you call configurationmanager.refreshsection() method.
Reloading configuration without restarting application using ConfigurationManager.RefreshSection
https://learn.microsoft.com/en-us/dotnet/api/system.configuration.configurationmanager.refreshsection?view=netframework-4.7.2
Thumbs up and mark it if it helped you!
How I have done it in my production code is that I have added to my App.config with my Visual Studios and made it have the format of:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="AConnection" value="127.0.0.1"/>
<add key="Folder01" value="L:\Path\To\A\Thing"/>
<add key="Folder02" value="L:\Path\To\ASecond\Thing"/>
<add key="Folder03" value="L:\Path\To\AThird\Thing"/>
<add key="Folder04" value="L:\Path\To\AFourth\Thing"/>
</appSettings>
</configuration>
Where the <add key="" value="">s are whatever you wish to name them and the values is the path to the correct file.
Assigning:
You can then assign these to variables:
string conStr = ConfiurationManager.AppSettings["AConnection"];
string strFolder1 = ConfigurationManager.AppSettings["Folder01"];
string strFolder2 = ConfigurationManager.AppSettings["Folder02"];
string strFolder3 = ConfigurationManager.AppSettings["Folder03"];
string strFolder4 = ConfigurationManager.AppSettings["Folder04"];

Settings value saved during run time is not changing from design in visual studio

At my settings file i have a parameter "Is_Running" and it value is set as 0
at run time i will check the value like below
if(Settings.Default.Is_Running == 0)
{
Settings.Default.Is_Running = 1;
Settings.Default.Save();
upload_file();
Settings.Default.Is_Running = 0;
Settings.Default.Save();
}
Due to some reason i stopped the program in the middle of execution. Now the condition is always failing. So i checked value of Is_Running using a message box and it shows "1". I checked the app config file and it shows below
<setting name="Is_Running" serializeAs="String">
<value>0</value>
</setting>
Any idea why it still use "1"?
In VS you change the default values of settings. Real settings are stored in the path C:\Users\<UserName>\AppData\Local\<CompanyName>\<AppName>\<v‌​ersion>\user.config (for applications).
Added by #Sachu.
Since my application is windows service installed in server level, the path is little different. What I done is searched for user.config then got the file and path. Changed the value to 0 and it worked fine.
In my case the path is:
C:\Windows\SysWOW64\config\systemprofile\AppData\Local\<application_folder_name>
\<application_name>\<version>\user.config

C# app.config read and write

Can we save data or some text in app.config file
if yes then it is persistence or temporary ?
for example if i store last access date time in app.config file and then close/Exit the application after the some time/days/years when i start my application is it possible that the last access date time I can retrieve. If yes then how please explain with code ....
Thanks,
Raj
here is my code ..
Trying to retrieve date time from config file..
But show error object not set to be an object like...
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (email.To.Contains(Email) && DateTime.Compare(email.UtcDateTime.Date, Convert.ToDateTime(config.AppSettings.Settings["ModificationDate"].Value)) > 0)
Here i store /save the date time in app.config file.
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration
(ConfigurationUserLevel.None);
// Add an Application Setting.
config.AppSettings.Settings.Add("ModificationDate", DateTime.Now + " ");
// Save the changes in App.config file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");
Console.WriteLine("Last Update :"+config.AppSettings.Settings["ModificationDate"].Value);
Console.ReadLine();
Please suggest me why it show me an error that object not set am done any mistake please ans...
You can create a settings xml file to do this.
In VS go to your project properties -> Settings, then write a value in.
In code, you can get/set that value using
Properties.Settings.Default.YourVariable = 0;
If you are setting the value make sure to save it
Properties.Settings.Default.Save();
See here for a good tutorial.
I would use a custom configuration section to create your configuration type - last access date time. you can create more complex hierarchy configuration and strongly-typed.
Again, it depend on your requirement and design if you need to do that. otherwise, standard file storage(txt/xml) would also allow you to do that. I personally normally using app.config for application specific level(appearance/fonts/servername etc.) configuration rather than transactional configuration.
for e.g
public class LastAccessConfigurationSection : System.Configuration.ConfigurationSection {
[ConfigurationProperty("LastAccess")]
public string LastAccess{
get { return (string)this["LaunchTime"]; }
set { this["LaunchTime"] = value; }
}
}
you can have a static class to manage the life-cycle that would allow you to persist the change.
public static LastAccessConfigurationSection Config { get; internal set; }
public static void Initialize() {
Config = ConfigurationManager.GetSection("LastAccess") as LastAccessConfigurationSection;
}
You could use App.config for storage like any other file and it will persist and be available the next time you run your program. That is the nature of file storage in general. I would suggest that you store that data in a separate file or database. I will not, however, write the code for you.

How to correctly iterate application settings in C# using reflection

I am trying to iterate through application properties in C# using reflection (.NET 3.5 using VS 2010). The code "works" in that it successfully gets properties. However, it always gets the property values that were defined at design time and does not see the current values in myapp.exe.config. Properties that I access directly by name do reflect what is in the .config file. Here is the reflection-based code which only sees design-time properties:
List<StringDictionary> dictList = new List<StringDictionary>();
StringCollection bogus = new StringCollection();
foreach (PropertyInfo info in Properties.Settings.Default.GetType().GetProperties())
{
if (!("logLevel".Equals(info.Name) || "eventURL".Equals(info.Name)))
{
if (bogus.GetType().IsAssignableFrom(info.PropertyType))
{
StringCollection rawConfig = (StringCollection)info.GetValue(Properties.Settings.Default, null);
// do something
}
}
}
This code does pick up the current values in myapp.exe.config.
String logLevelStr = Properties.Settings.Default.logLevel
What am I doing wrong in my reflection code that causes me to pull only the properties defined at design time and not what is currently in myapp.exe.config?
To get the current value you need to use something like this which looks at Default.PropertyValues instead of Default.Properties
foreach (SettingsPropertyValue property in Properties.Settings.Default.PropertyValues)
{
Debug.WriteLine(string.Format("Property {0}'s value is {1}",property.Name,property.PropertyValue));
}
// note: the above may not work in some multi-form app, even if the applicaton prefix is prepended in front of Properties esp for visual studio 2010 compiled app with .net frame work 4
I think that there is a fundamental misunderstanding here. Settings can be one of two types- Application settings and User settings.
Application settings are intended to be written only at design time. As Henk points out it is possible to edit them after deployment if you are admin, but that isn't really the intent. Also, it should be noted that while Application settings are stored in the .config file, they are only read once and then cached in memory. That's why you don't see the new values when you edit the file.
User settings can be overwritten at run time by application code and saved, but they are saved at a user scope, so a different user running the same application can have different values. The intention there was things like user preferences. There is a drop down in the settings designer grid to switch between Application and User scope for each Setting.
Either way, you shouldn't be accessing them via reflection.
There must be some kind of misunderstanding here.
If you want to read the configurations from myapp.exe.config you should use ConfigurationManager. This class allows you to access AppSettings and ConnectionString directly through static properties or read custom sections by the GetSection method.
Beside, application configurations are meant to be design-time only. You shouldn't alter myapp.exe.config at runtime. Never. This file must be the same for each execution of your application.
Beside, what is Properties.Settings.Default.logLevel ???
Consider:
foreach (SettingsProperty sp in Settings.Default.Properties)
{
Console.WriteLine(sp.Name + "=" + Settings.Default.Properties.Default[sp.Name].ToString());
}

Is it possible to modify configuration ConnectionStrings at runtime?

Is it possible to modify the connectionstrings defined in the app.config/web.config at runtime? I want to use different configfiles depending on the machine the app/site is run on (only for debugging purposes, of course. We'll use the regular config files when deployed).
I can write AppSettings, but not ConnectionStrings (AFAIK). Or can I?
Yes it's possible, but AFAIK only via Reflection. The following code should do what you need (read below for usage):
public static string SetConnectionString(Type assemblyMember,
Type settingsClass,
string newConnectionString,
string connectionStringKey)
{
Type typSettings = Type.GetType(Assembly.CreateQualifiedName(assemblyMember.Assembly.FullName, settingsClass.FullName));
if (typSettings == null)
{
return null;
}
PropertyInfo prpDefault = typSettings.GetProperty("Default", BindingFlags.Static | BindingFlags.Public);
if (prpDefault == null)
{
return null;
}
object objSettings = prpDefault.GetValue(null, null);
if (objSettings == null)
{
return null;
}
// the default property, this[], is actually named Item
PropertyInfo prpItem = objSettings.GetType().GetProperty("Item", BindingFlags.Instance | BindingFlags.Public);
if (prpItem == null)
{
return null;
}
object[] indexerName = { connectionStringKey };
string oldConnectionString = (string)prpItem.GetValue(objSettings, indexerName);
prpItem.SetValue(objSettings, newConnectionString, indexerName);
return oldConnectionString;
}
assemblyMember is the calling type
settingsClass is the type of your settings class
newConnectionString is the full string to set
connectionStringKey is the name of the connection string that you defined in your app's settings
You should call this method as soon as possible after your app has started, preferably in the Main() method.
I tried this once in my project for debugging purpose but could not do it, the problem (I guess, correct me if I am wrong) is on app start up the app.config gets loaded into the memory, any changes to app.config while the app is running do not get reflected.
To overcome this here's what I did, define all the connectionstrings in the app.config and then call the ones that you want when your program is running like this.
for example lets assume you defined your connectionstrings in the app.config as follows.
<connectionStrings>
<add name="YourNameSpace.Properties.Settings.ConnectionString_1"
connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=|DataDirectory|\file.mdb"
providerName="System.Data.OleDb"/>
<add name="YourNameSpace.Properties.Settings.ConnectionString_2"
connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=|DataDirectory|\file.mdb"
providerName="System.Data.OleDb"/>
</connectionStrings>
define as many as you want (you are debugging right :-) )
then to call those connection settings in your code do something like this:
YourNameSpace.Properties.Settings foo = new YourNameSapce.Properties.Settings();
foo.ConnectionString_1;
HTH
Best Regards
#nand
P.S: This reply is specific to C#.
You can't really edit the config file of the running process.
One option (with pros and cons) is to use config data in the machine.config or the master web.config (for "site", you use the "location" nodes) - not an option to rush into, though.
A better way to handle this is to swap the config file as part of your build/deploy process, ideally automated. That way, everything is self-contained, and you can "robocopy" to a vanilla server and have it work.
Re your "per developer" point; I found that the easiest way to do this was to standardise the config, and tweak the machines. For example, we run a local web-server on a VM; rather than code against each machine, we standardise on "localserver" (to mirror "localhost"), and add a local DNS record to each machine that the developer can control. Note that this requires fixed IP addresses (or maybe a DHCP reservation) to prevent it changing over time!
Ditto databases; local servers can use "."; remote servers can be aliased on the machine, so "devserver" points to whatever the user wants.
Just a thought...
You could run xmlpoke in a NAnt script when installing the website.
E.g.
Deploy the NAnt with the website.
Create a go.bat that calls NAnt which installs the site and does xmlpoke to modify the web.config with settings based on the server name or some other parameter.

Categories