Merging XML Config File w/ .exe - c#

I've developed a program that utilizes Settings within my C# program. When I build the program, a separate XML Config file is created, that contains the settings of the program.
I've been able to merge other files, like the .dll's and manifest file I use for the program, into the executable. I've tried the suggested solution of putting it as a resource, but I get an error saying that it can't find the file. Secondly, the user of the program can change the settings, and I think that the Settings being implemented within the Resources isn't the best way to go. I've also set the Build Action to Embedded Resource and it still creates a separate XML Config file. How could I also merge the XML Config file with the executable?

Encrypting sections of the config file is pretty easy. There are a couple providers. The simple code for this can be seen here. I usually use it to encrypt connection strings.
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var section = config.GetSection("connectionStrings");
section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
config.Save(ConfigurationSaveMode.Full);
Note: this code only takes effect at runtime. Every build will remove the encryption and once you release it and run it as expected (outside the debugger) it will encrypt it.
Link to MSN page

Related

Why wont my application read my DataAccessLayer.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.config. 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 DataAccessLayer.dll.config. My program runs fine and is able to use the default connection string.
Next I tried to edit the DataAccessLayer.dll.config file to change the connection string. I ran my program again, but it continued to use the default value.
This project is a class library that use to a Web project and sometimes the connection string can changes.
Builds will output config files named after the dll however those aren't actually what's read on app start up. You could put the setting in the web apps config (example here Equivalent to 'app.config' for a library (DLL)), those are the settings you'll actually be running with in this case.
If you want your library to be portable you'll have to either; 1) make your own config class/file 2) Read your dll's app config manually (example in the answer I linked to above) or 3) Put your setting in the importing projects app.config
In this case I would just put your connection string data in the web apps config. If DataAccessLayer.dll is only for internal use, this is in my experience the most common pattern, and doesn't really have many cons. Ultimately I would have these values set during my build or by a deploy utility like Salt or Chef. If you're manually editing the web apps config on or after deploy then you're doing it wrong.

How to set the app.config file for the current assembly in C#?

I have integrated a dll with a service(exe). The dll has its own app.config file. But the code inside the dll for any Key/Value reference, it always refers to the exe's config file instead of the dll's config file. How the make the dll's config file as current to be used only when referred from inside the dll's code?
A DLL (or library file) cannot have its own config file. It will ALWAYS use the "hosting" applications configuration files.
The whole point of a DLL is that is can be used by many different applications and does not have configuration itself. Instead its "host" will contain the configuration information, so this is "by design".
When your solution contains more than one project, you can add app.config in any of the project; but when you compile the code to generate final output, you get only one configuration file named <exeFileName>.exe.config . This is the only configuration file that will be read by the WinForms framework when the application is running.
If your DLLs (Assemblies in .NET) specify their own configuration file, those config files will not become a part of the final output (the respective assemblies).
To include the settings from the project specific config files, you will have to make those configuration entries (appSettings, connectionString, etc) into the main application's configuration file.
The DLLs can also read from the configuration file of the main application. Hence, when you make those entries in the <exeFileName>.exe.config file, all the DLLs, that are loaded can read values from the file.
Note: Take care of using unique names for the keys for each DLL as the configuration values are read using the keys.

Common app.config for multiple applications

I have several C# console applications, which need to have the same set of settings. I want to avoid duplicity and avoid separate app.config for each application.
Is there any way to read a common app.config file (say common.config) for applications (app1.exe, app2.exe).
Create one file called app.config. Put it in some place outside of your projects' directories, like up in the solution directory. Add it to your projects as a linked item with a relative path to the file. Set the right build action for this item (application configuration) in each project.
Now when each project builds, the file will be copied to the project's output dir with the right name.
You can load an external app.config using the code below:
config = ConfigurationManager.OpenExeConfiguration(Path.Combine("C:\test\root", "Master.exe"));
string logpath = config.AppSettings.Settings["Log.Path"].Value;
And save settings as so:
config = ConfigurationManager.OpenExeConfiguration(Path.Combine("C:\test\root", "Master.exe"));
config.AppSettings.Settings["Log.Path"].Value = "C:\newpath";
config.Save();
You might have to have a master config within one of the applications and point the rest to this. Typically this method is considered bad practice though. There might be issues with different applications locking the file.
#Ran's answer is an option, but each application will still have its own config file after you build. At compile time they will be the same, but at deploy time they are copies.
You can also open one application's config file from another application using:
ConfigurationManager.OpenExeConfiguration(string)
You can have an external config file that all applications reference using:
ConfigurationManager.OpenMappedExeConfiguration
And there's the option to using the Machine config file using:
ConfigurationManager.OpenMachineConfiguration()

Is it possible to access the app.config file when an exe is used as a dll?

I have a command line application that reads some settings from the app.config file, using the usual Properties.Settings.blabla properties.
This application is also used as a dll.
When I use it as a dll, it ignores any foo.exe.config that I drop in the directory. It doesn't throw an exception as I expected when using the methods that access the config file, but it doesn't take the config file either.
Is there a way to have an exe that is being used as a dll consume its own settings file, and still have it use the app.config file when used an an exe? I don't want to change neither the consumer code, and I want as little impact as possible on the exe code.
I've seen solutions using ConfigurationManager.OpenMappedExeConfiguration Method or OpenExeConfiguration, is the solution using those methods inside the exe code? That way it will always look for the config file, regardless of if it is being used as dll or exe?
If you want to do that, you'll need to read specifically from that file. A .NET executable reads from it's own app.config file. Library code always reads from the app.config file for the application being executed... even library code that just happens to have been compiled into a file with an .exe extension.
Edit for Emphasis/Clarification
When I speak of an app.config, I am of course talking about the appropriately-renamed [program.exe.config] file.

Can a Console Application reference its .exe.config if the .config is in another folder?

Here is the task I have been given at work. We have a Web Application for which I created a Console Application that can be executed by the Scheduled Tasks on a daily basis. The task I have be presented with is to discover if we can place the ConApp.exe and the ConApp.exe.config in two different directories (folders) in our application. We would like to place the .exe file in the bin folder with all the .dll's and place the .exe.config file in a central configurations folder. I have been looking around in the properties and such with in Visual Studio and I do not see any options that will allow me to specify to the ConApp.exe the location of the ConApp.exe.config.
Is there a way to place these two files in separate folders or do they need to be in the same folder and have the .exe.confing reference a central .config file?
Thanks, :)
You should be able to use ConfigurationManager.OpenExeConfiguration to do that. You can add a setting in the console application's config file that points out the path and filename to the config file, and pass that value to OpenExeConfiguration (granted that the console runs as an account that has read access to the location where the config file is stored).
Note that if your console app contains statements like ConfigurationManager.AppSettings["somekey"], these will need some rewriting so that they use the Configuration object returned by the OpenExeConfiguration method.
The automatic discovery of the .exe.config works only if the files are in the same folder. But you gave the answer yourself IMHO: have the .exe.config reference another .config file in the desired central location.
No, you cannot tell your app to look in another directory for its main app.config.
What you can do is externalize certain configuration sections to external files in another directory:
<configuration>
<appSettings configSource="config\appSettings.config" />
<connectionStrings configSource="config\connections.config" />
</configuration>
This works - even though in the Visual Studio designer there will be complaints about this - on any .NET configuration section (but not on section groups, e.g. you cannot externalize the entire <system.web> or <system.serviceModel> at once - you need to do it by their sub-elements.
So with help from Fredrik Mork I was able to figure out this solution. First of all when you create your Console Applications, DO NOT, create any setting in the projects properties window. This will create an app.config file in your project which I believe the executable will try to look for and crash if it doesn't find it. When you first create the Console Application and then Build it before writing any code. Visual Studio create the Debug folder with just the executable file and a few supporting files. I then placed this code in the "main" function:
Dim fileMap As ExeConfigurationFileMap = New ExeConfigurationFileMap()
fileMap.ExeConfigFilename = "....../AppName.config"
Dim externalConfig As Configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None)
Dim appS As AppSettingsSection = externalConfig.Sections("appSettings")
Dim reportURL As String = appS.Settings("URL").Value
Console.Writeline(reportURL)
In the 2nd line "fileMap.ExeConfigFilename = "....../AppName.exe.config" then "......" represent the full pathname to the config file and AppName is the name of your file. Now I also tried to copy the code from my original Console Application and run it but it still crashed. I think it is due to the .dlls that I am using which make calls to Stored Procedures on the database. I believe these dlls are looking for the .config file to be in the same folder since that is the way they were built. However, if you are careful when you begin writing your application you can utilize Web.config information like I did above.

Categories