Creating zip file from multiple files - c#

The code below is working fine in creating a zip file but the file created is having a folder IIS Deploy >>>WebService... then the text file and not just the text file.
How can I just add the text files to the zip file?
ZipFile z = ZipFile.Create("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\Accident.zip");
//initialize the file so that it can accept updates
z.BeginUpdate();
//add the file to the zip file
z.Add("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\test1.txt");
z.Add("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\test2.txt");
z.Add("C:\\IIS Deploy\\WebServiceTest\\WebServiceTest\\test3.txt");
//commit the update once we are done
z.CommitUpdate();
//close the file
z.Close();

If you have everything within same folder then the easiest option is to use CreateFromDirectory class.
static void Main()
{
// Create a ZIP file from the directory "source".
// ... The "source" folder is in the same directory as this program.
// ... Use optimal compression.
ZipFile.CreateFromDirectory("source", "destination.zip",
CompressionLevel.Optimal, false);
// Extract the directory we just created.
// ... Store the results in a new folder called "destination".
// ... The new folder must not exist.
ZipFile.ExtractToDirectory("destination.zip", "destination");
}
http://www.dotnetperls.com/zipfile
Please note that it is applicable to .NET Framework 4.6 and 4.5

Related

Link to local text file in Solution c#

I need to save a set of 20 txt files into my solution so they will be included into the exe file. In such a way I will be able to send to the final users only the executable file and anything else.
I need to use the following function:
File.Copy( sourcePath, #path + "\\FileName.txt");
to copy one of the 20 files into another directory (according to the request of the user). In order to include the 20 txt files into the solution, I created a new folder into the Solution Explorer and I put them into it. Then I selected "Resources" into the option of the single txt file. Let's suppose the name of the folder is FOO and the file is NAME01, then I'm assuming the local address of the single txt file is "\FOO\NAME01.txt". But this is not working, I'm getting an arror from the File.Copy function related to the sourcePath.
Do you have any suggestions? I'm stacked on this problem and I cannot find any solution on the web. Many thanks!
Step 1: add the files to your project
Step 2: make them embedded resource
Step 3: export them to filesystem at runtime:
using System.Reflection;
namespace ConsoleApplication1
{
class Program4
{
public static void Main(string[] args)
{
using(var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("ConsoleApplication1.Files.TextFile1.txt"))
using (var filestream = System.IO.File.OpenWrite("target.txt"))
{
stream.CopyTo(filestream);
filestream.Flush();
filestream.Close();
stream.Close();
}
}
}
}
"ConsoleApplication1.Files.TextFile1.txt" comes from:
ConsoleApplication1: default namespace of the project containing the files
Files.TextFile1.txt: relative path, dotted, inside the dll (look # screenshot 1)

Download all files of a given type(.dll) from a http path in C#

There are similar questions regarding this which were asked earlier. But I couldn't find a proper solution yet.
I have an application which uses a user defined dll library(Cplus_Function_Library.dll). Imagine that the application is launched already to customers. And if there's a new version of the dll available the application will automatically download it and replaces the old one. There's no problem there.
Now I want to create new dll libraries(a lot) and upload it in the sameplace where the Cplus_Function_Library.dll new version exsists(ex: http path/FTP server). And then I can add them by reference in the Cplus_Function_Library.dll. It's also clear. But my question is how can I download all the dll files in this path without giving the file names one by one inside my updater function? Because when I launch the app these files are not known.(updater function is included inside the application.)Is there an easy way to download all the dll files from a specified path without much hassle?
My current update function can be seen below.
Uri pathToNewVerNo = new Uri("//....../New_version.txt"); //Path to the new version number
Uri pathToCurrentVerNo = new Uri("...../Current_version.txt"); //Path to the current version number
Uri pathToDownload = new Uri(".....new_library.dll");
StreamReader readNewVer; //To read the new version number
StreamReader readCurVer; //To read the current version number
StreamWriter writeToCurVer;
WebClient verNew = new WebClient(); //will be used to download the New_version .txt file
WebClient verCur = new WebClient(); //will be used to download the Current_version .txt file
WebClient update = new WebClient(); //will be used to download the new dll file
verNew.DownloadFile(pathToNewVerNo, "New_version.txt"); //Download the New_version .txt file
readCurVer = new StreamReader("Current_version.txt"); //open Current_version.txt file to read
current_Version = readCurVer.ReadLine(); //assign the value to a string
readCurVer.Close(); //close the file
readNewVer = new StreamReader("New_version.txt"); //open New_version.txt file to read
new_Version = readNewVer.ReadLine(); //assign the value to a string
readNewVer.Close(); //close the file
current_ver_doub = Convert.ToDouble(current_Version); //convert the string value to a double
new_ver_doub = Convert.ToDouble(new_Version);
if (new_ver_doub > current_ver_doub) //check if the new version number is greater than the current version number
{
obj.SBO_Application.StatusBar.SetText("Please wait update in process", BoMessageTime.bmt_Medium, BoStatusBarMessageType.smt_Warning);
writeToCurVer = new StreamWriter("Current_version.txt"); //open the current_version.txt to write
writeToCurVer.Write(new_Version); //update with new version number
writeToCurVer.Close(); //close the file
update.DownloadFile(pathToDownload, "new_library.dll"); //download the new .dll file
//*************There will be a roll back functionality added in the future in case if the updated dll file is currupted.*****************
File.Replace("new_library.dll", "Cplus_Function_Library.dll", "Cplus_Function_Library.dll.bac", false); //make a back up file of the old .dll file and replace it
obj.SBO_Application.MessageBox("Update Successful. Please restart the AddOn", 1, "Ok");
try
{
foreach (Process proc in Process.GetProcessesByName("cplus_Global"))
{
proc.Kill();
proc.WaitForExit();
}
}
catch (Exception ex)
{
obj.SBO_Application.MessageBox(ex.Message, 1, "Ok");
}
}
else
{
// SBO_Application.MessageBox("No Update Available", 1, "Ok");
}
}//End of updater_cplus function */
First of all you need to ask yourself whether you absolutely want to reinvent the wheel, and are ready to tackle all problems you will encounter while doing that, such as the problem you now ran into. There are plenty of existing solutions to include installers and updaters with your software.
Anyway, to answer your question:
how can I download all the dll files in this path without giving the file names one by one inside my updater function?
You casually mention it should work over HTTP and FTP. The former has no formal "directory listing" command, so you'll have to invent that yourself. The latter does, but requires the directory to only contain relevant files, or you need to create a whitelist and/or blacklist to include or exclude certain files.
The easiest solution would be to define your version file format so as to include the list of files to download. Then you fetch the version file, interpret it and request the files mentioned in it.
Acording to CodeCaster's idea I put all my dll files inside one folder and the new_version text file in another folder. This way I made sure different file formats won't get mixed up.
The next step was to read the new_version.txt from the ftp server and compare the value with the current version. If it's greater than the later I took all the file names of dll files to a list. Then easily you can download the files one by one to your desired location.

Creating a zip file with ionic.zip

I have the following code set up to create a zip file of a set of doucments:
public bool CreateDocumentationZipFile(int documentIdentifier, string zipDestinationPath, IList<string> documentPaths)
{
bool zipped = false;
if (documentPaths.Count > 0)
{
using (ZipFile loanZip = new ZipFile())
{
loanZip.AddFiles(documentPaths, false, zipDestinationPath);
loanZip.Save(string.Format("{0}{1}.zip",zipDestinationPath, documentIdentifier.ToString()));
zipped = true;
}
}
return zipped;
}
The issue I have is that when the zip file is created, the folder structure is maintaned within the zip file:
e.g
I am creating a zip of a selection of documents located at
C:\SoftwareDevelopment\Branches\ScannedDocuments\
When the created zip file is opened, there is a folder structure within the zip as follows:
Folder 1 ("SoftwareDevelopment")
Inside Folder 1 is folder 2 ("Branches")
Inside Folder 2 is folder 3 ("ScannedDocuments")
the scanned documents folder then contains the actual scan files.
Can anyone tell me how I can just have the scan files in the zip without the folders path being maintained?
The documentation states that the third parameter
directoryPathInArchive (String)
Specifies a directory path to use to override any path in the file
name. This path may, or may not, correspond to a real directory in the
current filesystem. If the files within the zip are later extracted,
this is the path used for the extracted file. Passing null (Nothing in
VB) will use the path on each of the fileNames, if any. Passing the
empty string ("") will insert the item at the root path within the
archive.
So if you always want to have the files added to the root of your zip archive, change
loanZip.AddFiles(documentPaths, false, zipDestinationPath);
to
loanZip.AddFiles(documentPaths, false, "");

Bundle a folder with a .Net application

How can I bundle a folder with a one click application and reference those files/folders after?
Seems rather simple but I just can't figure out how.
As in, I had the file index.html in the folder UI and I wanted to package that with the application, then I want to get the stream for that file with the string "/UI/index.html" but instead of just index.html, an entire website.
Add the folder to your VS Project, right-click on it and select "embed as resource". That will make the files in the folder be embedded in the .NET assembly. To get the file contents in your program, you can use something like this:
public class ReadResource
{
public string ReadInEmbeddedFile (string filename) {
// assuming this class is in the same assembly as the resource folder
var assembly = typeof(ReadResource).Assembly;
// get the list of all embedded files as string array
string[] res = assembly.GetManifestResourceNames ();
var file = res.Where (r => r.EndsWith(filename)).FirstOrDefault ();
var stream = assembly.GetManifestResourceStream (file);
string file_content = new StreamReader(stream).ReadToEnd ();
return file_content;
}
}
In the above function I assume your files a text/html files; if not, you can change it not to return string but byte[], and use a binary stream reader for that.
I also select the files by file.EndsWith() which is enough for my needs; if your folder has a deep nested structure you need to modify that code to parse for folder levels.
Perhaps there is a better way, but given the content is not too large you can embed binaries directly into your program as a base64 string. In this case it would need to be an archive of the folder. You would also need to embed the dll used for unzipping that archive (If I understood correctly you want to have single .exe and nothing more).
Here is a short example
// create base64 strings prior to deployment
string unzipDll = Convert.ToBase64String(File.ReadAllBytes("Ionic.Zip.dll"));
string archive = Convert.ToBase64String(File.ReadAllBytes("archive.zip"));
string unzipDll = "base64string";
string archive = "probablyaverylongbase64string";
File.WriteAllBytes("Ionic.zip.dll", Convert.FromBase64String(unzipDll));
File.WriteAllBytes("archive.zip", Convert.FromBase64String(archive);
Ionic.Zip.ZipFile archive = new Ionic.Zip.ZipFile(archiveFile);
archive.ExtractAll("/destination");
The unzipping library is DotNetZip. It's nice because you need just a single dll. http://dotnetzip.codeplex.com/downloads/get/258012
Edit:
Come to think of it, as long as you write the Ionic.dll to the working directory of the .exe you shouldn't need to use the dynamic dll loading so I removed that part to simplify the answer (it would still need to be written before you reach the method it is in though).

How to create a folder then create a csv file inside it

I have an exe that already creates a csv file. If I save the exe in C:/EXE, then the cvs file automatically gets created in C:/EXE folder.
C# code uses StreamWriter to accomplish this:
using (TextWriter log = new StreamWriter(errorLog + errorBatchNumber.ToString("000") + ".csv", true))
{
if (errorCount == 0)
{
log.WriteLine("Error message");
}
log.WriteLine(link.StatusMessage);
log.Close();
}
What I need to add:
A folder needs to be created first where the csv file will be saved.
This folder will be created where the EXE was saved, in this example: C:/EXE
After folder and cvs file was created, it needs to be zipped thru code. (But I need to accomplish first 1 and 2)
Any ideas?
Thanks in advance guys! :)
If you know the path where the EXE will be saved then
Directory.CreateDirectory(path + folderName) to create folder
To zip items use SharpZipLib at
http://www.icsharpcode.net/opensource/sharpziplib/ or http://wiki.sharpdevelop.net/SharpZipLib_MainPage.ashx
Would be something like
DirectoryInfo di = new DirectoryInfo(#"C:\exe");
if(!di.Exists)
di.Create();
Then you can use di.FullName to get the directory to save your file into.
Syntax might be a bit off but it should be enough to get you started. You can check out the MSDN on DirectoryInfo as well.

Categories