środa, 15 lipca 2009

Assembly.CodeBase vs. Assembly.Location [PL]

Chyba każdy kto operował ścieżkami plików pod .NET zauważył, że ścieżki te mogą występować w dwóch postaciach:

  • standardowej - typu: c:\katalog\plik
  • przypominającej URL, czyli file:////c:/katalog/plik

Różnicę widać właśnie porównując właściwość CodeBase i Location klasy Assembly. Zobaczmy jaki będzie wynik poniższego kodu:

Assembly myAssembly = Assembly.GetExecutingAssembly();
Console.WriteLine("CodeBase: {0}", myAssembly.CodeBase);
Console.WriteLine("Location: {0}", myAssembly.Location);

Efekt jest następujący:

  • CodeBase: file:///D:/CodeBaseLocation/CodeBaseLocation/bin/Debug/CodeBaseLocation.EXE
  • Location: D:\CodeBaseLocation\CodeBaseLocation\bin\Debug\CodeBaseLocation.exe

Ta sprawa była już klika razy na różnych stronach omawiana (m.in. tutaj: Suzanne Cook's .NET CLR Notes : Assembly.CodeBase vs. Assembly.Location). CodeBase to URL, który wskazuje na to gdzie można odnaleźć plik, podczas gdy Location wskazuje na miejsce skąd był załadowany. Np. jeśli assembly jest popbrane z Internetu (np. jako ClickOnce) jego CodeBase może się zaczynać od "http://", ale Location może się zaczynać od "C:\". Warto również wiedzieć, że CodeBase nie musi byś ustawione dla assembly pochodzących z GAC, natomiast Location będzie zawsze ustawiona dla tych assebly, które są załadowane z dysku.

Pytanie jednak jak przejść od jednego typu ścieżki do drugiego? (pomijając fakt, że nie zawsze jest to możliwe) Niestety nie udało mi się znaleźć gotowego rozwiązania, można to co prawda zrobić w kilku linijkach (np. tak jak pokazuje kod niżej) jednak wydaje mi się to trochę mało eleganckie. A może ktoś zna lepsze rozwiązanie?

if ( FileName.StartsWith( "file://" ) )
{
FileName = ( new System.Uri( FileName ) ).AbsolutePath;
FileName = FileName.Replace( "%20", " " );
FileName = FileName.Replace( "/", "\\" );
}

1 komentarz:

  1. Na dotnetomaniaku ktoś napisał:

    Odnośnie konwersji między ścieżkami, to ja bym skorzystał z właściwości Uri.LocalPath (kod w Pythonie, tak dla urozmaicenia):

    from System import Uri, UriKind
    from System.IO import Path

    def normalize_path(path):
    if path.StartsWith('file:'):
    path = Uri(path).LocalPath
    else:
    path = Path.GetFullPath(path)
    return path

    OdpowiedzUsuń

Posty powiązane / Related posts