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( "/", "\\" ); }
Na dotnetomaniaku ktoś napisał:
OdpowiedzUsuń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