S h o r t S t o r i e s

// Tales from software development

Assembly Location and CodeBase

with 2 comments

I’ve just found out the hard way why I should have been using Assembly.CodeBase rather than Assembly.Location.

When I need to find a file or assembly that’s in the same folder as the assembly that’s executing I generally use Assembly.GetExecutingAssembly().Location, e.g.

string logPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "application.log");


Most of the time this works fine but it’s relying on the false assumption that the location the currently executing assembly was loaded from is the same location where your other files and assemblies are. There are some scenarios where this isn’t the case. For example, depending on how it’s configured, NUnit may copy the assembly being tested to a temporary folder but set its CodeBase to the original folder so that referenced assemblies are successfully located. As an example of this, while debugging an NUnit test a couple of days ago I found that the assembly being tested had a CodeBase of

file:///C:/svn/HL7/trunk/Solutions/HL7/Tests/bin/Release/Vitality.HL7.Processor.Tests.EXE


but its Location was

C:\Documents and Settings\SeaMonkey\Local Settings\Temp\nunit20\ShadowCopyCache\5312_634473125209531250\Tests\assembly\dl3\2aaca1d6\6a30ec8c_d24bcc01\Vitality.HL7.Processor.Tests.EXE


In this scenario, using Location to locate a file that I knew was in the same folder as the assembly fails because NUnit has copied the assembly somewhere else before executing it. However, the CodeBase property provides the information I need. The only problem is that it’s a URI rather than a file system path but creating a Uri instance and referencing its LocalPath property provides a simple means to convert the URI to a file system path:

Uri codeBase = new Uri(Assembly.GetExecutingAssembly().CodeBase);
string logPath = Path.Combine(Path.GetDirectoryName(codeBase.LocalPath), "application.log");


Advertisements

Written by Sea Monkey

August 3, 2011 at 8:00 pm

Posted in Development

Tagged with ,

2 Responses

Subscribe to comments with RSS.

  1. Works a treat to fix Appveyor ShadowCopyCache problem. Thanks.

    Anonymous

    November 12, 2015 at 5:22 pm

  2. Unfortunately this is NOT a simple means to convert a URI to a file system path. It is FULL of problems because neither “Assembly.GetExecutingAssembly().CodeBase” nor “Assembly.GetExecutingAssembly().EscapedCodeBase” are properly escaped (which they would need to be to feed into “new Uri()”. This results in many valid (but perhaps a bit unconventional) Windows file paths being malformed. Just a couple of examples would be paths with “%” signs, “#” signs, or spaces. For the ultimate example, try feeding the following totally valid Windows file path into “new Uri()”:

    C:\Test\Space( )(h#)(p%20){[a&],t@,p%,+}.,\Release

    The following StackOverflow url is where most of this information came from (specifically user ‘Martin Ba’):

    https://stackoverflow.com/questions/4107625/how-can-i-convert-assembly-codebase-into-a-filesystem-path-in-c

    Martin Ba does offer a solution (basically just chopping the “file:///” off the front of the result of CodeBase), but even that solution seems like it will have problems (UNC paths for example). Unfortunately, there just doesn’t appear to be any pretty solutions to this problem, short of ugly, error-prone manual parsing.

    lahma

    January 25, 2018 at 4:30 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: