问题
I have a C# application that includes the following code:
string file = "relativePath.txt";
//Time elapses...
string contents = File.ReadAllText(file);
This works fine, most of the time. The file is read relative to the directory that the app was started from. However, in testing, it has been found that if left alone for about 5 hours, the app will throw a FileNotFoundException
saying that "C:\Documents and Settings\Adminstrator\relativePath.txt" could not be found. If the action that reads the file is run right away though, the file is read from the proper location, which we'll call "C:\foo\relativePath.txt"
What gives? And, what is the best fix? Resolving the file against Assembly.GetEntryAssembly().Location
?
回答1:
If the file is always in a path relative to the executable assembly, then yes, use Assembly.Location. I mostly use Assembly.GetExecutingAssembly if applicable though instead of Assembly.GetEntryAssembly. This means that if you're accessing the file from a DLL, the path will be relative to the DLL path.
回答2:
One spooky place that can change your path is the OpenFileDialog. As a user navigates between folders it's changing your application directory to the one currently being looked at. If the user closes the dialog in a different directory then you will be stuck in that directory.
It has a property called RestoreDirectory which causes the dialog to reset the path. But I believe the default is "false".
回答3:
I think the lesson should be don't rely on relative paths, they are prone to error. The current directory can be changed by any number of things in your running process like file dialogs (though there is a property to prevent them changing it), so you can never really guarantee where a relative path will lead at all times unless you use the relative path to generate a fixed one from a known path like Application.StartupPath (though beware when launching from Visual Studio) or some other known path.
Using relative paths will make your code difficult to maintain as a change in a totally unrelated part of your project could cause another part to fail.
回答4:
In System.Environment, you have the SpecialFolder enum, that will help you get standard relative paths.
This way at least, the path is gotten internally and handed back to you, so hopefully if the system is changing the path somehow, the code will just handle it.
回答5:
if you do somehting like
> cd c:\folder 1
c:\folder 1 > ../folder 2/theApplication.exe
The current working directory of the applicaiton will be c:\folder 1 .
Here is an example program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CWD {
class Program {
static void Main (string[] args) {
Console.WriteLine(Application.StartupPath);
}
}
}
Build this in visualstudio then open a command prompt in the debug/bin directory and do
bin/debug > CWD.exe
then do
bin/debug > cd ../../ > bin/debug/CWD.exe
you will see the difference in the startup path.
In relation to the original question... "if left alone for about 5 hours, the app will throw a FileNotFoundException"
Once the application is running, only moving, or removing that file from the expected location should cause this error.
greg
回答6:
If you use an openfiledialog and the remember path property (not sure about the exact name) is true then it will change your current directory I think.
来源:https://stackoverflow.com/questions/158219/what-would-cause-the-current-directory-of-an-executing-app-to-change