Convert Uri to local path

היי,

מדי פעם אנחנו מעוניינים לגלות היכן Assembly הטעון באפליקציה שלנו ממוקם על הכונן הקשיח של המחשב עליו רצה האפליקציה.

לשם כך, ניתן לגשת לProperty ששמו CodeBase:

1
2
3
4
Assembly givenAssembly = typeof(int).Assembly;
string assemblyPath = givenAssembly.CodeBase;
// file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll

זה נותן לנו כמעט את מה שאנחנו רוצים.
מה הבעיה? שאנחנו מקבלים את התוצאה כUri עם הקידומית file:// והרבה סלאשים (/) במקום בק סלאשים (\).

זה עלול ליצור בעיה במידה ואנחנו מעוניינים בהמשך לגשת דרך האפליקציה שלנו לקובץ פיזית ולבצע עליו דברים.

הפתרון המתבקש:

1
2
3
4
5
6
Assembly givenAssembly = typeof(int).Assembly;
Uri assemblyUri = new Uri(givenAssembly.CodeBase);
string assemblyPath = assemblyUri.LocalPath;
// C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll

נראה טוב.

מסתבר שזה לא מספיק טוב: אם במקרה הDLL נמצא בתיקייה עם התו המיוחד #, נקבל תוצאה לא רצויה.

1
2
3
4
5
6
7
Assembly givenAssembly = typeof(Program).Assembly;
Uri assemblyUri = new Uri(givenAssembly.CodeBase);
// file:///C:/C# For Fun/Tip/Tips/bin/Debug/Tips.exe
string assemblyPath = assemblyUri.LocalPath;
// C:\C

מה קורה כאן? הUri מתייחס ל# בתור חלק מפריד של הUri ולכן לא מכניס את כל מה שנמצא שהחל ממקום זה לLocal path.

איך ניתן להתגבר על הבעיה? הפתרון המוצע מStackOverflow (תודות לג’ייסון פיין):

1
2
3
4
5
6
7
8
9
10
public static string ConvertUriToLocalPath(string uri)
{
Uri uriObject = new Uri(Assembly.GetExecutingAssembly().CodeBase);
return uriObject.LocalPath + Uri.UnescapeDataString(uriObject.Fragment).Replace('/', '\\');
}
Assembly givenAssembly = typeof(Program).Assembly;
string assemblyPath = ConvertUriToLocalPath(givenAssembly.CodeBase);
// C:\C# For Fun\Tip\Tips\bin\Debug\Tips.exe

קצת מכוער, אבל עובד 😃

יום טוב מקומית

שתף