0

我目前正在开发一个示例 Windows 8 应用程序,它加载一个日志文件并对其进行处理,以便在 DevExpress XtraGrid 中显示。当我将所需的扩展名添加到文件类型筛选器时,代码会引发 UnauthorizedAccessException,即使我将文件扩展名添加到 appxmanifest :

private void OpenFile()
    {
        try
        {
            FileOpenPicker pickLog = new FileOpenPicker();
            pickLog.CommitButtonText = "Logdatei öffnen";
            pickLog.SuggestedStartLocation = PickerLocationId.ComputerFolder;
            pickLog.ViewMode = PickerViewMode.List;
            pickLog.FileTypeFilter.Add(".log"); //This is where the code jumps out
            pickLog.FileTypeFilter.Add(".slg");

            pickLog.PickSingleFileAsync().Completed += delegate
            {
                StorageFile logFile = pickLog.PickSingleFileAsync().GetResults();
                Stream strLog = logFile.OpenStreamForReadAsync().Result;

                vm.LoadCommand.Execute(strLog);
            };

            pickLog.PickSingleFileAsync();
        }
        catch (Exception ex) //Catches UnauthorizedAccessException
        {
            MessageDialog md = new MessageDialog(ex.Message, ex.GetType().ToString());
            md.ShowAsync();
        }
    }

更糟糕的是,如果我注释掉 FileTypeFilter 行,代码会在我添加的匿名方法处跳出:

private void OpenFile()
    {
        try
        {
            FileOpenPicker pickLog = new FileOpenPicker();
            pickLog.CommitButtonText = "Logdatei öffnen";
            pickLog.SuggestedStartLocation = PickerLocationId.ComputerFolder;
            pickLog.ViewMode = PickerViewMode.List;
            //pickLog.FileTypeFilter.Add(".log"); 
            //pickLog.FileTypeFilter.Add(".slg");

            pickLog.PickSingleFileAsync().Completed += delegate //This is where the code jumps out
            {
                StorageFile logFile = pickLog.PickSingleFileAsync().GetResults();
                Stream strLog = logFile.OpenStreamForReadAsync().Result;

                vm.LoadCommand.Execute(strLog);
            };

            pickLog.PickSingleFileAsync();
        }
        catch (Exception ex) //Catches COMException
        {
            MessageDialog md = new MessageDialog(ex.Message, ex.GetType().ToString());
            md.ShowAsync();
        }
    }

我连续几天进行了彻底的研究,但没有工作结果(包括 StackOverflow 在内的来源),这就是为什么我在这里提出这个问题。我感谢这里提供的任何帮助:)

更新 :

抛出 COMException 时,HRESULT 始终为 (0x80070005),但内部 HRESULT(显示在详细信息窗口中的 HRESULT)通常为 -21474xxxx,但是当我在 VS 中使用提升权限调试我的应用程序时,内部 HRESULT 为 -2147024891 .

4

1 回答 1

1

你似乎不awaitPickSingleFileAsync电话。

你应该做这样的事情:

StorageFile file = await picker.PickSingleFileAsync(); 

在您拥有StorageFilefrom Pick 操作之后,您可以针对它执行任何您必须执行的操作。


您必须停止执行,直到从选择器返回选择。基本上,这是通过上面的行为您处理的。

此外,我看到MessageDialog'sShowAsync也是一个不等待的异步调用。用法应该是:

var messageDialog = new MessageDialog(...);
await messageDialog.ShowAsync();

或更短:

await new MessageDialog('','').ShowAsync();

AsyncMicrosoft对声明为 async 的任何方法强制执行此指南,以便更清楚地了解如何使用它。我想你也应该使用它。

作为一种好的做法,如果您要启动异步调用,则必须在某个时候等待它,否则您可能会得到不可预知的结果,这在大多数情况下会导致应用程序崩溃。


此外,当您想显示两个相同类型的消息对话框时,您也会遇到这种类型的异常。您一次只能在屏幕上显示一个消息对话框,当第一个已显示时,第二个将尝试执行操作,该操作将抛出UnauthorizedAccessException.


编辑

以下是您应该如何更改代码:

private async Task OpenFile()
{
    try
    {
        FileOpenPicker pickLog = new FileOpenPicker();
        pickLog.CommitButtonText = "Logdatei öffnen";
        pickLog.SuggestedStartLocation = PickerLocationId.ComputerFolder;
        pickLog.ViewMode = PickerViewMode.List;
        pickLog.FileTypeFilter.Add(".log"); //This is where the code jumps out
        pickLog.FileTypeFilter.Add(".slg");

        StorageFile logFile = await pickLog.PickSingleFileAsync();

        //operations on logFile are safe to be done here (open stream, loadCommand etc)
    }
    catch (Exception ex) //Catches UnauthorizedAccessException
    {
        MessageDialog md = new MessageDialog(ex.Message, ex.GetType().ToString());
        md.ShowAsync();
    }
}

您不需要为CompletedPicker 的事件添加事件处理程序。在调用完成logFile后运行您的代码就足够了。PickSingleFileAsync我无法提供完整的工作代码,因为我不知道您的逻辑。但无论如何,请确保您也await拨打OpenStreamForReadAsync电话(MSDN 文档)。

于 2014-12-08T15:51:02.167 回答