Sunday, 14 August 2016

UnauthorizedAccessException when deleting local files

While coding the first update for My Daily Wallpaper, I wanted to tackle some of the bugs reported by my users. According to the Windows Dev Dashboard, the top bug (by a long shot) was an UnauthorizedAccessException. Based on the logs this exception was caused by the wallpaper manager, which handles the downloading and setting of wallpapers based on user settings, where it would attempt to delete the old wallpaper.

foreach (StorageFile file in files)
{
    if (file.Name.StartsWith(LockscreenManager.OriginalFilenamePrefix, StringComparison.OrdinalIgnoreCase))
    {
        await file.DeleteAsync();
    }
}

The odd thing was, this error didn't occur all of the time and didn't have any clues as to why it did happen when it did.

I was stumped.

So I honed my Google-fu and managed to stumble upon a MS forum post which sounded a lot like mine.

It turns out, that when you reference a local file via the Image control in xaml, a lock is put on the file.

<Image source="Path/To/Local/File" />

This lock doesn't even seem to be taken off for while after navigating away from the page that includes said Image control.

The result - an UnauthorizedAccessException when attempting to delete the local file.

My solution to this problem is to use a converter to create the Source for the Image control by getting the file stream and loading it into a BitmapImage.

public class ImageSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        string path = value as string;

        if (String.IsNullOrEmpty(path) == false)
        {
            var storageFile = StorageFile.GetFileFromPathAsync(path).AsTask().Result;

            var imageStream = storageFile.OpenStreamForReadAsync().Result;

            BitmapImage imgSource = new BitmapImage();

            imgSource.SetSource(imageStream.AsRandomAccessStream());

            return imgSource;
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

2 comments:

  1. Thank you very much for your help as I had the same issue and I was so crazy as I did not understand what is wrong :)

    ReplyDelete

Got an opinion? Who hasn't? Post it here...