How to find path of active app.config file? - c#

I'm trying to finish this exception handler:
if (ConfigurationManager.ConnectionStrings["ConnectionString"]==null)
{
string pathOfActiveConfigFile = ...?
throw new ConfigurationErrorsException(
"You either forgot to set the connection string, or " +
"you're using a unit test framework that looks for "+
"the config file in strange places, update this file : "
+ pathOfActiveConfigFile);
}
This problem seems to only happen to me when I'm using nUnit.

Try this
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile

Strictly speaking, there is no single configuration file. Excluding ASP.NET1 there can be three configuration files using the inbuilt (System.Configuration) support. In addition to the machine config: app.exe.config, user roaming, and user local.
To get the "global" configuration (exe.config):
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
.FilePath
Use different ConfigurationUserLevel values for per-use roaming and non-roaming configuration files.
1 Which has a completely different model where the content of a child folders (IIS-virtual or file system) web.config can (depending on the setting) add to or override the parent's web.config.

If you mean you are only getting a null return when you use NUnit, then you probably need to copy the ConnectionString value the your app.config of your application to the app.config of your test library.
When it is run by the test loader, the test assembly is loaded at runtime and will look in its own app.config (renamed to testAssembly.dll.config at compile time) rather then your applications config file.
To get the location of the assembly you're running, try
System.Reflection.Assembly.GetExecutingAssembly().Location

Make sure you click the properties on the file and set it to "copy always" or it will not be in the Debug\ folder with your happy lil dll's to configure where it needs to be and add more cowbell

The first time I realized that the Unit testing project referenced the app.config in that project rather then the app.config associated with my production code project (off course, DOH) I just added a line in the Post Build Event of the Prod project that will copy the app.config to the bin folder of the test project.
Problem solved
I haven't noticed any weird side effects so far, but I am not sure that this is the right solution, but at least it seems to work.

One more option that I saw is missing here:
const string APP_CONFIG_FILE = "APP_CONFIG_FILE";
string defaultSysConfigFilePath = (string)AppDomain.CurrentDomain.GetData(APP_CONFIG_FILE);

Depending on the location of your config file System.Reflection.Assembly.GetExecutingAssembly().Location might do what you need.

I tried one of the previous answers in a web app (actually an Azure web role running locally) and it didn't quite work. However, this similar approach did work:
var map = new ExeConfigurationFileMap { ExeConfigFilename = "MyComponent.dll.config" };
var path = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None).FilePath;
The config file turned out to be in C:\Program Files\IIS Express\MyComponent.dll.config. Interesting place for it.

Related

Change app.config at runtime - in memory - not working "Access denied"

var configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (configuration.AppSettings.Settings[key] == null)
{
configuration.AppSettings.Settings.Add(new KeyValueConfigurationElement(key, value));
}
else
{
configuration.AppSettings.Settings[key].Value = value;
}
configuration.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
I've read all stackoverflow related questions and the answers are: You can't write to app.config file at run time. Which is fine for me. But I also found accepted answers that said you can change the in-memory app.config with the above code.
But I get the same error that the file is read-only... even though this code is supposed to only change in-memory?
What am I missing?
I am using .net framework 4.7.2.
#Muhkuh,
The app.config file is only when you are working on your source code and developing/programming the application.
After you build of publish the project, the build output is written to the folder that is configured in the project properties.
All the values you specified in the file, are read once the application's executable is ran and the first time any configuration is read by the ConfigurationManager class.
So, the configuration file should be changed before the application is ran. If you want to change the configuration values, you should consider a read/write configuration provider, and store any configurations in a table in the application's database or a configuration database (This will be determined by the design of the application components).
So, changing the configuration values that are come from the actual app.config file is not a best practice and is not recommended anyway.
Regards

Where appSettings values are stored when the app is installed in program files?

I built an app that is reading / storing appSettings like this:
Dim _config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
Dim _My_Settings = _config.AppSettings.Settings
'READING
tbServerIP.Text = _My_Settings.Item("ServerIP").Value
'STORING
_My_Settings.Item("ServerIP").Value = "127.0.0.1"
_config.Save(ConfigurationSaveMode.Modified)
This worked perfectly until I created an installer and installed the app in program files. Then I got an error when reading one (newest) config key/value. The app.config file is included with the installer and configured to sit alongside the EXE file.
To be sure that that prop value is actually missing I run the following and examined the result - the prop was truly missing.
MessageBox.Show(String.Join(",", _My_Settings.AllKeys))
So I need to find where those values are stored. But, a strange thing is happening: the app is still storing all other values BUT somewhere else, because, of course, it can't save into program files.
Where appSettings values are stored when the app is installed in program files?
I just did as Mathieu suggested and searched in all folders and found it in the following location:
C:\Users\user\AppData\Local\VirtualStore\Program Files (x86)\company\app
So I deleted appSettings file (which was missing that one prop value) and started the app again. The config file got recreated with all props. Now the next question is why it didn't update when I reinstalled app several times?
OK, found a solution for that. I am actually installing appSetting in that folder too by setting Custom Folder #1 to the following path:
[LocalAppDataFolder]VirtualStore\Program Files (x86)[Manufacturer][ProductName]

ConfigurationManager.ConnectionStrings["XXX"] is returning null

I have a console application in which website project is added as dll. Inside dll ConfigurationManager.ConnectionStrings["XXX"] is called which is always returning null.
But web.config in dll has connectionstring named 'XXX'. Can any one suggest what is going wrong?
I don't think .config file of the .dll is added to your console project together with the dll. You need to have the .config in your executing project.
Try copying the config file to your console project. Or at least the connection strings section. Probably in an App.config.
I had a slightly different problem that I haven't seen an answer to. I was using.
ConfigurationManager.ConnectionStrings["XXXX"].ConnectionString;
When I opened up web.config I saw that the connection string I had created was prefixed with "WebApplicationAPI.Properties.Settings." - putting the entire string in worked for me:
ConfigurationManager.ConnectionStrings["WebApplicationAPI.Properties.Settings.XXXX"].ConnectionString;
Your config file is not in the .dll. So you're referencing nothing I would suspect! Unless you've manually copied the web.config file to the correct location or references it via an absolute path?
web.config is for web application.
For console application you have to use app.config.
Well, actually that's the default configuration for C#, I won't be surprised some advanced user could make it go the other way arround.

Better way to get the base directory?

I have this code to load a config file and read all the values and it works fine when running the application but of course fails on team city because the appdomain's base directory is where the build script (psake) is started. I know I can change directory to the build dir before executing the tests but I thought it's better to make loading the config file work at all times regardless.
XDocument.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, cfgFile));
Is there another way to get the "BaseDirectory" that really works all times? I tried the below as well with same results:
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
XDocument.Load(Path.Combine(path, cfgFile));
EDIT 1 The problem is the following. My solutions base directory is "C:\Project", all compiled files are copied to "C:\Project\build". Now in the psake build script I have the following code:
task Test -depends PrepareTests {
try {
#$old = pwd
#cd $build_dir
&$mspec $mspec_projects --teamcity
#cd $old
}
catch {
&echo "Error starting test runner"
Exit 1;
}
}
As you can see I commented out the changing of directories which makes the BaseDirectory the location of the build file / solution instead of the build directory regardless of how I try to access it. Kind of confusing if you ask me.
UPDATE I really like to know if it is possible to get the directory of the assembly regardless of what directory the application that started the app domain is located. How?
differents ways to get the base directory
AppDomain.CurrentDomain.BaseDirectory
Directory.GetCurrentDirectory() // not guaranteed to work on Mobile application
Environment.CurrentDirectory // this calls Directory.GetCurrentDirectory()
this.GetType().Assembly.Location // Assembly.location
Application.StartupPath // for windows forms apps
Application.ExecutablePath // same as Application.StartupPath
string origAssemblyLocation = Assembly.GetExecutingAssembly().CodeBase;
Per MSDN:
Assembly.CodeBase Property
Gets the location of the assembly as
specified originally
Your question is a bit unclear. I don't really know if this is what you want.
I typically use AppDomain.CurrentDomain.BaseDirectory
Alternatives
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Environment.CurrentDirectory
So it sounds/looks like you're attempting to obtain the configuration file for an assembly. The following should accomplish that task by accessing the 'Location' property of the assembly and using it to retrieve the configuration path:
static string GetConfigFileByType(Type type)
{
Configuration config =
ConfigurationManager.OpenExeConfiguration(type.Assembly.Location);
if (config.HasFile)
return config.FilePath;
throw new FileNotFoundException();
}
try this one:
Module[] modules = Assembly.GetExecutingAssembly().GetModules();
return Path.GetDirectoryName(modules[0].FullyQualifiedName);
have you tried getting the FileName of the current process' MainModule?
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
Or GetEntryAssembly()?
System.Reflection.Assembly.GetEntryAssembly().Location
I like to make my classes configurable - for example they get the folder name as a parameter in their constructor.
This makes it possible to test with different config files.
In test code we use:
TestContext.TestDeploymentDir
This is the testrun folder, where all assemblies for a test run are copied into, together with the test deployment items. We 'deploy' our unit test config files to the test run folder - this can be specified in the testrunconfig dialog in visual studio.
For our production code we pass
Assembly.GetExecutingAssembly().Location
to the constructor, which works for us.
how about:
Application.StartupPath;
string baseDirectory=Application.StartupPath.Split(Path.DirectorySeparatorChar)[0];
Application startup path will return the path where exe is kept, we will split this using "\" and get the base directory as "C:" for example,

Wrong App.config being loaded

I have a .NET 3.5 class library I built that reads an App.config file for values it needs. It can pull the config values just fine when I test it in Visual Studio. To test it, I just change the project to a console application and execute a method call.
I have the need to call this class library from many other .NET programs, and I want the class library to be self sufficient (I should be able to call it from any other program, and it should use its own config file, not know about any calling config file etc.).
I can add a reference to the dll (since I am still development I am using VS 2008, haven't thrown anything into the GAC yet) but the App.config that the class library is reading is from the calling program's App.config, not the class library's App.config.
The class library dll has it's config file in the same directory, so it should be able to find it just fine, and the calling application is named differently. I am using the standard key value pairs in the App.config (e.g. name of config file myClassLibrary.dll.config) and getting values out with the following line of code:
String myVal = ConfigurationSettings.AppSettings["myConfigSetting"];
Does anyone know how to fix this?
An app domain in C# can have only one assembly level app.config file. See here on MSDN. An executable will always start up an AppDomain and by default look for a config file with name: EXECUTABLE_NAME.config. For example, SampleApp01.exe will look for SampleApp01.exe.config as its configuration file.
you can place your configs in the machine.config file inside the framework folder by this way you can globally use your configuration in all .Net applications running in that machine,
I believe app.config will always be used by the executable. Just drop it in that directory.
They would do that to ensure the dll can be shared and not have to share the same .config file.
You might be able to create a link from the executable .config file
<appSettings configSource="\lib\app.config">
Or change its name, i don't understand how you can have both app.config files in the same directory..don't they have the same name?
<appSettings configSource="\lib.app.config">
I can't find a way to avoid getting the app.config for the calling dll/exe etc. The only way I have found is to use a hardcoded path and load it that way. Here is code I am using to do that:
using System.Configuration;
...
public static KeyValueConfigurationCollection getAppSettingsFromAppConfig(String appConfigPath) {
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = appConfigPath;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
AppSettingsSection section = config.AppSettings;
KeyValueConfigurationCollection appsettings = section.Settings;
return appsettings;
}
You then have a collection of KeyValueConfigurationElement, which you can use .Value to get the string from config file with.

Categories

Resources