Can I modify a custom configuration section using ConfigurationManager? - c#

I have an App.config of the form
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="Custom.Config" type="System.Configuration.DictionarySectionHandler, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<kCura.Config configSource="Custom.config" />
</configuration>
With a custom configuration file Custom.config of the form
<?xml version="1.0" encoding="utf-8"?>
<Custom.Config>
<add key="foo" value="bar" />
</Custom.Config>
I've inherited this code, and there is no existing ConfigurationSection or ConfigurationSectionHandler associated with this Custom.Config section.
I can access the value of foo just fine with
DirectCast(System.Configuration.ConfigurationManager.GetSection("Custom.Config"), System.Collections.IDictionary)
But now I would like to update this value, programatically (for testing purposes). Is this possible?
I've read the following, and I'm still stumped; they seem to imply that this namespace is only for reading values, not full CRUD:
How to: Create Custom Configuration Sections Using ConfigurationSection
How to: Create Custom Configuration Sections Using IConfigurationSectionHandler

You'll have to modify the Custom.config file on disk by using XDocument then you'll need to call RefreshSection on the ConfigurationManager
This will then refresh the named section so the next time that it is retrieved it will be re-read from disk.

Related

C# - The configuration section was not found error using aspnet_regiis.exe

I am trying to Encrypt sensitive connection string information inside my app.config file for a C# applicaiton that I am developing. I am using the following command from the VS command promt running as administrator:
aspnet_regiis.exe -pef "Credentials" "C:\Users\.....\MyProjectFolderDir"
This is the structure of my app.config file:
<?xml version="1.0" encoding="utf-8" ?>
<config>
<configSections>
<section name="ApplicationSettings" type="sometype"/>
<section name="WebSettings" type="sometype"/>
<section name="Credentials" type="sometype"/>
<section name="SQLServerSettings" type="sometype"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<ApplicationSettings Mode="mymode"
FileSearchMode="myfilemode"
SubtractHoursDebugging="0"/>
<WebSettings WebApiServers=""
CredentialMethod="mymethod"/>
<Credentials
Domain="mydomain"
UserName="myusername"
Password="mypassword"/>
<SQLServerSettings
ConnectionString="Server=***********"/>
</config>
However, I keep getting the following error:
Encrypting configuration section...
The configuration section 'Credentials' was not found.
Failed!
How can I get this to encrypt my section?
Your config file should start with <configuration> element and not <config>. Since it's <config> aspnet_regiis.exe thinning Credentials as nested element and thus the error. With your current config file the command should be
aspnet_regiis.exe -pef "config\Credentials" "C:\Users\.....\MyProjectFolderDir"
First of all here's an answer that you can learn from about custom configuration section How to create custom config section in app.config? and here is an example from msdn https://msdn.microsoft.com/en-us/library/2tw134k3.aspx
Second, the type usually refer to a real model so you should enter the namespace and the class that you created to model the type of configuration you would like to use like so:
<configuration>
<configSections>
<section name="sampleSection"
type="System.Configuration.SingleTagSectionHandler" />
</configSections>
<sampleSection setting1="Value1" setting2="value two"
setting3="third value" />
</configuration>
Hope it helps
So as it turns out, aspnet-regiis.exe is exclusively for web.config files. It doesn not work with app.config files unless you rename to web.config. Instead of renaming my app.config everytime I wanted to encrypt/decrypt, I ended up creating a class that would handle this each time I ran the application. Make sure you are using the following:
using System.Configuration;
using System.Web.Security;
Class:
internal class Crypto
{
internal static AppSettingsSection GetEncryptedAppSettingsSection(string exeConfigName)
{
// Open the configuration file and retrieve
// the connectionStrings section.
System.Configuration.Configuration config = ConfigurationManager.
OpenExeConfiguration(exeConfigName);
AppSettingsSection section =
config.GetSection("appSettings")
as AppSettingsSection;
EncryptConfigSection(config, section);
return section;
}
internal static ConnectionStringsSection GetEncryptedConnectionStringsSection(string exeConfigName)
{
// Open the configuration file and retrieve
// the connectionStrings section.
System.Configuration.Configuration config = ConfigurationManager.
OpenExeConfiguration(exeConfigName);
ConnectionStringsSection section =
config.GetSection("connectionStrings")
as ConnectionStringsSection;
EncryptConfigSection(config, section);
return section;
}
internal static void EncryptConfigSection(System.Configuration.Configuration config, ConfigurationSection section)
{
//Ensure config sections are always encrypted
if (!section.SectionInformation.IsProtected)
{
// Encrypt the section.
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
// Save the current configuration.
config.Save();
}
}
}

Why no AppSettings in my ConfigurationManager?

I don't know why but i don't have AppSettings in my app.config.file.
If i add it, when i run my apps, appSetting is deleted, so i'm unable to read my data !
Here is my file :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<add key="RepertoireEntree" value="E:\DEV\Autres\DevAgréga\Input\*.txt"/>
<add key="RepertoireSortie" value="E:\DEV\Autres\DevAgréga\Output\"/>
</configuration>
And in c# :
string RepertoireEntree = ConfigurationManager.AppSettings["RepertoireEntree"];
You have your app settings in a appSettings element, else it won't be recognized:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="RepertoireEntree" value="E:\DEV\Autres\DevAgréga\Input\*.txt"/>
<add key="RepertoireSortie" value="E:\DEV\Autres\DevAgréga\Output\"/>
</appSettings>
</configuration>
By the way, it is easier to use settings the usual way. You can do this by creating a settings file from your Project Settings > Settings tab.
Visual Studio will generate the XML elements in the app.config for you and you can reference your property like this:
string re = Properties.Settings.Default.RepertoireEntree;
You do not have your xml correct in the app.config file.
note the start and end tags for appSettings
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="RepertoireEntree" value="E:\DEV\Autres\DevAgréga\Input\*.txt"/>
<add key="RepertoireSortie" value="E:\DEV\Autres\DevAgréga\Output\"/>
</appSettings>
</configuration>
PS
While this is probably not an issue for you (but moreso for future readers)
Make sure you have this reference:
Namespace: System.Configuration
Assembly: System.Configuration (in System.Configuration.dll)
as noted on MSDN

Dynamically add and remove key-value pairs from a section in app.config

My XML file looks like:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="databaseTypes" type="System.Configuration.NameValueSectionHandler" />
<section name="dataDictionary" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<databaseTypes>
<add key="ExampleServerPrefix_T" value="Connection_String_For_ExampleServer" />
<add key="ExampleServer2Prefix_T" value="Connection_String_For_ExampleServer_2" />
<add key="COPYLIVE_" value="ODBC;DSN=s2;" />
</databaseTypes>
<dataDictionary>
<!-- Other pairs in this section -->
</dataDictionary>
</configuration>
What I am trying to achieve is to be able to add and remove key-value pairs from the databaseTypes section. So for example to would like to dynamically add a run time a new pair <add key="blah" value="ODBC;blah" />.
First its useful to know is this possible? If so how because I can't find any relevant documentation or examples on how this is done.
Ben,
Here are two articles that will help you with adding key/value pairs to the config:
Writing custom sections to app.config
Writing custom sections into app.config
Update AppSettings and custom configuration sections in App.config at runtime
http://yizeng.me/2013/08/31/update-appsettings-and-custom-configuration-sections-in-appconfig-at-runtime/

Edit App.Config name-value pairs from a separate tool

I am trying to create a simple tool for a service person to update a few entries in the App.Config of a different program. The App.Config file contains custom parameters used upon initialization of our program.
Since the App.Config contains many sensitive items a tool is needed to ensure only certain parameters are changed. Thus, the reason not to allow them to edit the App.Config directly.
My questions:
How can I access the name-value pairs from the config sections of an App.config from a separate program?
Which is better suited for the UI: Winforms or WPF? Are their controls that make it easy to add more entries in the future?
The tool should allow the user to set either a String, int, double or Boolean.
Here is the structure of the App.Config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="Settings">
<section name="Section1" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section2" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section3" type="System.Configuration.NameValueSectionHandler"/>
<section name="Section4" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>
<Settings>
<Section1>
<add key="NAME_STRING" value="Some String"/>
</Section1>
<Section2>
<add key="NAME_INTEGER" value="10"/>
</Section2>
<Section3>
<add key="NAME_DOUBLE" value="10.5"/>
</Section3>
<Section4>
<add key="NAME_BOOLEAN" value="true"/>
</Section4>
</Settings>
... Omitted ...
</configuration>
In the program which uses the App.Config itself, I can easily change the values like so:
NameValueCollection nvc = (NameValueCollection)ConfigurationManager.GetSection("Settings/Section1");
Is there a similar way to do this from a separate program after loading the App.Config?
An answer to Question 1: An app.config file is an XML file. It might be easiest to load it as an XML document and modify that programmatically, followed by a save, than to use System.Configuration classes.
ETA: I believe it can be done with ConfigurationManager. Look at the OpenMappedExeConfiguration method. There's a good example there.
You could treat the app.config file as a normal XML file. Use either XDocument or XmlDocument to load the file.
Then use XPath or Linq to XML to find the name-value pairs.
As for Windows.Forms vs. WPF, its a design decision. Both have good and bad points.
[Update]
If you still want to use System.Configuration, you can use the ConfigurationManager.OpenExeConfiguration to get access to the other program's app.config file. This returns a Configuration object, which has a GetSection method.

dll Configuration file (dllName.dll.config)

I am developing a plugin for a .NET 4 application and I want to add a config file to the dll as I dont want to put the configuration in the main config file.
I have added the app.config t the project and it is correctly compile and dllName.dll.config generated.
Here is my configuration file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="MyTabsConfig" type="NewApp.UI.MyTabsConfigHandler, NewApp.UI" />
</configSections>
<MyTabsConfig>
<MyTabs>
<MyTab Name="First" Leads="2" />
<MyTab Name="Second" Leads="4" />
<MyTab Name="Third" Leads="1" />
</MyTabs>
</MyTabsConfig>
</configuration>
Now I have 1 problems:
If I copy the file in the ExtraPlugins directory of my main application, NewApp.UI.dll cannot be found when calling GetSection("MyTabsConfig"). I think it is looking in the main application folder.
Thanks.
Have you tried something like this?
ConfigurationSection section = ConfigurationManager.OpenExeConfiguration("myConfig.config").GetSection("mySection");

Categories