Question

I am working on an application where I have an images folder relative to my application root. I want to be able to specify this relative path in the Properties -> Settings designer eg. "\Images\". The issue I am running into is in cases where the Environment.CurrentDirectory gets changed via an OpenFileDialog the relative path doesn't resolve to the right location. Is there a way to specifiy in the Settings file a path that will imply to always start from the application directory as opposed to the current directory? I know I can always dynamically concatenate the application path to the front of the relative path, but I would like my Settings property to be able to resolve itself.

Was it helpful?

Solution

As far as I know, there is no built-in functionality that will allow this type of path resolution. Your best option is to dynamically determine the applications executing directory and concatenate to it your images path. You don't want to use Environment.CurrentDirectory specifically for the reasons you mention - the current directory may not always be correct for this situation.

The safest code I've found to find the executing assembly location is this:

public string ExecutingAssemblyPath()
{
   Assembly actualAssembly = Assembly.GetEntryAssembly();
   if (this.actualAssembly == null)
   {
      actualAssembly = Assembly.GetCallingAssembly();
   }
   return actualAssembly.Location;
}

OTHER TIPS

Are you looking for Application.ExecutablePath ? That should tell you where the application's executable is, remove the executable name, and then append your path to it.

2 options:

  • The code that uses the setting can resolve the setting against the directory of the current executing assembly.
  • You can create your own type that serializes as a string relative to the executing assembly, and has an accessor for the full path that will resolve against the directory of the current executing assembly.

Code sample:

string absolutePath = Settings.Default.ImagePath;
if(!Path.IsPathRooted(absolutePath))
{
    string root = Assembly.GetEntryAssembly().Location;
    root = Path.GetDirectoryName(root);
    absolutePath = Path.Combine(root, absolutePath);
}

The nice thing about this code is that it allows a fully qualified path, or a relative path, in your settings. If you need the path to be relative to a different assembly, you can change which assembly's location you use - GetExecutingAssembly() will give you the location of the assembly with the code you're running, and GetCallingAssembly() would be good if you go with option 2.

This seem to work in both WinForms and ASP.NET (gives the path to the config file):

new System.IO.FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile).Directory;

For Windows and Console applications, the obvious way is by using:

Application.StartupPath

I suggest you to use Assembly.CodeBase, as shown below:

public static string RealAssemblyFilePath()
{
   string dllPath=Assembly.GetExecutingAssembly().CodeBase.Substring(8);
   return dllPath;
}

You can try Application.ExecutablePath. But you need to make reference to System.Windows.Forms. This may not be a good idea if you want your class library to steer clear of forms and UI stuff.

You can try the Assembly.GetExecutingAssembly().Location. But if, somehow, you do a "Shadow Copy" before you run your application (like the default NUnit behavior), then this property will return you the shadow copy location, not the real, physical location.

The best way is to implement a function that calls the CodeBase property of Assembly object and chop off the irrelevant portion of the string.

I use the following two methods to help with that:

public static IEnumerable<DirectoryInfo> ParentDirs(this DirectoryInfo dir) {
    while (dir != null) {
        yield return dir;
        dir = dir.Parent;
    }
}
public static DirectoryInfo FindDataDir(string relpath, Assembly assembly) {
    return new FileInfo((assembly).Location)
        .Directory.ParentDirs()
        .Select(dir => Path.Combine(dir.FullName + @"\", relpath))
        .Where(Directory.Exists)
        .Select(path => new DirectoryInfo(path))
        .FirstOrDefault();
}

The reason to look at parent dirs to to be easier in use during development when various build scripts end up sticking things in directories like bin\x64\Release\NonsensePath\.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top