I have a Windows Service that I'm creating and I'm wondering what options are available in order for me let developers configure the service.
The service is part of an over all larger open source project and hence the service is going to be installed on lots of different machines.
Normal I would use a web/app.config for this but I'm not sure if this is possible.
Hence I am looking to so how others handle this case.
you do as you expect. You use the app.config, which will be renamed to <exeName>.configwhen the project is built and then <exeName>.config will be read by the service called <exeName>.
Settings are applied in a layered way and may come from other configuration files on the machine, such as machine.config. You can read about how configuration is handled on MSDN
EDIT
In response to comment: A service will only read the config when it starts (for perf reasons). If you want to reload the config file later, you need to handle that yourself I think.
You could read the last modified date/time of the config file to determine if the file has been changed, or setup a file system watcher and then tell the configuration manager to reload that section again next time it is read, by calling ConfigurationManager.RefreshSection("appSettings") and that section will be reloaded from disk when you next access it. See the ConfigurationManager MSDN docs
You can just use a .config file with the same name as the exe that is the service.
If your service runs as MyService.exe, it's config file would be MyService.exe.config.
In Visual Studio, just add an Application Configuration file. This will add an app.config file to the project.
You can then access things like AppSettings and ConnectionStrings using the ConfigurationManager class, just like you do with ASP.Net applications.
Related
I have an asp.net project that is using Entity Framework that is used on several different client servers. This means a different web.config for each for connectionstrings and app settings.
Hasn't been an issue but I changed something that altered the web.config file recently and I manually had to adjust this for each client, I also have to exclude the web.config file in updates to ensure their own one is not overwritten.
What I would like to achieve is store these settings in maybe another config file that the project can pick up and use. Maybe that on Globals Application_Start gets these and imports them/overwrites the current web.config file perhaps.
Essentially I don't want to affect the current code that uses the connection string and ConfigurationManager.AppSettings used throughout the project but I do want to be able to let the web.config file update for each client and use a seperate file for some settings.
NOTE: I do not have access to publish directly to each server so I can't simply write a different deploy web.config for each one. I have to publish the files locally, store as zip and automated routine on servers downloads and extracts accordingly.
EDIT:
Please do say if this is considered a bad idea but an idea I had was to put something similar in Global.asax Application_Start method:
Does config file exist?
If no, create file and append all current settings in web.config
If yes, open and import those settings to the current web.config overwriting the original values
Hopefully then in a few weeks time, after I have asked all clients to perform a manual update they will have this code and I can begin to include the web.config in updates.
In VS, inside the Build menu, the last item is Configuration Manager.
In here you can specify various different release environments which can each have their own web.config transforms.
This is normally used for production/staging/test environments. However, I can see no reason why you could not use this and have a configuration file for each of your servers/environments.
You will then need to create the transformations for each environment, by rightclicking the web.config, then selecting Add Config Transform.
each of the environments you had setup can then override the settings in the main web.config. (That now acts as a template/default settings)
e.g.
In Web.EnvironmentA.Config
<add key="ConnectionString" value="ConStringA" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
In Web.EnvironmentB.Config
<add key="ConnectionString" value="ConStringB" xdt:Transform="SetAttributes" xdt:Locator="Match(key)"/>
Then when you do a publish, you simply setup which config file to use. If you use Azure or the VS publish method, it will save each of these settings, so then you can simply push to the relevant environment easily.
Just make sure you test this works as you intent first, before you start publishing everywhere ;)
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...
We have many C# console apps that run on scheduled tasks. All of these apps have their own config file, which contain settings like our smtp server. If our smtp server ever changed, we would have to manually go into each config file and change it. Can multiple apps look at 1 config file on the C: drive, or is that considered bad practice? Using the database to store values is a no no.
You can point to external config files inside your application's configuration file like the following, and have all your applications use the same set of settings from a single file:
<appSettings file="c:\CommonSettings.config">
<add key="MyKey" value="12"/>
</appSettings>
For more information, you can read following articles:
AppSettings can Reference an External Config File
How to share custom application configuration settings across projects in .NET
It is not directly possible to share one application configuration file because the .config filename needs to match the executable name (so for example.exe it would be example.exe.config).
It makes sense to have separate values for the different applications, as they are separate applications.
If there are configuration sections that you do want to share, you can use the configSource attribute to point to a file. The appSettings section also has a specific file attribute that you can use in the same manner.
If there are certain configuration values that are shared across all applications, you can consider placing them in the machine.config file for the version of the framework you are using.
Can you use custom xml files to store configuration data ?
There's no necessity to use app.config.
Using Cinchoo framework you can achieve this, by simply creating custom configuration object and use it all the console applications. All of them will read from same configuration file. For more information, please visit http://www.cinchoo.com
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'm having trouble seeing how I can use logging in my setup / install project.
I've got Log4net working on installed applications, but I can't seem to log the install / uninstall process.
My main problem is with the logging config file.
I suppose it's a bit of a chicken/egg scenario - theres no way for me to grab the just-installed logging file?
I have a method that finds the root directory of my app, using - AppDomain.CurrentDomain.SetupInformation.ApplicationBase
and i normally use this to locate the logging config file.
This directory however, during install, is not where it is installing (obviously) it is somewhere within the windows filesystem.
Does anybody have any ideas to this?
Consider configuring log4net in code and not using a file or storing the configuration as a file resource of your custom action assembly and using XmlConfigurator.Configure(Stream configStream) overload.
Of course if you want to reuse the configuration of the application this is not a clean solution.
Also checkout this question:
log4net pure code configuration with filter in c#
When executing MSI's you are bound to msiexec's logging mechanisms (which is not as friendly as log4net).