简体   繁体   English

如何在UWP应用程序中区分System.UnauthorizedAccessException的不同“类型”?

[英]How to distinguish between different “types” of System.UnauthorizedAccessException in UWP application?

This code snippet tries to read a file outside the location allowed for UWP apps: 此代码段尝试在UWP应用允许的位置之外读取文件:

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: 引发System.UnauthorizedAccessException,该异常会被Visual Studio 2015调试器拦截并显示在漂亮的弹出窗口中:

WinRT例外对话框

The entire text is below: 全文如下:

An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code mscorlib.ni.dll中发生类型'System.UnauthorizedAccessException'的异常,但未在用户代码中处理

WinRT information: Cannot access the specified file or folder (C:\\Temp\\spam.dat). WinRT信息:无法访问指定的文件或文件夹(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). 该项目不在应用程序可以访问的位置(包括应用程序数据文件夹,可通过功能访问的文件夹以及StorageApplicationPermissions列表中的持久项)。 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 mscorlib.ni.dll中发生类型'System.UnauthorizedAccessException'的异常,但未在用户代码中处理

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)) (来自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). 在我的代码中,我需要了解获得UnauthorizedAccessException的原因-如果是因为文件被另一个编写者占用而被锁定以进行读取(我可以稍后再试),或者是由于另一个原因,例如它在LocalFolder之外(并且不值得重试)。 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. 我实际上正在开发一个将由UWP应用程序的开发人员使用的库,所以我不知道将获得哪个文件/文件路径,并且不能对权限,目录结构等进行任何假设。我只是在输入时获取路径并且,如果发生任何情况,只能使用异常处理来了解原因。

So, Visual Studio debugger somehow sees the difference but I don't see how I can do this programmatically. 因此,Visual Studio调试器会以某种方式看到差异,但是我看不到如何以编程方式进行此操作。 InnerException is null in both cases, HResult is the same either (0x80070005). 在这两种情况下,InnerException都为null,HResult也相同(0x80070005)。

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): 如果要将.NET库移植到UWP,大概它根本不依赖于StorageFile (在实现中还是在公共接口中),因此我将继续使用.NET类型,该类型有明显的错误(未经授权的访问与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). 如果运行示例代码,则使用StorageFile读写示例不会有任何异常(尽管我正在运行Windows 10 Creator更新的Insider Builds)。 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 : 如果我尝试两次打开同一文件进行写入,则可以得到一个异常,但是它也被投影为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);
}

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. 对于第二个,您正在使用IO流,而没有处理前一个流,而您正在尝试在同一文件上创建另一个流。 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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM