I ran into an interesting issue yesterday while adding log4net to a project that was using NDoc as part of its build process. The project is using Team System for both source control and builds, and is using NDoc 2 Alpha 3 to generate code documentation files as part of the build. A common tools folder exists as part of the source control tree that is copied to the build server during the build process and used as a reference point for common libraries throughout the solution. This approach has been successful for me in the past because it means that the hint paths for references can point to a common known location and avoid common path issues to referenced libraries. However, shortly after checking in the log4net library to the tools folder and referencing it from several projects, I received the following build failure notification:
It appeared that the log4net library was locked and was causing NDoc to fail. After a little investigation, I found that the log4net dll was marked as read-only (because it had been added to source control) and experimented to see if that was part of the problem. Sure enough, on my local machine, if I changed the file to not be read-only then NDoc would build the documentation successfully. However, this didn’t solve the problem for the build process as the files on the build server are purged and freshly checked out prior to each build. The read-only log4net.dll would be copied down to the build server upon each build with the read-only flag set and the build would fail. The first, and more distasteful solution, was to add a build step prior to generating documentation to modify the attributes of the file to ensure that it was not read-only. However, more investigation led me to learn about the NDoc shadow cache. I found the information on Kiwidude’s blog here.
It turns out that NDoc is copying the referenced libraries to a separate shadow cache before interrogating them to build the documentation. This is to avoid, of all things, access permission problems that might arise from NDoc attempting to read a locked file. However, when NDoc goes to delete this shadow cache, it fails to note that some of the copied files might be read-only; the case with our log4net.dll. The System.UnauthorizedAccessException is being generated when NDoc tries to delete the read-only file from the shadow cache. Thanks to Kiwidude’s blog, I was now aware of an option to disable the shadow cache and force NDoc to simply read the files in place. Opening up the NDoc GUI, I loaded our .ndoc project and immediately saw the UseAssemblyShadowCache option:
This actually manifests itself in the project file as the following:
After changing this option, NDoc was able to compile the documentation without error and checking in the change fixed the build. I am presuming that the beta version of NDoc 2.0 will check the attributes on files that were copied to the shadow-cache to avoid this kind of problem, but for now this fixes it.