Add Multiple Folders / Directories to a ZipFile - c#

I am writing a backup program that requires predefined multiple folder(s) & single file(s) to be added to a single zip archive. I have had no issues adding a single folder using -ZipFile.CreateFromDirectory(string, string, c..level, bool(false))
However i am having a hard time adding multiple folders as there does not seem to be a way to update an archive or target two folders using the CreateFromDirectory method.
- Would be nice if there was an UpdateFromDirectory mehod!
I have been trying to stay away from third party libraries for no reason really, however as far as i have found none deal with multiple unrecursive folders.
I have tried just about everything other than writing my own code to recurse & add individually which i don't really want to do.
The program has several inputs that defines the folders / files to be zipped and depending on whether they are not null should add them to a single zip file regardless of whether they are a folder or file.
I guess my question is whether this is possible at all using the boxed libraries without custom recursing or even with a third party library without heavy mods... Not sure if i have made my question clear, sure you will all let me know if i have not.

From what I can tell using the ZipFile class you can only create and read. if you want to update you would need to create the whole zip again. [Source: ZipFile methods]
to target more than one folder you could arrange all the files and folders into one folder then zip the entire source without including the source folder. In most cases moving this files/folders isn't possible so I'd recommend looking into Symlinks within windows. I'd redirect to you [Issue with creating symbolic link to directory

You can create a "myFolder" folder and put in it all the folders you want found in the zipped folder. Then do ZipFile.CreateFromDirectory("myFolder", "name of zip file to create", CompressionLevel.Fastest, false, Encoding.UTF8). Overriding this IncludeBaseDirectory method to false allows this to be done.

Related

Building own Installer for Game

I have made a game and wish to distribute it online. I have spent years playing around with many Installers (InstallWise, InstallShield, etc, etc, etc).
They are very complex, require time and in most cases, a decent amount of money. So I want to write my own Installer, that will install my game for the user.
My game is comprised of:
DLL files (these will go inside the Game's folder, inside Program Files.
The application file itself (a single .exe file).
I will also need to create a shortcut on the Desktop (if the user allows) which will launch the .exe in Program Files folder. I can already do this.
I know how to copy and write files to folders. What I am asking is, how do I "pack" the files into my installer file, so that I can give a user a single file to download, which will then "unpack" the game's files into the appropriate location?
I have asked this question 2 years ago on SO and was met with hostility; the person claimed that this is not possible - but incase they haven't noticed, 90% of installers are just a single file, which unpacks its contents into a directory/several directories. So I know it is possible.
The only way I can think of that I can get this to work is by going over each file that needs to be packed, and reading the bytes into the app and storing it into an embedded file. And when the app is run, it will look for embedded files/bytes and write those bytes to new files in the specified locations. Please correct me if I am wrong.
Any help will be greatly appreciated.
You will need to either save the bytes in your installer, which means that you will need a builder for the actual installer which will use CodeDom.
Or you can download the files from a server, which seems faster in this case.
You choose.
To do so i would use a Self-Extract Zip. this is an exe that will unpack itself with all necessary files then you set the after extract command to call and exe of yours which copy everything where you want and then create yourself link on desktop and such. not very difficult.
In the Self-Extract file you can also specify that the content is extracted in the temp folder of the computer allowing you to find stuff using environment special directory

How to merge 2 zip files together into 1 zip

I am trying to make a custom launcher for Minecraft in C# but I have come across a bump.
I want to add something into it, Minecraft Forge, but the only way I could think of is to change the extension of minecraft.jar to minecraft.zip, extract the contents of the Minecraft Forge.zip and the minecraft.zip into the same folder and then zip that entire folder up into minecraft.jar.
However minecraft.jar has a file named aux.class so whenever my extract script (Made in java) tries to extract it, it simply says:
Unable to find file G:\Programming\C#\Console\Forge Installer\Forge Installer\bin\Debug\Merge\aux.class.
The only other way I can think of is to merge minecraft_forge.zip into minecraft.zip, I have spent around 2 hours looking on Google (watch as someone sees it within a couple of minutes) but it always shows me results for "How to zip multiple files", "How to make a zip file in C#" etc.
So I have come here looking for my answer, sorry if this is a lot to read but I always see comments on here saying "You didn't give enough information for us to help you with".
EDIT: The question in case it wasn't clear is: How am I able to put the contents of minecraft_forge.zip into minecraft.zip?
In your case, if you cannot unzip the files due to OS limitations, you need to "skip" unzipping temporary files to zip them. Instead, only handle input & output streams, as suggested in the answers found here: How can I add entries to an existing zip file in Java?
As you pointed out, "aux" is a protected keyword within windows and it does not matter what the file suffix may be; windows won't let you use it. Here are a couple of threads that discusses this in general.
Ref 1: Windows reserved words.
Ref 2: Windows reserved words.
If you are typing in commands to perform the copy or unzip, there is a chance you can get this to work by using a path prefix of the following \\.\ or \\?\. When I tested this, it worked with either a single or double back-slash following the period or question mark. Such that the following work:
\\.\c:\paths\etc
\\.\\c:\paths\etc
\\?\c:\path\etc
\\?\\c:\path\etc
I used the following command to test this. When trying to rename through windows explorer it gave a "The specified device name is invalid." error message. From the command line it worked just fine. I should point out, that once you create these files, you will have to manually delete them using the same technique. Windows Explorer reports that these text files which have a size of 0 bytes "is too large for the destination file system", ie... the recycle bin.
rename "\.\c:\temp\New Text Document.txt" aux.txt
del "\.\c:\temp\aux.txt"
As far as copying directly from zip or jar files, I tried this myself and it appeared to work. I used 7-zip and opened the jars directly using the "open archive..." windows explorer context menu. I then dragged-and-dropped the contents from forge.jar to the minecraft jar file. Since it is the minecraft jar file with the offending file name the chance of needing to create a temporary file on the filesystem is reduced. I did see someone mention that 7-zip may extract to a temporary file when copying between jars and zips.
7-zip reference on copying between archives
I should point out that my copy of minecraft jar (minecraft_server.1.8.7.jar) did not contain a file named aux.class. I also did not try to use the jar after the copy/merge. Nor did I spend too much time trying to figure out how well it merged the two contents since it appears like there may be a conflict with com\google\common\base\ since there are similar class name but with different $ variable suffixes on them.
I hope these two possible suggestions could give you some room to work with to find a solution for your needs... if you're still looking.

Using zip archives

I created quite a neat application for backups. It just copies the directories you specify to wherever you want. Unfortunately I encountered a problem. The maximum length of the file path is about 250 so what happens is that the program can't copy files if the new location path is longer - and the program collapses.
I learned that using zip archives would resolve the problem. But... The program uses some filters and it's logic isn't that straightforward. I really wouldn't like to rewrite it all.
My program visits all subdirectories in a specified directory and checks if there are any new or modified files there. If it finds some it copies it to ..../Backups/......../dir_A/dir_B/file. Every file and dir is processed separately (it's checked if it was modified, if it fits the filters, etc)
What I need is something that would help me substitute Backups directory with Backups.zip Especially offering something like this:
myArchive.copyFile("dir_a/dir_b/...../file", original_file_path);
myArchive.fileModificationDate("dir_a/dir_b/...../file");
myArchive.getDirectotiesIn("dir_a/dir_b/");
Is there such a feature in .Net? Or maybe there is a free library for this?
There are mainly two free alternatives for handling zip files in c# :
DotNetZip
SharpZipLib
I prefer DotNetZip.
SharpZipLib

Make sure file got copied successfully using c#

I am creating an application to back up files from a source directory into a destination directory. I store the files information from the source and destination folders in separate lists then I compare the lists based on their size, date modified etc to see which files need to be copied.
Anyways the point is that I end up with a list of the files that need to be copied and I will like to know how much time is every file taking therefore I have tried the following techniques:
Technique 1
Technique 2
Thechnique 3 : the regular File.Copy("source....","Destination")
The first two techniques are great because I can see the progress. The problem is that when I copy some files with those techniques, the new file sometimes has different dates. I will like both files to have the same modified date and also the same creation date. Moreover if for whatever reason my program crashes the file that is being copied will be corrupted because I have tried copying a large file ( a file that takes about a minute to get copied in windows) if I exit my program meanwhile the file is being copied the file that is being copied sometimes has the same attributes and the same size so I want to make sure I don't have corrupted files in case my program crashes.
Maybe I should use aether techniques 1 or 2 and then at the end copy the attributes from the source file and assign those to the destination file. I don't know how to do that though.
FileInfo has members CreationTime and LastWriteTime that are settable - so you could settle for your preferring techniques and set the dates afterwards if that helps.
Have you considered just writing a shell script that calls robocopy? Any time I've had to run backup tasks like this, I just write a script -- robocopy already does the heavy lifting for me, so there's often no need to create a bespoke application.
A solution that I have but its long:
I know I can copy the file from the source and then name the file in the destination something else like "fileHasNotBeenCopiedYet" with attributes of hidden then when my program finishes copying the file change the name to the source name and copy the attributes and then latter I know that if a file with that name ("fileHasNotBeenCopiedYet") exists that means that the file is corrupted.

How can you detect when files are dropped into Windows Explorer?

I have a WinForms app that has a TreeView. The user can drag files from WindowsExplorer to the TreeView, and then they can drag the files back into WindowsExplorer which in affect copies the files to wherever the files were dropped. What I'm trying to do is, if the files already exist in the directory where the files are being dropped, I want to rename the files/folders being copied in ahead of time, so that there's no collision.
Here's how I'm copying files into WindowsExplorer. On the treeView's ItemDrag, I loop through the nodes of the selected node, and then package that into an array. Then, I use this code:
var dataObject = new DataObject(DataFormats.FileDrop, files.ToArray());
dataObject.SetData(DataFormats.StringFormat, dataObject);
DoDragDrop(dataObject, DragDropEffects.Copy);
This works well, but once it ships off to Windows Explorer, it's out of my hands. How can I find out when and where the files are being copied TO and intercept that to make changes? Is this possible?
Explorer Drag & Drop is an excellent article doing what you are trying to achieve.
EDIT2: It seems that there's a C++ article available for the same on CodeProject. But I was unable to find a way of how to do it using C#.
AFAIK, there is no way to know drop target (in your case destination folder). You can look into CFSTR_FILENAMEMAP shell clipboard format, but still in this case you can only provide name mappings before (or in process) of drag-n-drop.
Also note, that default DataObject in .net has limited shell support. So if you need to use mentioned above format, you need to write your own IDataObject implementation (or take someone's implementation, good example with lot shell drag-n-drop related stuff can be found here)
Instead of putting the file names into the dataobject, create a temporary file with a unique/easily distinguishable name and place that file name into the data object's drop list instead (That file could be empty or contain some information you might need). Use a FileSystemWatcher (watching an entire drive) to detect the drop (set the filter to the temporary file name, set IncludeSubDirectories to true, and set Path to root directory of drive to watch.) Initiate the DoDragDrop. Once the unique/easily distinguishable file is dropped, the FileSystemWatcher can tell you where it was dropped and you can do whatever you need to do (e.g. delete the dropped temporary file and replace with the ones you originally wanted to drop. It is a far-from-perfect solution but might help. Better still, it might give someone an idea to come up with a better one!)
One downside is that you don't really know in which drive someone might drop the file and you may have to set up a watcher for several drives. And if you miss a drive (or a network path) then problems .....! Remember to dispose of the watchers after the drop.
There has to be a better way though. e.g. consider when you drag a file from a zip folder. The file is only extracted after the drop.
i don't think that is possible.

Categories