简体   繁体   中英

FileOpenPicker throws UnauthorizedAccessException

i am currently developing a sample Windows 8 App which loads a Logfile and processes it for being shown in a DevExpress XtraGrid. When i add the required extensions to the Filetype Filter, the code throws an UnauthorizedAccessException, even though i added the File extensions to the 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();
        }
    }

Worse Thing is, that if i comment out the FileTypeFilter lines, the code jumps out at the anonymous method i added down there :

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();
        }
    }

I did thorough researches for days on end without working results (sources including StackOverflow) which is, why i pose the question right here. I appreciate any help given here :)

UPDATE :

When COMException has been thrown, the HRESULT is always (0x80070005), but the inner HRESULT (the HRESULT displayed in the Details window) was normally -21474xxxx, but when i debug my app in VS with elevated right, the inner HRESULT is -2147024891.

You don't seem to await the PickSingleFileAsync call.

You should be doing something like this :

StorageFile file = await picker.PickSingleFileAsync(); 

After you have the StorageFile from the Pick operation, you can perform whatever operations you have to, against it.


You have to stop execution until a selection from the picker is returned. Basically, this is handled for you with the line above.

Moreover, I see that the MessageDialog 's ShowAsync is also an async call which is not awaited. The usage should be :

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

or shorter :

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

Microsoft enforced this guideline of using the Async suffix to any method which is declared as async in order to be more obvious on how to use it. I suppose you should use it as well.

As a good practice, if you're launching an async call, you will have to await it at some point, otherwise you might get unpredictable results which most of the time lead to application crash.


Also, when you would like to show two message dialogs at the same type, you would run as well into this type of exception. You can have only one message dialog on the screen a time, and while the first is already being displayed, the second will attempt an operation which will throw the UnauthorizedAccessException .


Here's how you should change your code :

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();
    }
}

You don't need to add an event handler for the Completed event of the Picker. It is just enough to run your code as it is on the logFile after the PickSingleFileAsync call completed. I'm not able to provide a full working code because I'm not aware of your logic. But in any case, make sure you also await the OpenStreamForReadAsync call ( MSDN documentation ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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