views:

656

answers:

5

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.

+1  A: 

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;
}
Scott Dorman
A: 

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.

Chris Marasti-Georg
+1  A: 

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.

Harper Shelby
That will only work if it's a Windows Forms application. It also returns the path for the executable file that started the application, including the executable name so you need to strip off just the path portion.
Scott Dorman
I made the assumption that this was a .NET application due to the mention of Environment.CurrentDirectory.
Harper Shelby
.NET != WinForms
Chris Marasti-Georg
A .NET application doesn't necessarily mean it's a WinForms application. You can write .NET applications that are command line applications, which won't have access to the Application class.
Scott Dorman
Wouldn't this also break down in ASP.NET?
Chris Marasti-Georg
Chris, yes I believe it would for the same reasons. The Application class is part of the System.Windows.Forms assembly, which isn't available to ASP.NET applications either.
Scott Dorman
Thanks for the information. I contemplated deleting this, but I think the comments might be instructional as well.
Harper Shelby
OpenFileDialog was mentioned, so this is obviously a WinForms app.
Jacob
A: 

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
Sire
A: 

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.

Ngu Soon Hui