While using a third party dll I was getting the following exception:
exePath must be specified when not running inside a stand alone exe
with the following trace
System.Configuration.ConfigurationManager.OpenExeConfigurationImpl(ConfigurationFileMap fileMap, Boolean isMachine, ConfigurationUserLevel userLevel, String exePath).
The reason I found was that it was looking for app.config and I had provided the details in web.config. My question is: why does the system.configuration differentiate between web.config and app.config? Any thoughts?
Executables:
Several .NET executables can live in the same directory. As there cannot be two files with the same name in the same directory, the applications must use different names for their main configuration files. The applicationName.exe.config scheme solves this.
Web applications / sites:
.NET web applications are compiled to DLLs, and web sites are usually compiled just-in-time. Hence, there is no "main entry point" in these types of projects. It is possible to create a web project where each page is compiled to its own assembly. Which one is the main assembly? Which assembly should we name the configuration file after?
Fortunately, only one web project can be hosted from a single directory, so only one main configuration file is going to live here. This allows for the main configuration file name to be picked by convention, and that file name happens to be web.config.
web.config is for your website and web applications only. It stays fixed, i.e. doesn't change its name; it's always called web.config.
app.config is for non-web applications - Winforms, WPF, NT Services etc. This will be renamed into YourApplicationName.exe.config when you build your project. You won't ever find an app.config by that name in an application's directory (or if you do, it will not be used).
Why Microsoft choose to use two different kind of names - I don't know - ask Microsoft.
So you basically just have to know what you're dealing with and provide the information in the correct place.
Related
Now I have seen this question before on SO in a variant ways, but surprisingly not in this form:
I have a solution with multiple web services (projects) that need to talk to each other. After publishing each of these web services might end up on a different machine with a different database. To tell each web service where all other web services are, I want to maintain a single config file during development.
I would like to expect that after publishing the config to be present in each published project. And I would like to expect the config file to be editable after publishing, so I can swiftly migrate a certain web service and then just edit all config files of the other web services.
I don't want to do this in the database, for the config file its self should also hold connection settings to the database(s).
I came across the following ideas/thoughts/questions:
I have a dll project called 'common' that is referenced by other projects. Let's give that one a shared.config and build a class in that project that can be used to read out the shared.config by doing System.Configuration.ConfigurationManager.OpenExeConfiguration("shared.config"). Just need to make sure the shared.config will be published along with the DLL.
I would favor this solution, as it would also let me keep a web.config inside each project having just the project specific settings. And have the shared.config having the shared settings. But I read on SO that this should not be considered lightly and could have some unwanted side-effects, like file-access-issues; though I wonder if this would apply to my case. Also I would like to ask your help here on how to actually realize this as I don't think Visual Studio supports app.config for DLL projects out of the box.
I also thought about creating a shared.config file in the Solution Items. Then linking that file inside each project. And in the Web.config of each projects, add: <appSettings configSource="shared.config" /> pointing to the linked file in that project.
Though I cannot find any reason why not to do this, first implementation failed. It seems (at least during development), c# cannot find the linked shared.config file. I'm guessing linking files is not done instantly nor maintained after creating the linked file, but the file is only copied to the projects WHEN I do a publish. Thus leaving the file missing during development. Is this correct?
The config files are app specific. This mean that you can add a config file to a class library but the file will then by used by the app (windows service, webservice and so on) referencing the library.
Same thing for external configSource, this are app specific as well and need to be included withing the project using it.
So if your solution is composed by 2 projects you then need 2 config files. One for each project.
While for a windows based application(services, winforms) the expected folder for config files is the bin directory, for web based projects this will be the directory is the root folder of the virtual directory.
This said, using a shared config file looks the easier solution (and you don't have to copy the app.config from the class library for each project). Here are the steps :
Create a solution folder.
Add the config file to it.
Add the file as a reference for each project needing it. Right click the project and Add existing item - > Choose the file and Add as link
Ensure the file is always copied by setting the copy option (properties of the file) with Copy Always.
At this point you should have the config file deployed into your project directory everytime you compile the solution.
EDIT:
I'd avoid looking into the bin for config files within a web app, the
convention is that file should be in the root, so I would avoid the
first option.
Linked files end up in the bin after building the project. Try the same steps for importing the file but this time simply add it (not as link) and it will be deployed as content in the root of your site, so it can be always available.
If your hosting in IIS it is possible to have a single web.config file at the root site level but Giorgio is right in that app.config files are app specific. it is possible to use custom build steps to automate the copying of config files across multiple projects so personally I would go with that.
This actually drove me a bit crazy. In the end I fixed it like this:
Created a Shared.config file in the dll project 'common', having the contents look like any ordinary web.config/app.config.
Set the file to be Content and Copy Always, so it would surely be copied out to all projects that reference project common. (Though the config file will indeed end up in the bin folder.
Created the class SharedConfiguration inside the common project. The really tricky part was having to use OpenMappedExeConfiguration() , and getting the path to the executable directory (including bin, and without file:// in front of it).
Now when I want to access a setting from the shared settings, I do SharedConfiguration.instance.AppSettings.Settings["CubilisEntryPointUrl"].Value.
(I cannot use SharedConfiguration.instance.AppSettings["CubilisEntryPointUrl"] directly because of this issue)
.
public static class SharedConfiguration
{
public static readonly Configuration instance = GetConfiguration("Shared.config");
private static Configuration GetConfiguration(string configFileName)
{
ExeConfigurationFileMap exeConfigurationFileMap = new ExeConfigurationFileMap();
Uri uri = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
exeConfigurationFileMap.ExeConfigFilename = Path.Combine(uri.LocalPath, configFileName);
return ConfigurationManager.OpenMappedExeConfiguration(exeConfigurationFileMap, ConfigurationUserLevel.None);
}
}
I am writing a wpf application (EF, dot net 4, wix 3.6). It compiles fine. I can debug the app and everything works. I can run the produced executable and everything works. I try to package it up with Wix which successfully produces an .msi file, which copies the executable to the right place. When I run the msi-deployed .exe I get the error above.
I've checked out the questions here: The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid, and here: The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid. The second link isn't the solution as that deals with web.config and I'm in a windows desktop environment.
The first solution talks about multiple projects and the EF project's config needing duplication in the other projects. In my case the only two projects are the Main Application (which includes the EF stuff) and the Wix installer project.
In any event, I copied the App.config to the Wix project, but that didn't make any difference. I had a lot of trouble getting the wix stuff going, but I think it's right now, however that might be a pointer to the solution.
Can anyone help?
OK, as Gert Arnold correctly pointed out, the config file had not been copied to the application directory, so the connection strings couldn't be found. The config file created is named MyAppName.exe.config, and contains stuff from the App.config file created in VS and other bits (like EF config details).
(Something must be different between the settings for the VS2010 installer and the Wix installer as the .msi deployment has never involved a .config file before.)
In any event, adding the .exe.config file to the Product.wxs file as a component contained within the main application feature solved the problem.
Newb notes:
If you copy and paste the component tag, remember to set KeyPath="no".
The path to
the files being deployed is relative to the location of the .wxs file
I have a VC2010 C# Solution, with a number of projects in it.
So for example, I have a web project, and I have a class library.
In the web.config file, I have a key in the <appSettings> section, e.g.
<add key="FileDirectory" value="G:\ftproot\sales" />
I have also added a key in the Web.Production.config file to reflect the file directory on the server.
So when I reference it in my web project (It's MVC) - I do so like this:
var FTPPath = ConfigurationManager.AppSettings["FileDirectory"];
this works fine within my web project. However, I also need to reference this in the class library, which gets to my question - Is there a way to reference a key in the web.config file from another project, e.g. a class library, in the same solution??
All help is appreciated.
Thanks
Yes you can use exactly the same code. .Net will look up the configuration key in the config file of the application which started the app domain. A class library used by such an application will have access to it's config file.
class libraries do not have their own configuration. They use the configuration of which ever executable they are being used in.
This means that for you you should be able to use the same code, and it will read the setting from the config (assuming that it is there).
This is not always convenient though (for example if you write a .net based plugin for a MMC snap-in, as this means you have to modify the mmc.exe.config in the system folder.)
You might be better having a method to pass this required configuration setting into you library code. then in apps where you control the config you can just read it from there and pass it in, and in apps where you can't you can use another approach, like reading from the registry or from a manually read config file. Or have the best of both worlds and make it so you can pass it in, and if this is not done it attempts to read it from the default configuration.
This question has some more details on the pitfalls associated with dll configuration, but also has some techniques for doing it if you need to.
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.
I have a config file in my C# class library called MyLibrary.config, in vs 2008.
I created another project, say a simple console app, add reference by "Browsing" the MyLibrary.dll in the bin directory of the class library project, and when I compile, the MyLibrary.config is not including in the bin directory of the output in the console app.
How can I set it so I can include it when I reference the dll?
Cheers
You can't. Your console application is expecting to find a config file with prefix the same as the name as the console application (MyConsoleApplication.exe -> MyConsoleApplication.exe.config.).
In some situations you can share a config file by using the file attribute on the appSettings element:
<appSettings
file="path">
</appSettings>
Note that path is relative to the executing assembly.
As a side note, DLLs do not even use the config file that you've defined in the project. Again, configuration information is read from the a config file with prefix the same as the executing assembly. Thus, even when MyLibrary.dll tries to yank configuration information out of a config file, it will be reading the config file for the executing assembly, not MyLibrary.dll.config.
For more on how config files work, see MSDN.
The standard way to use a config file is to have it the same as the executable, adding a reference to a dll will not include its config file and as far as I know dll's don't load config files on their own, rather they rely on the executable that reference them.
Beyond not being able to do this, I would also advise against this approach.
Rather than trying to tighly couple your settings to the DLL library, consider more of a "Dependency Injection" type approach - i.e. where you pass in the value dependencies (i.e. settings) to the code you are calling (i.e. the library).
The advantage in this is you are not tied to a single method of storing settings. You can then use a database, different config file formats... even hard-coding. It also makes unit testing easier by removing the external file dependency.
There are different ways to implement this, however one example is to pass the configuration settings into the constructor of the class(s) that uses them.