OpenMappedExeConfiguration vs. OpenExeConfiguration - c#

OpenExeConfiguration has 2 overloads:
ConfigurationManager.OpenExeConfiguration (ConfigurationUserLevel) ----- (1)
ConfigurationManager.OpenExeConfiguration (String) ----- (2)
OpenMappedExeConfiguration has only 1 prototype:
OpenMappedExeConfiguration (ExeConfigurationFileMap fileMap,ConfigurationUserLevel userLevel) ----- (3)
It seems both (2) and (3) can be used to open a specific config file rather than the default app.config file.
So what's the difference between them? When to use which?
Why do we seperate the UserLevel and Config File Location in (1) and (2), but combine them in (3)?
Thanks for any replies.
Update
I know that Microsoft always like to do things in more than one ways. But it should do it for a reason. Any body know the reason in my question? Do we need a bounty ;) ?

The difference is explained in the ultimate .NET config resource - Cracking the Mysteries of .NET 2.0 Configuration:
OpenExeConfiguration (String)
will append ".config" to the filename
you provide and load that
configuration file. It's important to
note that OpenExeConfiguration(string
exePath) is a very misleading method,
as the filename does not have to be
the filename of the .exe that is
running [...]
By providing a filename other than the
EXE filename, an alternate *.config
file can be opened.
OpenExeConfiguration (ConfigurationUserLevel)
The second method,
OpenExeConfiguration(ConfigurationUserLevel
level) will load the appropriate
configuration file for the specified
configuration level. Configuration
levels, available in the Exe context,
allow you to specify whether you want
exe, roaming user, or local user
configuration [...] Remember that configuration is hierarchical and merged. When requesting roaming or local user configuration, that level up through machine.config are merged, resulting in the complete configuration accessible by your application for the given user level.
OpenMappedExeConfiguration(), OpenMappedMachineConfiguration()
Unlike the OpenExeConfiguration()
methods, which make several
assumptions about where your
configuration files reside,
OpenMappedExeConfiguration() and
OpenMappedMachineConfiguration() allow
you to explicitly specify where your
*.config files reside on disk. Using these methods, you can load an
alternate machine.config, load
User.config files from the locations
of your own choosing (vs. letting the
.NET framework decide on some
convoluted path), etc. When accessing
machine.config, a custom version is
not required,
OpenMachineConfiguration() should be
used instead.

The difference between OpenExeConfiguration (String) & OpenMappedExeConfiguration (ExeConfigurationFileMap, ConfigurationUserLevel) ) is that the mapped version will let you choose the configuration file that you wish to open using an ExeConfigurationFileMap.
If you use the OpenExeConfiguration(string) overload then it will open the configuration using the Machine and Exe config locations whereas the mapped version will let you pick the specific file you wish to load from any location (obviously still respecting permissions, etc.).
If you take a look at the source, both methods actually call the same implementation method:
public static System.Configuration.Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel)
{
return OpenExeConfigurationImpl(fileMap, false, userLevel, null);
}
public static System.Configuration.Configuration OpenExeConfiguration(string exePath)
{
return OpenExeConfigurationImpl(null, false, ConfigurationUserLevel.None, exePath);
}
So when to use one over the other? Use OpenMappedExeConfiguration when you don't want to open the default configuration file. In my experience, the only time I call either of these methods is when I want to read a non-default configuration so I've only used OpenMappedExeConfiguration.

Related

What is the difference between appsettings.json and runtimeconfig.json?

What is purpose of either of that files?
When to use appsettings.json?
When to use runtimeconfig.json?
appsettings.json is for configuring your application. You (or your IDE) create this file. You manually maintain it with changes that you need.
runtimeconfig.json is an internal configuration for the .NET runtime, used when it needs to run your application. Generally, you don't touch, edit, maintain or even version control this file. It's created automatically when your application is built.
It's never an either/or situation: you generally use both. appsettings.json is used explicitly/manually, while runtimeconfig.json is generally used under the hood and very rarely used manually.
The appsettings. json file is an application configuration file used to store configuration settings such as database connections strings etc. This is basically a configuration file for configuring your application. You can able to edit it manually, whenever the changes are required.
The runtimeconfig. json file is generated automatically in the output directory when the application is built . It is basically a internal configuration for the .Net Runtime. There is no need of making any changes or any edit in this file manually as it is automatically generated at your application's Runtime.

How can my commonLib.dll use the referencing applications app.config?

Ok so i have 2 classes so far that i want to put in my common dll, logger and db. im moving them from my current project to a new class library project and changing their namespaces and whatnot. The issue I am having is that I wish to use the app config of my application (or any app that I want to reference my commonlib.dll) but I dont know how to use the referencing projects app.config. Is there any way to do this?
The OpenExeConfiguration() methods of ConfigurationManager are your ticket. One of them will take a path to the executable, allowing you to open the app config of a specified application (even a different one; you can use this technique to change the configuration of another application before launching it with Process.Start()). The other one will open the app.config of the current application (even if your library is used by multiple apps) for a specified user level (All users, current roaming user, and current roaming and local user). Usually, when dealing with an actual app.config, you want the one that applies to all users; the per-user configs are stored in each user's AppData folders.
Also, one last thing; unless your library has its own config file, the ConfigurationManager properties, like AppSettings, will be populated based on the current executable's app.config. So it could be as simple as using those properties. Keep in mind that those properties are read-only and only loaded once at program startup, so if you make changes to your config during program execution that you want to be effective immediately, it's better to explicitly load/save config files.

Dynamically generate app configuration as part of CI

We have many environments and thinking of creating dynamic application configuration as part of CI. The configuration values will be stored in Database using WPF. Operation team manages the app for new app config entries.
The problem I am facing is how can I dynamically create the config and validate it? Opinions..? Thanks in advance.
If the number of configurations is finite and known (test, UAT, production desktop, production mobile, etc), you can take advantage of the configSource attribute found on the AppSettings, ConnectionStrings and ConfigSection elements. Here's the basic premise; create an AppSettings.xyz.config file for each configuration, where xyz is the name of the configuration ("local" "test", "uat", "prod", etc). Create a single app.config file that uses a <!ENTITY config "xyz"> definition, and has configSource attributes for various sections set similar to:
<appsettings configSource="appSettings.&config.config">
Now, in deployment logic, you change one thing; the string literal defined by the entity. This change is simple enough that you don't even really need XML parsing to make the change; just slurp the file into memory with a FileStream, find the entity definition, make the change and spit the new content back out into the file. If you're using an installer, you can control which child configs are installed, or just put them all out there for simplicity.
Take a look at T4. You can create a skeleton .config file with certain variables that are filled from the database to generate the environment-specific file.

Application Wide Settings Available to All Projects

I have a Solution with 3 projects in, each project needs access to certain settings. I'm looking for a way to have these setting values available to any project from 1 distinct source. I cant use the .Config file as that is relevent to that particular project.
I could use the database but have been told this is not good practice (Without an reason)
Any ideas?
You could do this:
create a solution.config in your solution folder
in each project's app.config, add this to your <appSettings> node:
<appSettings file="solution.config">
....
</appSettings>
You would have to put symbolic links to your common solution.config in each project folder - but you could have one single physical file that you share amongst the projects.
The <appSettings> node is the only one that allows that sort of "cummulative" settings - those from the file specified in the file= will be added to your app settings, but potentially overwritten by anything you specify explicitly in your app.config.
On the other hand, yes, of course, you could use the database. We do that, too, in most of our projects, since we typically do have access to the database, but not to the file system in the client's server machines. I don't see why that should necessarily be a bad thing - we have settings for DEV, TEST and PROD in a table - so you have all your settings in one place - and we pick those settings we need when we need them. Works just fine - of course, some settings like the connection strings to the database cannot be stored there - but the bulk of our config info is. Again: I really don't see any reason why this should be a bad choice per se - so unless your source can back his/her statement up with some facts and reasons, I'd ignore it.
You can define configSource attribute in a defined configSection, to reference an external file from which to load your properties.
Here you can find an example:
Is there any way for an App.config file to reference another full config file? (.NET)
You can also use a DB of course, but that would probably involve developing some kind of configuration console, since it's not a good practice to manage config attributes directly into DB.
Otherwise you can create your config file (an xml, or yaml for example) and create your own shared config parser.
I create a class to hold system-wide settings using either a Singleton pattern, or a Global instance (whichever you preference is).
If another project is in the solution, it can see the class (when references are added).
This also decouples the presentation of the settings from the storage mechanism (database, config file, custom XML file, whatever), and if you design to the interface, it makes unit testing more flexible, too.
You could add an entry into each projects .config file that points to the global one. You would need to read that in three places though.
Another solution that springs to mind is to put your common settings into their own assembly with it's own .config file. You then include that assembly in each of your projects. The .config file is read in the assembly and you can read out those values you need.
What kinds of settings?
You can use the system wide machine.config and web.config files for settings that apply across an entire machine.
\Windows\Microsoft.NET\Framework[64]\[version]\config\machine.config
\Windows\Microsoft.NET\Framework[64]\[version]\config\web.config
You could use the registry if you have access to it. Then all you would need is a class to read them out (and possiblty one to put them in) and each project could use that class to read them.
The major downside though is that you would have to add the settings to each machines registry that you run your solution on.

Multiple Applications, Shared Settings: Use the registry or XML-based configuration?

My Scenario
I have a class library that is going to be called from multiple separate executable applications. This class library needs to know about an address of a database server (and many other configuration options, auth info, etc) to access. I have a configuration and administration application, separate from the class library, that also needs to know and set these configuration options.
My Question
Is it be common practice to store these user specific configuration options in the Windows registry, or is it preferred to use the typical 'App.config' XML approach for the class library and allow the configuration tool to change and modify it?
I am leaning toward the registry approach, but I know many people have opinions about not using it. What would you do?
The best practice is to use XML configuration files in the user's %appdata% directory.
There are a number of reasons for this:
Your application is most likely to be installed into Program Files. If the user hasn't granted (or been granted) administrative rights to your application's process, you won't be able to write to the file.
I've worked in partially trusted environments where registry access is just simply not an option. The client had completely disabled registry permissions to the .NET Runtime on that server.
Your user should always have access to their own %appdata% directory. Here's a sample:
string configFilePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "myAppConfig.config";
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = configFilePath;
Configuration cfg = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
cfg.AppSettings.Settings.Add("mySetting", "myValue!");
cfg.Save(ConfigurationSaveMode.Modified);
// to read the setting back
string mySetting = cfg.AppSettings.Settings["mySetting"].Value;
// at this point, mySetting = "myValue!"
Remember to add the System.Configuration v2.0.0.0 reference to your project! The default System.Configuration namespace does not have all of the required classes.
I prefer xml configs over registry settings because I can simply make a class and use the xmlSerializer to open and save right into my classes.
Check this topic out for a similar SO question.
In my specific case, these specific config settings made more sense to be stored in the registry. I can't be positive that our users will install the applications to the same locations, and at the very least, I'd have to store the location of the "master" config XML file in the registry so the other applications could locate it.
I simply whipped up a class with an index to read/write configuration settings to the registry like a Hashtable (string ponySetting = myRegistryObject["DefaultPonySetting"]) and called it a day. I reference the main assembly with this class in all the other applications anyways. Huzzah
I wouldn't use the registry for sure but for simple application-wide settings I just roll my own XML file in the same location as the EXE and use my own classes to access it. For this sort of thing the setting handling in .NET is way overcomplicated, and it's not even as bad now as it used to be.

Categories