Reputation: 2609
This code snippet tries to read a file outside the location allowed for UWP apps:
StorageFile sf2 = await StorageFile.GetFileFromPathAsync(Path.Combine("C:\\Temp", "spam.dat"));
throws System.UnauthorizedAccessException which is intercepted by a Visual Studio 2015 debugger and shown in a nice popup:
The entire text is below:
An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code
WinRT information: Cannot access the specified file or folder (C:\Temp\spam.dat). The item is not in a location that the application has access to (including application data folders, folders that are accessible via capabilities, and persisted items in the StorageApplicationPermissions lists). Verify that the file is not marked with system or hidden file attributes.
An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code
Now another code snippet (this code tries to read a file which is already opened for writing):
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(ApplicationData.Current.LocalFolder.Path);
StorageFile file = await folder.CreateFileAsync("spam.dat", CreationCollisionOption.ReplaceExisting);
Stream fs = await file.OpenStreamForWriteAsync();
StorageFile sf2 = await StorageFile.GetFileFromPathAsync(Path.Combine(ApplicationData.Current.LocalFolder.Path, "spam.dat"));
await sf2.OpenStreamForReadAsync();
The exception screen in the debugger looks completely different:
Additional information: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I don't understand how debugger looks different for these exceptions. In my code, I need to understand the reason of getting UnauthorizedAccessException - if it was because file is locked for reading as it's occupied by another writer (and I can try again a bit later) or due to another reason, like it's outside of LocalFolder (and it's not worth retrying). I'm actually developing a library which will be used by developers of UWP apps so I don't know which file/filepath I will be given and can make no assumptions for permissions, directory structure, etc. I just get the path on input and, if anything happens, can only use exception handling to understand the reasons.
So, Visual Studio debugger somehow sees the difference but I don't see how I can do this programmatically. InnerException is null in both cases, HResult is the same either (0x80070005).
Upvotes: 0
Views: 264
Reputation: 12019
If you're porting a .NET library to UWP, presumably it has no dependencies on StorageFile
at all (either in implementation or public interface) so I would continue to use .NET types, which have distinct errors (Unauthorized Access vs. IO):
try
{
var f = File.OpenRead(@"d:\temp\foo.txt");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine(ex.Message);
}
try
{
var localPath = ApplicationData.Current.LocalFolder.Path;
var filename = Path.Combine(localPath, "foo.txt");
var f1 = File.OpenWrite(filename);
var f2 = File.OpenRead(filename);
}
catch (IOException ex)
{
Debug.WriteLine(ex.Message);
}
If I run your sample code, I don't get any exceptions for the write / read example using StorageFile
(although I am running Insider Builds of the Windows 10 Creator's Update). I can get an exception if I try to open the same file twice for writing, but then it's also projected as an IOException
:
try
{
var f = await StorageFile.GetFileFromPathAsync(@"d:\temp\foo.txt");
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine(ex.Message);
}
try
{
var localFolder = ApplicationData.Current.LocalFolder;
var f1 = await localFolder.CreateFileAsync("foo.txt", CreationCollisionOption.ReplaceExisting);
var f2 = await localFolder.GetFileAsync("foo.txt");
var s1 = await f1.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.AllowOnlyReaders);
var s2 = await f2.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.AllowOnlyReaders);
}
catch (IOException ex)
{
Debug.WriteLine(ex.Message);
}
Upvotes: 1
Reputation: 885
Alex,
For the second one you are working with the IO stream without disposing the previous stream you are trying to create another stream on the same file. Thus it is preventing you saying unauthorized Access. I have introduced flush the stream and dispose the stream then the code is working for me. Below is the modified code:
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(ApplicationData.Current.LocalFolder.Path);
StorageFile file = await folder.CreateFileAsync("spam.dat", CreationCollisionOption.ReplaceExisting);
Stream fs = await file.OpenStreamForWriteAsync();
fs.Flush();
fs.Dispose();
StorageFile sf2 = await StorageFile.GetFileFromPathAsync(Path.Combine(ApplicationData.Current.LocalFolder.Path, "spam.dat"));
var x = await sf2.OpenStreamForReadAsync();
Upvotes: 0