Search code examples
vb.netmicrosoft-metrozipwindows-runtimeaccess-denied

Zip all files in a folder


I'm a bit new to WinRT developing platform, and it's already driving me crazy (I'm a long-time .Net developer, and all those removed APIs are quite annoying) I'm experiencing a problem while zipping all files present in the Windows.Storage.ApplicationData.Current.TemporaryFolder Here is my current code (VB.Net, based on MSDN code, and "file" is the zip file I'll put all my files into) :

Using zipMemoryStream As New MemoryStream()
Using zipArchive As New Compression.ZipArchive(zipMemoryStream, Compression.ZipArchiveMode.Create)
    For Each fileToCompress As Windows.Storage.StorageFile In (Await Windows.Storage.ApplicationData.Current.TemporaryFolder.GetFilesAsync())
        Dim buffer As Byte() = WindowsRuntimeBufferExtensions.ToArray(Await Windows.Storage.FileIO.ReadBufferAsync(fileToCompress))
        Dim entry As ZipArchiveEntry = zipArchive.CreateEntry(fileToCompress.Name)
        Using entryStream As Stream = entry.Open()
            Await entryStream.WriteAsync(buffer, 0, buffer.Length)
        End Using
    Next
End Using
Using zipStream As Windows.Storage.Streams.IRandomAccessStream = Await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite)
    Using outstream As Stream = zipStream.AsStreamForWrite()
        Dim buffer As Byte() = zipMemoryStream.ToArray()
        outstream.Write(buffer, 0, buffer.Length)
        outstream.Flush()
    End Using
End Using
End Using

It builds well, but when I launch the code, I have the exception : UnauthorizedAccessException : Access denied. (Exception de HRESULT : 0x80070005 (E_ACCESSDENIED)) On line : WindowsRuntimeBufferExtensions.ToArray(blahblah... I'm wondering what is wrong. Any idea ?

Thanks in advance !


Solution

  • I rewrote your method in C# to try it out:

    var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip");
    
    using (var zipMemoryStream = new MemoryStream())
    {
        using (var zipArchive = new System.IO.Compression.ZipArchive(zipMemoryStream, System.IO.Compression.ZipArchiveMode.Create))
        {
            foreach (var fileToCompress in (await ApplicationData.Current.TemporaryFolder.GetFilesAsync()))
            {
                var buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(fileToCompress));
                var entry = zipArchive.CreateEntry(fileToCompress.Name);
                using (var entryStream = entry.Open())
                {
                    await entryStream.WriteAsync(buffer, 0, buffer.Length);
                }
            }
        }
    
        using ( var zipStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
        {
            using (var outstream = zipStream.AsStreamForWrite())
            {
                var buffer = zipMemoryStream.ToArray();
                outstream.Write(buffer, 0, buffer.Length);
                outstream.Flush();
            }
        }
    }
    

    It works flawlessly - it creates the zip file in local folder as expected. Since you get the exception in ToArray call, the reason could be that the file you're trying to open is already locked from somewhere else. If you are creating these files yourself or even only accessing them, make sure you're closing the streams.

    To test this method you could manually create a folder inside temp folder, put a couple of files in it and then run the method on that folder (the files are in C:\Users\<Username>\AppData\Local\Packages\<PackageName>\TempState) just to exclude any other reason for error.