Log4Net not watching for app.config file modifications - log4net

Let me start out by explaining what my goal here is. I'm trying to allow modifications to my config file to come into effect without having to restart my program/debugging. Now I've attempted to approach this in two ways, the first way was to simply add the following code at the bottom of my Assemblyinfo.cs file
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
Now the logger works as intended, however, when I modify the .config file during debugging the modifications I have made are not used.
My initial assumption was the the app.config file cannot be "watched" while the program is running for whatever reason. So, I decided to attempt to create an external config file and place the Log4Net information there. To do this I moved all of the Log4Net information out of the app.config file and moved it into the file "Log4Net.config" that I created. Then I modified the code inside Assemblyinfo.cs to be the following:
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
However, now the logger says it cannot find the config file upon startup. So, here is what I'm asking.
1) If the app.config can indeed be watched for modifications, what am I doing wrong? Why are my modifications not being noticed and implemented while the program is running?
2) If an external config file is necessary, why can the new config file I created not be found by Log4Net?
This is my first question on stackoverflow, I've looked around but couldn't find something that directly addresses my question. Thanks for the help!

If you are debugging your application with Visual Studio, you need to modify the YourApplication.vshost.exe.config file in your output folder (that is the one that is active during debugging).

Related

NLog and the include file option

Ok, this has been doing my head in all day. In my UAT setup I have the following in my web.config
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance>
<include file="d:\logs\nlog.config"/>
</nlog>
This pulls in all my rules and targets and has been working fine. That was until I published to our prod server. Same setup but it fails to find the nlog.config file.
At first I thought it was NTFS permissions, but Nlog can write to the same folder location as where this config file resides. I used the internal logging to get an idea what was happening. Nlogs internal log just says that the file doesn't exist. I can't seem to identify why the same setup works in one system but not on another. I've added all relevant NTFS permissions (triple checked) and even went as far as granting 'everyone' read rights as a test, still no joy.
I'm guessing there's something going on within IIS that is stopping the app from reading outside of the root web folder on prod? Which would be odd given it can write to the same place.
It's ok, I was being a donut, well sort of. I created a text file and named it nlog.config not realising that .txt had been stuck on the end. Now the problem makes sense! It never clicked because the .txt was hidden and showing the name as nlog.config in explorer. :o)

What is the name of the web role .config file with SDK 2.2

I have a web role in which I have extended the RoleEntryPoint to do some work that is outside of the scope of the web site. As part of the RoleEntryPoint.Run() my code is required to read from the .config using ConfigurationManager.
While this is a little unusual, using SDK 1.8 I was able to make this work by ensuring that my package included a [The name of my project].dll.config file.
Now that I have upgraded to SDK 2.2 when I try to use .AppSettings or .GetSection() the values are always null, which leads me to believe it is unable to find my file.
I have tried deploying a Worker Role and the .config file still follows the same name pattern that I'm currently using.
I have also tried naming the file WaIISHost.exe.config.
I am aware that ideally this configuration should be included in the .csfg file, but my questions is does anyone know what I should be calling my config file?
UPDATE:
With the help of this question, I now know that the name of the config file it is reading from is E:\base\x64\WaIISHost.exe.Config, but I don't know why this has changed or what I can to overide this.
After much investigation and trial an error I finally have a solution.
The name of the file is still required to be [The name of my project].dll.config, but you need to make sure that this file is in your approot\bin\ directory of your package.
I believe my initial problem was caused by the Copy to Output Directory property being changed to Do Not Copy, although I'm unsure how this happened. If you find yourself in a similar situation you can just add a file with the correct name to your project and set the Copy to Output Directory to be Copy Always.
Once I'd done that however I realised I had another problem. I needed the .config file to have had the config transformations run over it, which this didn't do. To fix this I updated the .ccproj file to have the following:
<PropertyGroup>
<!-- The first two of these targets are what is defined in the base SDK 2.2 targets file. When we upgrade we may need to look reassess this. -->
<CopyRoleFilesDependsOn>
CopyWebRoleFiles;
CopyWorkerRoleFiles;
CopyWebConfigToBin;
</CopyRoleFilesDependsOn>
</PropertyGroup>
<Target Name="CopyWebConfigToBin">
<!-- We need to copy the transformed Web.config to the bin directory so that the RoleEntryPoint has access to the config settings.-->
<Message Text="Copy %(WebRoleReferences.OutputDir)Web.config tp %(WebRoleReferences.OutputDir)\bin\BackOffice.UI.dll.config" Importance="high" />
<Copy SourceFiles="%(WebRoleReferences.OutputDir)Web.config" DestinationFiles="%(WebRoleReferences.OutputDir)bin\[Name of project].dll.config" />
</Target>
This adds an extra target which waits until all of the other files have been copied to the appropriate directory and then picks up the web.config and puts a copy in the bin directory with the correct name.
Are you able to put the config values into the Azure config file (the .cscfg) rather than using the .config file? You can read the values from the cscfg via the RoleEnvironment.GetConfigurationSettingValue static method.
This page explained why it's called WaIISHost.exe.Config and where you can put it in your project.
http://azure.microsoft.com/blog/2010/12/02/new-full-iis-capabilities-differences-from-hosted-web-core/
Like knightpfhor mentioned, you can also use [AssemblyName].dll.config to put these configuration too. It depends on the assembly name of your project, you can check property of your web role project.

Logging via FileAppender

here is an easy question coming:
i am trying to use log4net to log the infos on a file. i wrote
< file value="log-file.txt" /> into my appender tag in app.config. and now wondering where the log-file.txt is positioned and whether it is created automatically or i should create it by myself.
i am using c# - wpf
It should be in the Debug\Bin or Release\Bin folder.
if its not there, try specifying full path.
The file will automatically be created if it doesn't exist.
It may require that the application has write permission to the folder where the logfile is placed.
As Orentet mentions this is normally the bin folder.

How do I add a project to CruiseControl.NET?

I am looking at the cruisecontrol web dashboard. I can see one farm and one server. However, I don't see any way to add a project?
Is this something I can do with the UI or do I need to edit the config file by hand?
You'll need to edit the ccnet.config file by hand (located within the CruiseControl directory) to add projects. There are some graphical tools to help you do this however you do get used to doing it by hand fairly quickly - just have the documentation near by!
Update: An example of one such tool is http://www.codeplex.com/ccnetconfig
You can use CCNETConfig to edit the config file through an UI although it doesn't support higher version > CruiseControl.NET 1.4.
You have to basically edit the configuration file by hand, however I have it setup so that the raw config file is split into different include files, each of which is setup in my source control system. Then I created a project for the configuration, and then for the whole config. So when something changes in the config, CC.NET itself pulls out the changes, recreates it's config files and the refreshes the system configuration.
This means that anyone can edit the config (if they can access the files in sourcecontrol), and no-one has to go into the program files directory of the CC.NET machine itself.
Not sure whether this answers the question you asked, but this is how our setup works

Why Does CruiseControl.NET need to be restarted after GetCcNetConfigFiles?

CruiseControl.NET service needs to be restarted to pick up changes in the projects configuration files.
I find this very annoying, not sure if it's a bug or it's the way it works.
Is there any way to overcome this issue in people's experience?
If your projects are separated in a different file from ccnet.config, then you need to restart the service unless you touch the actual ccnet.config.
We use ENTITY with SYSTEM file reference in ccnet.config for our projects, so we're in the same boat. I'm happy to pay the price for easier project maintenance, as it's easy to script a restart:
net stop CCService
net start CCService
IISRESET
If you wanted to completely automate this, and had your projects under source control, then you could trigger an update and restart whenever your project files are touched.
There was a bug in CC.Net prior to 1.4.4 if you were using a pre-processor include it did not reload the configuration when an included ccnet.config file was modified.
That was a bug that I reported and it is fixed in CC.Net 1.4.4 and greater.
Also, keep in mind that if a build is running and there is a change to the configuration it will not take place until that build is in an idle state.
How are you updating your config files? By hand? Mine always recognizes and adjusts. Is your config file in source control and designed to pull it down and replace the file? This for me requires a kick. How I ended up fixing it was have my project pull it down to a seperate folder. THen I call ccnet.exe -validate on it to make sure it is well formed, then I copy it over ontop of the current config file. CC.NET recognizes the changes and loads in the new config
Exceptions: If cc.net is currently running a project, it will not recognize the changes till that project has completed.
If your ccnet.config has errors, it will not ever recognize the changes and keep running the old version it has stored in memory. (However when CC.NET does restart it will try to parse the error filled config and choke.
Hope this helps!!
Do you mean you are using linked files, that is the ccnet.config file has links to the independent project files.
If so then they are not picked up, it's mentioned in the documentation that it doesn't watch the sub-files.
Internally we have modified our CruiseControl.net so that our ccnet.config is optionally a directory - and we can drop shortcuts to our project config files into that directory. We put watches on the directory, the files or shortcuts in the directory and all of the targets of the shortcuts. That means we have our project config files in ClearCase and just drop a shortcut into the ccnet.config directory.
I've just spent half a day or so moving from 1.2 to 1.4.2 dropping our changes into the new version for our internal use. We don't own our code, our client does and so it has to stay internal :(
I have never experienced this. Whenever I change the configuration files, the CruiseControl.NET service seems to automatically re-read them.
I'm using Version 1.3 of CC.NET.
Update:
In the service's config file (ccservice.exe.config), there is a setting to enable/disable watching the ccnet.config file for changes:
<add key="WatchConfigFile" value="true"/>
Make sure this is set to true.

Resources