Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does default/relative path resolution work in .NET?

So... I used to think that when you accessed a file but specified the name without a path (CAISLog.csv in my case) that .NET would expect the file to reside at the same path as the running .exe.

This works when I'm stepping through a solution (C# .NET2.* VS2K5) but when I run the app in normal mode (Started by a Websphere MQ Trigger monitor & running in the background as a network service) instead of accessing the file at the path where the .exe is it's being looked for at C:\WINDOWS\system32. If it matters The parent task's .exe is in almost the same folder structure/path as my app

I get a matching error: "System.UnauthorizedAccessException: Access to the path 'C:\WINDOWS\system32\CAISLog.csv' is denied."

My workaround is to just fully qualify the location of my file. What I want to understand, however is "What is the .NET rule that governs how a path is resolved when only the file name is specified during IO?" I feel I'm missing some basic concept and it's bugging me bad.

edit - I'm not sure it's a.NET rule per se but Schmuli seems to be explaining the concept a little clearer. I will definitely try Rob Prouse's suggestions in the future so +1 on that too.

If anyone has some re-wording suggestions that emphasize I don't really care about finding the path to my .exe - rather just didn't understand what was going on with relative path resolution (and I may still have my terminlogy screwed up)...

like image 505
Dan Malkinski Avatar asked Nov 05 '08 20:11

Dan Malkinski


People also ask

How do you define relative path?

A relative path refers to a location that is relative to a current directory. Relative paths make use of two special symbols, a dot (.) and a double-dot (..), which translate into the current directory and the parent directory. Double dots are used for moving up in the hierarchy.

What is absolute and relative path?

An absolute path is defined as specifying the location of a file or directory from the root directory(/). In other words,we can say that an absolute path is a complete path from start of actual file system from / directory. Relative path. Relative path is defined as the path related to the present working directly(pwd) ...

What is an example of a file path?

For example, if the file path is D:sources , the current directory is C:\Documents\ , and the last current directory on drive D: was D:\sources\ , the result is D:\sources\sources .


3 Answers

When an application (WinForms) starts up, the Environment.CurrentDirectory contains the path to the application folder (i.e. the folder that contains the .exe assembly). Using any of the File Dialogs, ex. OpenFileDialog, SaveFileDialog, etc. will cause the current directory to change (if a different folder was selected).

When running a Windows Service, its containing folder is C:\Windows\System32, as that is the System folder and it is the System (i.e. the Operation System) that is actually running your Windows Service.

Note that specifying a relative path in most of the System.IO objects, will fall back to using the Environment.CurrentDirectory property.

As mentioned, there are several ways to obtain the path of the service executable, using Assembly.GetEntryAssembly() or Assembly.GetExecutingAssembly() and then using either the Location property or the CodeBase property (be aware that this is the file path, not directory, of the executable).

Another option is to use:

`System.IO.Directory.SetCurrentDirectory( System.AppDomain.CurrentDomain.BaseDirectory );`

Make the call in the Service's OnStart method, applying it to the whole application.

like image 191
Schmuli Avatar answered Sep 28 '22 06:09

Schmuli


It is based on the current working directory which may or may not be the same as where your application resides, especially if started from a different program or a shortcut with a different working directory.

Rather than hard code the path, get the path to your program and use it. You can do this with something like this

Assembly ass = Assembly.GetEntryAssembly();
string dir = Path.GetDirectoryName(ass.Location);
string filename = Path.Combine( dir, "CAISLog.csv" );

This assumes that the entry assembly is where your file is. If not, you can change up getting the assembly for something like;

Assembly ass = Assembly.GetAssembly( typeof( AClassInYourAssembly ) );
like image 29
Rob Prouse Avatar answered Sep 28 '22 06:09

Rob Prouse


Relative Path resolution never works against the path of the launching executable. It always works against the process' Current Directory, and you can't really expect that to always be set to the directory the .exe lives in.

If you need that behavior, then take care to find out the right path on your own and provide a fully qualified path to the file operations.

like image 40
tomasr Avatar answered Sep 28 '22 06:09

tomasr