When building I got some errors & warnings. One of these warnings was:
Could not resolve assembly "System.Web". The assembly is not in the currently targeted framework ".NETFramework,Version=v4.0,Profile=Client". Please remove references to assemblies not in the targeted framework or consider retargeting your project.
I went googling about the different target frameworks and I found a page explaining the this: http://msdn.microsoft.com/en-us/library/cc656912.aspx. Basicly there are some parts "missing" by default if the target is ".NET Framework 4 Client Profile".
OK, fair enough, I changed the target framework to ".NET Framework 4" instead of ".NET Framework 4 Client Profile" on the log4net project.
Finally, I can build my solution! I was dissapointed again when I tried to run it. Now I get the following error in log4net.Core.DefaultRepositorySelector.CreateRepository():
Exception has been thrown by the target of an invocation.
The inner exception was more detailed:
Inheritance security rules violated while overriding member: 'log4net.Util.ReadOnlyPropertiesDictionary.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)'. Security accessibility of the overriding method must match the security accessibility of the method being overriden.
It states that something is wrong with the overriden method GetObjectData() in the ReadOnlyPropertiesDictionary class. ReadOnlyPropertiesDictionary implements ISerializable which makes you have to implement GetObjectData(). When you look at the definition of ISerializable.GetObjectData() you'll see there is an SecurityCritical attribute specified on it. With the inner exception in mind, I added the SecurityCritical attribute to the method GetObjectData() in ReadOnlyPropertiesDictionary. To be honest, the people in this thread pointed me in the good direction: http://stackoverflow.com/questions/2903669/log4net-and-net-framework-4-0.
Having changed that I ran it again. Now other errors arised, however Visual Studio did not break on it, it was written to the VS output window and my console app. One of the errors was the same as above, but then for log4net.Core.LoggingEvent.GetObjectData(). So I added the attribute SecurityCritical there too.
Still no luck with that, because now this error was thrown:
System.MethodAccessException: Attempt by security transparent method 'log4net.Util.SystemInfo.get_CurrentThreadId()' to call native code through method 'System.AppDomain.GetCurrentThreadId()' failed. Methods must be security critical or security safe-critical to call native code.
The property CurrentThreadId of the class log4net.Util.SystemInfo calls System.AppDomain.GetCurrentThreadId(). However, it seems that this is obsolete and need to be changed to System.Threading.Thread.CurrentThread.ManagedThreadId. See http://msdn.microsoft.com/en-us/library/system.appdomain.getcurrentthreadid.aspx.
Changed the property, run it, get an error. Do you have the impression we are in a vicious circle? Don't worry, so do I, but we are getting out of it!
This time the error is:
System.MethodAccessException: Attempt by security transparent method 'log4net.Appender.ColoredConsoleAppender.ActivateOptions()' to call native code through method 'log4net.Appender.ColoredConsoleAppender.GetConsoleOutputCP()' failed. Methods must be security critical or security safe-critical to call native code.
Some security changes were made in the .NET 4.0 framework. In the AssemblyInfo.cs file of the log4net project, you'll find the following line:
This is affected by the security changes. Take a look at this page for more details: http://msdn.microsoft.com/en-us/library/system.security.allowpartiallytrustedcallersattribute.aspx.
I commented that line and now I can succesfully run my application with the logging capabilities of log4net! Isn't that great?
Because the AllowPartiallyTrustedCallers is in comment, the SecurityCritical attributes we added can be removed again.
As a summary, this is what you'll need to do to make log4net run on .NET framework 4:
- Include the source as a project
- Change log4net.Util.SystemInfo.CurrentThreadId to return System.Threading.Thread.CurrentThread.ManagedThreadId instead of System.AppDomain.GetCurrentThreadId().
- Put [assembly: System.Security.AllowPartiallyTrustedCallers] in comment in the AssemblyInfo.cs file.