Quick one. Given any .Net app I want to know the root path of the application i.e. the top level directory. I was doing this with .Net Core but it puts in extra directories by default in the exe path i.e.
bin\Debug\netcoreapp2.0\my.dll
so my normal kuldgy methods weren’t working. This all works for any .Net app not just Core in fairness – it’s just that the extra stuffed in by .Net Core threw me a little. There are all kinds of ways to find this for particular applications web, windows etc.. but this should work generally. Well it worked with my little console app anyway.
The Code
Use reflection to targeting the executable and get the path
var rootDir = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
this will get you
file:///c:/development/MyApp/bin/Debug/netcoreapp2.0/myApp.dll
which is the UNC path. Combine with Path.GetDirectoryName i.e.
var rootDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.
GetExecutingAssembly().CodeBase);
this gets
file:\c:\development\MyApp\bin\Debug\netcoreapp2.0
which is a file path now and it has got us the directory of the executable. It’s still not where we want to be so use some regex
(?<!fil)[A-Za-z]:\\+[\S\s]*?(?=\\+bin)
This will chop up the path and gives you
c:\development\MyApp
which is correct.
The Function
So overall a useful function for this could be
public string GetApplicationRoot()
{
var exePath = Path.GetDirectoryName(System.Reflection
.Assembly.GetExecutingAssembly().CodeBase);
Regex appPathMatcher=new Regex(@"(?<!fil)[A-Za-z]:\\+[\S\s]*?(?=\\+bin)");
var appRoot = appPathMatcher.Match(exePath).Value;
return appRoot;
}
Which does what we need or I quite like it as a (much abused) extension method
public static string ToApplicationPath(this string fileName)
{
var exePath = Path.GetDirectoryName(System.Reflection
.Assembly.GetExecutingAssembly().CodeBase);
Regex appPathMatcher=new Regex(@"(?<!fil)[A-Za-z]:\\+[\S\s]*?(?=\\+bin)");
var appRoot = appPathMatcher.Match(exePath).Value;
return Path.Combine(appRoot, fileName);
}
Which can be called like
“TargetFile.cs”.ToApplicationPath()
Which gives
c:\development\MyApp\TargetFile.cs
Job done.
The Regex
Not everyone likes Regex*. But for the aficionados here is what it is doing
(?<!fil)[A-Za-z]:\\+[\S\s]*?(?=\\+bin)
For example matching this
file:\c:\development\MyApp\bin\Debug\netcoreapp2.0
[A-Za-z]:\\+[\S\s]*?
Is my match – this will match a drive and a path up to
(?=\\+bin)
It’s a lookahead (zero length assertion). It will check for “bin” but not include it in the match
(?<!fil)
It’s a negative lookbehind (zero length assertion again). It will make sure that the letters fil don’t immediately proceed the match. This is to stop e:// being the match i.e. the e from file.
Clearly this assumes that the bin folder is directly under the root path as it normal is. If it isn’t in your app then break out your favourite Regex editor and write your own. It will make a man/woman/scared child of you.
(* Hardly anyone likes it – well I haven’t met many)
Useful Links
https://stackoverflow.com/questions/837488/how-can-i-get-the-applications-path-in-a-net-console-application
Full disclosure – the first bit of this is from this SO question. The extension I did with my very own coding fingers
http://regexstorm.net/tester
Regex storm – C# regex tester. Very good. JavaScript based testers don’t work with this as they can’t do negative lookbehinds.
https://www.regular-expressions.info/lookaround.html
Look ahead, behind and all around with zero length assertions