UnauthorizedAccessException with path to file in temp folder from Zip archive - c#

I'm trying to make my image viewer app work with files that are opened by clicking an image file directly inside a Zip folder (using windows explorer to browse Zip files). The application seems to be run with correct command line, which looks like this:
"C:\myApp.exe" "C:\Users\Admin\AppData\Local\Temp\Temp1_Wallpapers.zip\Wallpaper1.jpg"
The file is being read with the following code:
using (var fs = new FileStream(path, FileMode.Open))
And the exception is thrown at that line:
Exception:Thrown: "Access to the path 'C:\Users\Admin\AppData\Local\Temp\Temp1_Wallpapers.zip\Wallpaper1.jpg' is denied." (System.UnauthorizedAccessException)
A System.UnauthorizedAccessException was thrown: "Access to the path 'C:\Users\Admin\AppData\Local\Temp\Temp1_Wallpapers.zip\Wallpaper1.jpg' is denied."
I figured this may be a problem with how the path is interpreted. There's a .zip in the middle of it, so this could be the problem, but I don't know how to solve that.
Also, simply opening a file at that path directly (not through zipped folder explorer window) results in the same exception.

Windows Explorer gains the ability to treat a .zip archive as a folder through a shell name extension handler. Such handlers extend the capability of the shell. But that's however restricted to shell functions only, it doesn't automagically make the low-level file access functions capable of doing the same. Like FileStream.
You'll need to copy the file out of the .zip archive first, then you can open it with FileStream. Lots of .zip support libraries around, SharpZipLib and DotNetZip are popular. It got finally added to .NET 4.5 with the System.IO.Compression.ZipArchive class. Let's pick that one for the most future-proof example code.
I created an Example.zip archive with a single image and copied it to my temp directory. This code retrieved it and made it the background image of a Winforms form:
using System.IO;
using System.IO.Compression; // Add reference to System.IO.Compression
...
private void button1_Click(object sender, EventArgs e) {
var srcePath = #"c:\users\hpass_000\appdata\local\temp\example.zip";
using (var file = new FileStream(srcePath, FileMode.Open)) {
var zip = new ZipArchive(file, ZipArchiveMode.Read);
var entry = zip.GetEntry("Chrysanthemum.jpg");
var destPath = Path.GetTempFileName();
using (var srce = entry.Open())
using (var dest = new FileStream(destPath, FileMode.Create)) {
srce.CopyTo(dest);
}
using (var img = Image.FromFile(destPath)) {
this.BackgroundImage = new Bitmap(img);
}
File.Delete(destPath);
}
}

I just found out what the problem was. Files extracted from compressed folders into temp folder will have read-only attribute, which my image viewer app apparently can't handle and throws UnauthorizedAccessException. I just need to remove that attribute and everything will be fine. Guess trying to read read-only files is an access violation of sorts.

The issue has nothing to do with the . in the temp file path because periods are legal in file names as well as directory names.
As you expect, opening a Zip folder in the shell and opening a file automatically extracts the contents to a temp folder, which is just a normal folder. The only thing that looks strange here is that it's opening the Administrator temp folder. Are you running the exe as a normal user? If the exe and shell are running under separate users, the exe may not be able to access the temp folder used by the shell.

Related

NET Core throws InvalidDataException when unzipping ZIP file, Windows Explorer unzips successfully

I'm trying to unzip a nested zip file, but I'm getting a InvalidDataException. When I try unzipping the same file in Windows Explorer, it unzips successfully. Why would Windows Explorer be able to unzip it and not the .NET Core Compression library?
I suspect there is something wrong with the zip file, but if Windows Explorer is able to do it, it must be possible to do in a .NET Core project.
I've tried unzipping the parent zip file, but that throws the InvalidDataException 'A local file header is corrupt.'
ZipFile.ExtractToDirectory("parent.zip", outputFolder) // throws exception
I've tried opening the parent zip file and unzipping the nested zip file, but that also throws the InvalidDataException 'End of Central Directory record could not be found.'
using (var archive = ZipFile.OpenRead("parent.zip"))
{
var nestedZip = archive.GetEntry("nested.zip");
using (var stream = nestedZip.Open())
using (var nestedArchive = new Archive(stream)) // throws exception
{
nestedArchive.ExtractToDirectory(outputFolder)
}
}
Try the scenario with a different zip file and see if that works, if it works means that there's some issue with the zip file.
Also try using a different librairy.

UWP StorageFile.OpenAsync Access Denied Issue

I'm running into an issue where I can read from a file in the app install directory but can't write to it.
In the below code, I open a file for reading, do stuff, dispose of my stream pointers, then try to open the file for writing.
//Open file for reading
var SocStorageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///LastSoc.txt"));
var SocInputStream = await SocStorageFile.OpenReadAsync();
var SocClassicStream = SocInputStream.AsStreamForRead();
var SocStream = new StreamReader(SocClassicStream);
<do stuff with file read>
.....
SocInputStream.Dispose();
SocClassicStream.Dispose();
SocStream.Dispose();
//Open record file for writing
var RandomAccessStream = await
SocStorageFile.OpenAsync(FileAccessMode.ReadWrite);
When I try the last line to enable write access, I get:
System.UnauthorizedAccessException: 'Access is denied. (Exception from
HRESULT: 0x80070005 (E_ACCESSDENIED))'
Worried that my Dispose() methods didn't completely clean it up, I tried commenting out all my read accesses. Same error. (Yeah I know, i should use 'using' but I don't think that's the problem here)
I'm not sure why I can't obtain write access. Advice appreciated thanks!
From the path specified in your code, it looks like you are attempting to write to a file that is part of your app's package. This file exists in the installation folder of your app which you only have read only access to.
Simply put, you can read application files in the installation directory but you can't write to files in that directory. This is also true for creating new files in the app installation directory.
Have a look at this doc from Microsoft explaining file access in UWP: https://learn.microsoft.com/en-us/windows/uwp/files/file-access-permissions
From the doc linked above, the important part is:
The app's install directory is a read-only location. You can't gain access to the install directory through the file picker.
Now, if you are planning on updating this file's content, you should move it to the Application Data folder ( ApplicationData.Current.LocalFolder ). UWP apps are allowed to read and write (and create new files) in that directory.

System.IO, where do the files get saved?

i am saving a File in Xamarin Forms using System.IO and i am not able to find it in the File-Explorer of the device, when debugging it on Live Player.
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "test.txt");
File.WriteAllText(path, "test12345678");
It throws no exception, and i can read the file afterwards using File.ReadAllText
I would expect finding this file in the Documents folder in the explorer, but i can not find it there.
Does Xamarin somehow encapsulate this from the device, or is it in some hidden Directory, which i am not able to see?

Reading zipped folder with empty subdirectories causes problems

I'm running into a strange problem using ZipFile and ZipArchive with .Net 4.5.
ZipFile.CreateFromDirectory takes all content of a directory, including folders that are empty.
If I try to create the same zip file using Windows explorer by right clicking > Send to > Compressed folder, I get a warning message saying the empty folder was omitted.
I'm loading the resulting zip file into an application that runs on Apache Tomcat. This application throws errors for every single file contained in the zip that I produced with ZipFile.CreateFromDirectory. The zip that I created manually through Windows explorer is read just fine.
I suspect the problem lies in the empty zipped folders, but haven't yet been able to definitively conclude this. If the empty folders are the cause, I'd need a way to use ZipFile.CreateFromDirectory excluding empty folders.
Taken from my comment above:
I have no .NET 4.5, but from the remarks section: "The directory structure from the file system is preserved in the archive. If the directory is empty, an empty archive is created." So this is by design.
So you either have to
fix it in the comsuming app on tomcat or you have to
create a temporary folder which just contains the non-empty folders, if possible
I haven't found a way to exclude empty folders in CreateFromDirectory in the first place.
Alternatively, I can remove empty directories from the created zip file. Though this still causes errors in the Tomcat application.
// compress and copy new zip
ZipFile.CreateFromDirectory(dirtocopy.FullName, NewZipFilePath);
using (ZipArchive za = ZipFile.Open(NewZipFilePath, ZipArchiveMode.Update))
{
// only empty folders end with \
List<ZipArchiveEntry> emptyFolders = (from ZipArchiveEntry zae in za.Entries
where zae.FullName.EndsWith("\\")
select zae).ToList<ZipArchiveEntry>();
emptyFolders.ForEach((ZipArchiveEntry folder) => folder.Delete());
}

Can't extract .zip file. Getting Invalid Data Exception

I have a very large zip file which contains other zip files inside of it. I want my c# program to be able to recognize that the file is a zip file and if it is a zip file, then to extract it to a folder in the same location as the zip file. My code is here:
private void Unzip(OpenFileDialog tvZipOpen)
{
string zipFile = tvZipOpen.FileName; // file to unzip
int i = zipFile.LastIndexOf(".zip");
string targetDirectory = zipFile.Substring(0, i); // location to extract to
using (ZipArchive zip = ZipFile.OpenRead(zipFile))
{
zip.ExtractToDirectory(targetDirectory);
}
tvZipOpen.InitialDirectory = targetDirectory;
tvZipOpen.ShowDialog();
}
I am using the ZipFile class from .NET 4.5 and i call on this method here:
if (tvOpen.ShowDialog() == DialogResult.OK)
{
while (tvOpen.FileName.ToLower().EndsWith(".zip"))
{
Unzip(tvOpen);
}
return tvOpen.FileNames;
}
The code works fine for extracting the first zip file but when I try to extract the second zip file, I get an InvalidDataException that says local file header is corrupt. However, I don't think it is corrupt because I am able to open and extract the zip files perfectly in windows explorer. I'm not sure if the fact that it is a large zip file with a zip64 extension has anything to do with it but whatever the problem is, how come I don't get the problem when I open and extract in windows explorer and how do I fix this? Any help would be greatly appreciated.
c# does not support the .zip64 extension.
how large is your zip file because if it under 4GiB rename it to .zip and it should work fine if it is larger than that see this
http://dotnetzip.codeplex.com/
To change the file extension
Open windows explorer and press Alt + V
Then go to tools and then folder options and make sure that the hide extensions for known file types box is unchecked and click apply and ok.
then simply rename the file to remove the 64 from the extension so it is just .zip
Then Click yes on the prompt
And then you should be able to open the file in your program
hope this helps

Categories

Resources