FileOpenPicker throws UnauthorizedAccessException

482 views Asked by At

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.

1

There are 1 answers

7
VasileF On BEST ANSWER

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.


Edit

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).