4

I have C# code that is trying to get the LocalPath for a executing assembly using the following line of code:

Uri uri = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;

This piece of code performs fine for all the variety of paths. It started to fail giving the right AbsolutePath and Localpath because the executing assembly path contained a # in it.

Assembly.GetExecutingAssembly().CodeBase gives "C:\c#\ExcelAddin1.1.0\GSRExcelPlugin\bin\Debug\Common.dll"

But new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath gives "C:\c" while it should have given "C:\c#\ExcelAddin1.1.0\GSRExcelPlugin\bin\Debug\".

Is there something that I need to handle or is there something wrong the way Uri class is used?

If this is a .net framework issue, how should I report this issue to Microsoft?

Linger
  • 14,942
  • 23
  • 52
  • 79

3 Answers3

7
System.IO.FileInfo logger = new System.IO.FileInfo(Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath), "settings.config"));

Using EscapedCodeBase instead of CodeBase solves the problem. I dint realize that this was already handled until I stumbled on it.:)

user_v
  • 9,628
  • 4
  • 40
  • 32
  • Damn: Does NOT work with a directory like: `Test\Space( )(#)(%20){[&],@,%}\Release` ... the %20 is not handled correctly – Martin Ba Feb 04 '15 at 09:36
  • This solution worked for me, and I have a space, a (x86) character and a # in the path. Thanks! – Fabiano Nov 08 '19 at 21:23
2

The Uri class is behaving as expected. # is not a valid part of a url. Imo this is an issue with CodeBase property. It returns a string unescaping special characters rendering it pretty much unreliable. Your options are:

1) Always use EscapedCodeBase property instead.

var uri = new Uri(Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath;

2) Or if you really have to deal with CodeBase property (if that is the only option), get the escaped part yourself.

var x = new Uri(Assembly.GetExecutingAssembly().CodeBase);
var uri = x.LocalPath + Uri.UnescapeDataString(x.Fragment).Replace('/', '\\');

3) For file location of the loaded assembly, the easiest is to use Location property.

var uri = Assembly.GetExecutingAssembly().Location;

The issue has been reported several times, but MS insists that is how CodeBase is designed here, here, here and here.

nawfal
  • 70,104
  • 56
  • 326
  • 368
  • At least `Uri` is consistent with itself. If I do `new Uri(new Uri("C:\\"), "#%23")`, I get `file:///C:/%23%2523` out (meaning it treats the interpolated path as a file path instead of a URI-style path). – binki Aug 23 '18 at 21:09
1

I assume The URI functions are stripping away everything after the sharp # because it thinks its an anchor.

URI are designed for identifying resources on the internet, so your # character would be an illegal character in the middle of any URI.

Take even this question for example, the Title is

System.Uri fails to give correct AbsolutePath and LocalPath if the Path contains “#”

but the end of the URL has the "#" stripped away

system-uri-fails-to-give-correct-absolutepath-and-localpath-if-the-path-contains

Why do you need to convert it into a URI anyway. The only difference between these 3 console.writelines is the fact that the first two are prefixed with File:///

Console.WriteLine(Assembly.GetExecutingAssembly().CodeBase);  // 1
Uri uri = new Uri(Assembly.GetExecutingAssembly().CodeBase);
Console.WriteLine(uri);                                       // 2
Console.WriteLine(uri.LocalPath);                             // 3
Community
  • 1
  • 1
Eoin Campbell
  • 43,500
  • 17
  • 101
  • 157