Using app.config correctly - c#

In several C# projects I have been using an app.config file to pass various settings to my program, settings like connectionstrings, power levels etc.
However sometimes I have come in situations where the settings aren't updated as expected and I have concluded that I am not that well informed with the proper use of app.config file.
Example:
Replacing the .exe file with a new version (where settings are different) to the output directory without changing the exe.config, results in the program seeing the hard-coded settings and not the settings of the existing .exe.config
So my Questions are:
What is the exact role of exe.manifest file
Every time I create a new .exe do I have to paste in the output folder anything else except the .exe file?
Whats the difference in obtaining the setting value by: ConfigurationManager.'settingName'... rather than:
Properties.Settings.Default.'settingName'?
What is the role of app.config build action?
Sorry If I am asking too much in a single Question.

The app.config file is a file that gets a special treatment when running the associated application. If you executable is named MyApp.exe the app.config file should be named MyApp.exe.config. The role of the app.config build task is to copy the file named app.config in your project to MyApp.exe.config in the output directory.
.NET provides ways to read the contents of the file (it is in XML format) and various parts of .NET will look for different sections in this XML to provide configuration.
A widely used section is the settings section you refer to as Properties.Settings.Default. This section plays together with Visual Studio that provides an editor for application settings. The settings are accessed in the code by using a generated class. Adding a setting will add a property to this class and this property is initialized from a value in the app.config file.
In the Visual Studio editor you can set a value for the setting and you can think of this as a default value for the setting. However, if you overwrite the value in the app.config file the later will take precedence. This allows you to modify the app.config file after installation and rerun the application with a modified setting.
You can also access application settings the app.config file using other methods, but in my oppinion using the Visual Studio editor and the code generated class is the best way to do that.
I am not sure I fully understand the problem that you experience. If you update MyApp.exe and leave MyApp.exe.config intact you should not see a change in the settings used by the application (unless of course you have renamed or changed some settings).
The manifest file provides information about side-by-side assemblies and can be used to request elevated privileges among other things. This is not related to the app.config file.

There quite a few resources about that.
See http://msdn.microsoft.com/en-us/library/ms229689%28v=vs.90%29.aspx
and the (better) overview: http://msdn.microsoft.com/en-us/library/k4s6c3a0%28v=vs.110%29.aspx
app.config is a very powerful tool. It addresses many issue like versioning, migration, upgrading etc. but this requires some in-depth reading from the links above.

Maybe one thing you could do, if you want to copy only .exe file every time you build your app, is make a settings.ini or settings.txt file, put your parameters in this file (that are not secret of course) and read all your settings from there when you start your app.
You can put all your connection string logic in your login form if you have one...

Related

Modifying App.config in Program Files directory

Kind of a two part issue.
I developed an app which reads from and writes to an App.config.
The application is installed in Program Files by my MSI installer.
It works fine on my Win7 computer but I have users on Win7 that get Access Denied when writing to this App.config.
I am writing to the app.config using the below code:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["Endpoint"].Value = endpointTxtBox.Text;
config.Save(ConfigurationSaveMode.Modified);
Why don't I get this issue on my development pc? I have tried both with a local admin and normal local user account.
How do I relocate the App.config to an unprotected directory?
Cathal,
You should not have to move the app.config in order to let your users save their application settings; .NET already has support for saving user-scoped app settings in user-writable storage baked in! You can even specify the default user settings in the app.config file.
Check this link for details:
http://msdn.microsoft.com/en-us/library/8eyb2ct1(v=vs.110).aspx
Note that making use of a strongly-typed .NET Settings class rather than the raw, more weakly-typed AppSettings NameValueCollection. (The settings can still stored in the app.config, though.)
You can create a Settings file in VS (the template is called "Settings file" in VS).
A couple of things confused me about Settings files at first, so I thought I would point them out to you:
1) First: the .settings file. The VS designer lets you define your app settings, their types, and their scopes (i.e. user or application). This is the file the designer modifies when you user the designer, but runtime configuration changes will never be written to this file. It defines your app settings and their default values. That's it. I didn't get that at first when I was trying to wrap my head around Settings files.
Also, notice that the build action on the .settings file is set to SettingsSingleFileGenerator.
2) The .designer.cs file. VS/MSBuild generates this file at build-time for you because the build action on the .settings file is set to SettingsSingleFileGenerator. The class that it generates is a strongly typed wrapper for your configuration properties, and you can use it equally well for your application-scoped and user-scoped properties.
3) The runtime settings that your Settings class wraps are still stored in the app.config.
4) User settings are stored underneath that user's AppData\Local directory so that they have full read/write permissions.
I had a couple of other ideas, if what you need to do really is let the user modify the global application settings for all users.
Externalize some of your configuration by using the configSource attribute. You store the entire
appSettings section, for instance, in a separate file by doing this:
<appSettings configSource="....\file.config" />
Here are the docs for that feature: http://msdn.microsoft.com/en-us/library/ms228154(v=vs.85).aspx
I believe you can manually load a config file anywhere you want using the System.Configuration.ConfigXmlDocument class. Construct one using the no-arg constructor and then call its Load(String filename) method.
Store your configuration in the registry rather than the filesystem by implementing a custom SettingsProvider.

Persisting application variables/settings C#

In my application I would like to persist a variable for configuration as part of the the project (I could do it with an accompanying file but that would be evil), so that a change can be made while the application is running and saved such that it can be closed and re-opened and keeping the same value.
What is the recommended or best practice approach to this in a Visual Studio 2010 C# project?
Use App.config or Web.config.
Example: here
Which is the recommended best approach.
You could also save your settings in the Database (if you're using one) and load them at runtime, if you don't want to use "an accompanying file" (although having said that it is still an accompanying file). However you'd have to hard code the connection string to your DB which might be troublesome if the connection string is changed.
Also note that connection strings are usually saved in the .Config file under the tag <connectionStrings></connectionStrings>
Make use of .Config file for saving setting. Developers can use configuration files to change settings without recompiling applications.
Configuration files contain elements, which are logical data structures that set configuration information. Within a configuration file, you use tags to mark the beginning and end of an element.
Configuration Files
and
Configuration Settings File for providing application configuration data

.NET .config HELL

I have the following projects:
MVC
Console application
Class library
Windows forms application
COM Library
All these applications need to use a single configuration file. As far as I understand, app.config files are for windows, console applications and class libraries when web.config are for the web projects.
The same configuration need to be accessible in all of these projects. I have read that it's suggested to use machine configuration file, but we won't always have access to that, therefore configuration files must reside within our solution.
I don't fully understand how the configuration files get build. Currently I wrote a simple project where I have the following:
Class library to store for serving configuration files. A have attempted to do this through reflection.
Windows application that should read the app.config from a class library.
When I execute the following code I expect to get a configuration file with test values:
_applicationSettings = ConfigurationManager.OpenExeConfiguration(
System.Reflection.Assembly.GetAssembly(typeof(WCSConfiguration)).Location
).AppSettings;
What I get instead is an empty application settings file.
Class library has the following App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="TestTextKey" value="TestTextValue"/>
</appSettings>
</configuration>
I have tried using .GetExecutingAssembly() method which I expect to return an assembly of a code that's currently being executed. This didn't work, instead it has returned the assembly of a Windows application.
GetAssembly(type(WCSConfiguration)) has returned a right assembly, however, the configuration file was missing in the bin/debug directory.
I have a feeling that either I'm doing something fundamentally wrong or Microsoft hasn't made this flexible enough. I have also tried to search MSDN for explanation, but this hasn't been documented well IMO.
I have also left COM in bold because I'm not sure whether any config files would be available to COM library at all. Firstly I would like to get other projects to work.
I understand that this is a lot of information. Any help would be greately appreciated. Previously we have chosen to use registry, but this has turned out to be nasty, mainly because access to registry is not available in some scenarios. Additionally we now have multiple versions of the applications and switching between branches is a half an hour job :(
Thank you
Edit:
If I add the dll's config sections to app.config that means that these settings will be available only from that application. Please correct me if I'm wrong. Example that I have provided is a scaled down version. In total there are about ten windows applications, a single MVC project and range of class libraries all of which need to make a use of that configuration.
Configuration settings are mostly connection strings, lookup values that do not belong in the database and few other minor settings. Main concern at this point are the connection strings. There are few minor releases of the application where each release points to a different database.
What I'd like to get out of this is a good workable solution so that it can be posted online and other people who come across the same problem won't spend days of their time.
Morale of the story IMO:
Use both App.config and Web.config to store location of your own configuration file.
Write simple XML serializer to read/write config and DLL for serving the configuration.
COM objects are a long story and were implemented with a "hack", since neither App.config or Web.config are available in COM DLLs.
Note ConfigurationManager.OpenExeConfiguration needs to be passed the filename of the config file, not the executable.
You'll need to append .config to the path of the executable. To get the exe assembly use Assembly.GetEntryAssembly.
If you have configuration settings you want to share across multiple pieces of code that are not all in the same .NET Process, I would suggest:
Put them in their own myStuff.config.
In .NET code use ConfigurationManager.OpenExeConfiguration to open and access myStuff.config.
Non-.NET code will need to use an XML parser to load and read the settings. Unless you configuration structures are very complex this shouldn't be too hard to encapsulate.
Put the path to myStuff.config in the app.config of each application sharing this configuration for .NET applications. (Not non-.NET applications: depends on what works for that application.)
Another approach, where the configuration structure is the same but the settings are per-application would be a custom configuration section.
A couple of general points -- add the dll's config sections to the app.config file rather than relying on the dll's config file to get picked up; and app.config actually gets renamed to .exe.config on build, so you need to make sure a file of that name's available.
Also -- you're not constrained to using the default config loading mechanism to configure your application. You could create your own configuration classes and just use XML serialization to deserialize and configure at will.

Why wont my application read my MyApplication.dll.config file?

I'm trying to use application settings with a C#.NET project I am working on. But I can't seem to get it to return anything other then the default values. Through the project properties I've added a single setting, DBConnectionString, and set its value to a connection string I want to use. Its scope is set to "application".
Doing this created a number of files including Settings.settings, Settings.Designer.CS, and app.conifg. From what I understand the two Settings.* files define a custom Settings class that derives from ApplicationSettingsBase. The Settings class then has custom, type safe, properties that can be used to set and retrieve each setting. The app.config file is a XML file that stores the actual settings values.
When I build my project it looks like the app.config file is copied to the target directory as MyApplication.dll.config. My program runs fine and is able to use the default connection string.
Next I tried to edit the MyApplicaiton.dll.config file to change the connection string. I ran my program again, but it continued to use the default value. I noticed that in my Settings.Designer file there is a DefaultSettingValueAttribute with the original default string. I tried removing this attribute, but then when I tried to retrieve the connection string setting it just returned null.
This is the code I'm using to read the connection string.
string conn = Properties.Settings.Default.DbConnectionString
What am I doing wrong? How can I get it to return the value in the settings file and not the default value?
Update:
Sorry I should have mentioned this. I'm actually writing a plug-in for another application through a public API. So my project is a DLL not an EXE.
You cannot read settings from *.dll.config files. If you library needs any special settings you need to put them in your app.config or web.config files.
EDIT: You can include the external config files in the main application or web config file. Look here for details.
This question discusses how to manage configuration files for large projects.
Settings files and .config files are different things (I do not know why VS automatically added a .config when you created a Settings file). But, the settings file is compiled into a class and is referenced like you said. If you decompile the dll with .NET reflector the Settings class will be in there. It is used for holding constant values or external resources. For example: error message strings, icons, or images.
The config file is for settings which can change frequently or between environments (dev, test, prod). For a connection string you should use the <connectionStrings> section of the config file. And the property can be referenced using System.Configuration.ConfigurationManager[ "connectionStringName" ].
However, from your original post it looks like your .dll is going to be used in a larger project (either an .exe of web project). One thing to note is that all projects only use one .config file. And that is the config file for the main project. Websites the web.config file, and exe's use XXX.XXX.XXX.exe.config (as you saw, *.exe.config files are renamed copies of the app.config files). dll's do not have usable config files. All dll's will look at the main project's .config file to retrieve information.
If your connection string is never going to change then by all means use the Settings file. Otherwise, use a config file and let the developer of the main project determine what to populate the connection string with.

C# Settings xml file location

I have a project that reads in a file based on a value in a C# Setting class. This value however changes from machine to machine and Id rather not ask the user the first time the program is run as its a corporate environment, instead Id like it to be set in the installer, but where is the file located? Is there an easier method?
This is a visual studio addin not a standalone program
From your post it appears you have a windows application? , you can store an initial value in the application config, you can make an installer in Visual Studio and write custom actions that can write values to the file on first install in you install project.
The configure file is the easiest way to do what you are asking, however it is NOT the best. In fact it is recommended Not to use .config files for such cases.
whenever users install an 'update', there is a risk of overwriting their existing changes.
some businesses might have policy restrictions on the .config files.
the user cannot easily move his settings from one PC to another.
From my own experience, using XML, MS-Access, Registry or text files to store user settings has proven more useful than using the .config files.
I believe you are talking about designer-generated settings (the .settings file)?
The exact path usually contains some sort of a Hash (check this link). I usually have my own settings class which I serialize to and from xml using XmlSerializer, which gives me more freedom (I think C# settings files don't allow you to add custom enums, for example, or they make it a bit harder to do it than simply adding them to the .settings file).
However, maybe there is no need to set values during installation? For example, you could add a FirstStartup setting (set to true initially), which you can read when your App is started for the first time, and then set it to false. That way you can set your default settings when you detect a "first startup".
You will certainly need some sort of custom action at the end of your installer. You haven't mentioned what technology you're using to deploy your application so I will refrain from giving any specific guidance.
I recommend setting the value in your App.config. This is an xml file which will be named MyApplication.exe.config in the same directory as your application. Add it to your installer if it is not there already. In your installer, add a new setting:
<configuration>
<appSettings>
<add key="MySetting" value="My Value"/>
</appSettings>
</configuration>
In your code, retrieve the setting:
String setting = ConfigurationSettings.AppSettings["MySetting"];
If this is a machine-wide setting, this installer is the right place to set this. If you do it on the first execution you will run into a host of problems with permissions on the files and directories if the first person to run the app is a user with limited permissions.
Registry or an INI file or a XML file whatever suits you best.
Best option would be registry. Istalling the application will require Admin access so writing to the registry during installation will not be an issue.
More over if some one accidently deletes the ini or settings file then the program might stop working.
You said that this is for a corporate environment. You can create an administrative template for group policy to set the default in the registry. Then, your program can just query that one registry value if the default hasn't already been set.
I personally would never use web.config or app.config. Just read your own xml file, have a look at my post on this:
http://www.picnet.com.au/blogs/Guido/post/2009/09/10/XML-Settings-Files-No-more-webconfig.aspx
Thanks
Guido
To answer the "Where is the file located" bit of the original question for those interested (I'm assuming that the "settings file" in question is the "Settings File" item available from the "Add New Item" dialogue).
In Win7 (and probably all the other ones) the settings file will generate under the path:
C:\Users\[user]\AppData\Local
The folder structure from here on out depends on your AssemblyInfo and build information, the "AssemblyCompany" field (if populated) is used for the top-most folder, beneath this is a folder copying the application executable name, followed by the build and then finally the settings file (named "*.config").
In my case, the complete path is as follows:
C:\Users\[user]\AppData\Local\[company_name]\Application.exe_StrongName_zx0v1qxyoass4d0z3mtwe3vbrhaehkjg\0.0.5812.21662\user.config
My case is different, my project is a class library (dll) which have the app.config file. I decided to create 4 application settings variables (title, url, limit, rate). To create this, i right-click ont he project --> Properties --> Settings. this values you can retrieve in code using this command --> Settings.Default.title, ...etc
the problem is let say i instantiate 5 objects (same object for example MyProject.MyClass) from this library, i want the instance be able to have its own settings. i mean each of the instance may have their xml setting file. can this be done?

Categories

Resources