0

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.

Community
  • 1
  • 1
AlphaNERD
  • 155
  • 1
  • 1
  • 9

1 Answers1

1

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

VasileF
  • 2,856
  • 2
  • 23
  • 36
  • Thanks for your hint, i applied the changes as shown in your answer, but it still wont work. Visual Studio doesn't allow the `await` statement in a `catch` block – AlphaNERD Dec 09 '14 at 08:08
  • I've added some edits, I hope you can sort it out now to make it work. Long story short, all calls for methods with Async suffix have to be awaited. Read a little more about the async-await usage. – VasileF Dec 09 '14 at 08:22
  • That is true, you cannot await in a catch block. But why would you want to display the error in such way? Is it for debug purpose? Simply put a breakpoint in the catch block and see details about the "ex" variable which has details about the exception. – VasileF Dec 09 '14 at 10:02
  • Thanks, mate, the code in the edit block finally helped me :) Thats why i like StackOverflow @Vasile : Yes, the MessageDialog was simply for Debugging purposes – AlphaNERD Dec 09 '14 at 11:33
  • Use breakpoints! :) See the exception details, then take appropriate actions. Haven't tried yet in the Windows Store, but I guess you could also use the Output Window and write there some logs about the exception - Debug.WriteLine(exception.Message). – VasileF Dec 09 '14 at 14:53
  • I guess you would not believe this, but VS has its issues with breakpoints sometimes. The thing is, that if i want to debug step - by - step and run into an unhandled exception, the pointer goes directly to app.g.i.cs, which it shouldn't. I tried to use Debug.WriteLine while fixing another issue, but it did not write anything – AlphaNERD Dec 10 '14 at 08:48
  • If your app is on an actual device and you're trying to debug it, then yes, in case of an exception, you will be redirected to app.g.i.cs. But even there, inspect the contents of the "e" variable which stands for the exception which occured. Put a breakpoint after the "UnhandledException += (sender, e) =>" ... line and then inspect the contents of e. – VasileF Dec 10 '14 at 09:54