Wednesday, December 28, 2016

Always Use Environment.SpecialFolders

Never, *ever*, hard-code a path to directories like User Documents or AppData!! As far back as Windows XP, a user could move those directories off of the C drive (from C:\Users\MyName\……) and put them on another drive. This is mainly done for two reasons:

  1. To save space on the C drive.
  2. To keep data separate from the OS and other installed programs.

So, in your application, if you hard-coded a path to C:\Users\MyName\Documents you could be in trouble if you tried to write a file there, and the user had “re-mapped” the folder elsewhere … because you’d get a “Directory Not Found” exception. Instead, use the Environment.SpecialFolders enum. (Please note that this probably does NOT apply to UWP apps … and since I don’t write those currently, I can’t speak authoritatively about the correct way to determine these folders in a UWP app.)

Here’s an example:

string DocFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string MyFile = "MyTestFile.txt";
File.WriteAllText(Path.Combine(DocFolder, MyFile), "This is my test data...");

The above code-snippet will result in the file being written where a user expects it to be written.

There are a number of these SpecialFolders, such as:

Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments);

You can explore them yourself using Intellisense to see what else there is.

Another handy File/Directory trick to have up your sleeve, is the use of the Path.GetTempPath() and Path.GetTempFileName() methods.  There is typically a Temp directory in the User’s local AppData folder, so again it’s very important to use Path.GetTempPath() if you intend to write/read a file to this Temp directory.

The Path.GetTempFileName() method is great if you don’t really care about the name of the file you want to write, if it truly is a quickie temp file that you will use right away and then delete. What the GetTempFileName() method does is create a zero-byte file for you and returns the path to it, including the randomly-generated name it used. Here’s an example of how you might use it:

string temp = Path.GetTempFileName();
try
{
File.WriteAllText(temp, "This is data in a temporary file!");
// Then do something with that file, whatever your temporary needs are
}
finally
{
File.Delete(temp);
}

One last thing that I should mention. I have not found a way to access the Downloads folder using the Environment.SpecialFolders enum nor any other built-in C# methods. A fellow named Ray Koopa has a Code Project article in which he has written a wrapper class to access all the Special Folders, Downloads included. He also has created a NuGet package for his wrapper. You can find it all here:

https://www.codeproject.com/articles/878605/getting-all-special-folders-in-net 

Happy Coding! =0)