30 April 2010

Using Assembly.CodeBase to get the location if shadow copied

A long time I had problems with NUnit tests that needed to access files living relative to the tested dll. NUnit (and Resharper) are shadow copying a dll before running the test, so the Location property of an assembly returns the path to the shadow folder and not the original location where the expected file lives. My solution was to disable shadow copying in NUnit and Resharper. But every now and then I forgot to disable it in new projects. The result was spending time with debugging until I remembered to disable shadow copying.
But now I have found by chance a much better solution, which is more robust and also useful for other shadow copying scenarios like hosting WCF services in IIS. You can use the assemblies CodeBase property to get the original location. The only drawback is that the codebase is formatted as a Uri. It normally includes a file protocol “file:///”  and uses slashes ‘/’ instead of backslashes ‘\’, so you need to modify the returned string a bit:
var assembly = Assembly.GetExecutingAssembly();
var path = assembly.CodeBase.Replace("file:///", "").Replace("/", "\\");
I believe that in certain scenarios you may see other protocols (perhaps http://) but for unit testing scenarios that relieves from the pain of remembering to disable shadow copying.