Inconsistent Exceptions for WinRT File Operations
Recently I encountered strange and inconsistent behavior in exceptions being thrown by different file operations in WinRT. Let's start with a snippet:
var file = await Package.Current.InstalledLocation.GetFileAsync(@"\Assets\Text.txt");
file.CopyAsync(ApplicationData.Current.LocalFolder);
Although there is a file named Text.txt
in Assets
folder of the application package, the above code throws an exception. If you were paying close attention while reading the code you might have even noticed the problem. There's no exception thrown in the first line, though. Instead the second line throws an ArgumentException
:
Value does not fall within the expected range.
Strange, isn't it?
Let's take a closer look by putting a breakpoint on the second line. The problem lies in the value of file.Path
property: C:\Users\Username\Documents\Visual Studio 2012\Projects\SlnName\ProjName\bin\Debug\AppX\\Assets\Text.txt
. Did you notice the two backslashes before the Assets
folder? They're causing the problem. CopyAsync
method can't find the file because of it and throws the non-descriptive exception which doesn't really help pinpointing its cause. Calling ReadTextAsync
on the file instead would've make it much easier:
var file = await Package.Current.InstalledLocation.GetFileAsync(@"\Assets\Text.txt");
var text = await FileIO.ReadTextAsync(file);
In this case the second line throws FileNotFoundException
:
The filename, directory name, or volume label syntax is incorrect.
Definitely much clearer. Too bad, CopyAsync
doesn't throw the same exception. It would have made troubleshooting the original issue much easier.
That's not all, though. I still think the exception should already be thrown in the first line. If we replace the filename with a non-existent one (e.g. Text1.txt
), it does throw FileNotFoundException
as expected:
The system cannot find the file specified.
It seems that for some reason GetFileAsync
can handle paths with double backslashes. It even sets file.DateCreated
correctly, so there can be no doubt about that. The other methods don't seem to support this same syntax. That's not a problem per se, but in my opinion all methods should behave the same to avoid confusion: either support the syntax or not. Until that happens, I'll keep in mind the described anomaly, just in case I stumble upon it again.