private void createSelfExtractingZip(MyFile mf) { try { NetworkDrives.MapDrive("iboxx"); //comment for local testing 3/26 using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) { if (mf.IsFolder) { zip.AddDirectory(mf.From); } else { zip.AddFile(mf.From); } Ionic.Zip.SelfExtractorSaveOptions options = new Ionic.Zip.SelfExtractorSaveOptions(); options.Flavor = Ionic.Zip.SelfExtractorFlavor.ConsoleApplication; zip.SaveSelfExtractor(mf.FullName, options); } NetworkDrives.DisconnectDrive("iboxx"); //comment for local testing } catch (Exception e) { displayError(e); throw; //if (Error == "") { // Error = "Error caught in createSelfExtractingZip() " + e; // throw; //} ////ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "Message", "<script>alert('Error caught in createSelfExtractingZip() " + e + "');</script>", true); ////this.Response.Write("<script>alert('Error caught in createSelfExtractingZip() " + e + "');</script>"); } }
/// <summary> /// Create a self-extracting ZIP using the DoNetZip library /// </summary> public static void CreateSelfExtractingZip(string outputFile, string tempFilePath, string productVersion, string productDescription, string installPath, string postExtractCommand) { if (!String.IsNullOrEmpty(outputFile)) { using (var zip = new ZipFile()) { zip.AddDirectory(tempFilePath); var options = new SelfExtractorSaveOptions { ProductName = productDescription, ProductVersion = productVersion, FileVersion = new System.Version(productVersion), Description = productDescription, Copyright = "Copyright © Influence Health 2015", DefaultExtractDirectory = installPath, Flavor = SelfExtractorFlavor.WinFormsApplication, Quiet = false, RemoveUnpackedFilesAfterExecute = false, IconFile = Environment.CurrentDirectory + @"\Installer.ico", ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently, PostExtractCommandLine = postExtractCommand }; zip.SaveSelfExtractor(outputFile, options); } } }
//string _defaultExtractLocation; //string _postExtractCmdLine; // string _SetDefaultLocationCode = // "namespace Ionic.Zip { public partial class WinFormsSelfExtractorStub { partial void _SetDefaultExtractLocation() {" + // " txtExtractDirectory.Text = \"@@VALUE\"; } }}"; /// <summary> /// Saves the ZipFile instance to a self-extracting zip archive. /// </summary> /// /// <remarks> /// /// <para> /// The generated exe image will execute on any machine that has the .NET /// Framework 2.0 installed on it. The generated exe image is also a /// valid ZIP file, readable with DotNetZip or another Zip library or tool /// such as WinZip. /// </para> /// /// <para> /// There are two "flavors" of self-extracting archive. The /// <c>WinFormsApplication</c> version will pop up a GUI and allow the /// user to select a target directory into which to extract. There's also /// a checkbox allowing the user to specify to overwrite existing files, /// and another checkbox to allow the user to request that Explorer be /// opened to see the extracted files after extraction. The other flavor /// is <c>ConsoleApplication</c>. A self-extractor generated with that /// flavor setting will run from the command line. It accepts command-line /// options to set the overwrite behavior, and to specify the target /// extraction directory. /// </para> /// /// <para> /// There are a few temporary files created during the saving to a /// self-extracting zip. These files are created in the directory pointed /// to by <see cref="ZipFile.TempFileFolder"/>, which defaults to <see /// cref="System.IO.Path.GetTempPath"/>. These temporary files are /// removed upon successful completion of this method. /// </para> /// /// <para> /// When a user runs the WinForms SFX, the user's personal directory (<see /// cref="Environment.SpecialFolder.Personal">Environment.SpecialFolder.Personal</see>) /// will be used as the default extract location. If you want to set the /// default extract location, you should use the other overload of /// <c>SaveSelfExtractor()</c>/ The user who runs the SFX will have the /// opportunity to change the extract directory before extracting. When /// the user runs the Command-Line SFX, the user must explicitly specify /// the directory to which to extract. The .NET Framework 2.0 is required /// on the computer when the self-extracting archive is run. /// </para> /// /// <para> /// NB: This method is not available in the version of DotNetZip build for /// the .NET Compact Framework, nor in the "Reduced" DotNetZip library. /// </para> /// /// </remarks> /// /// <example> /// <code> /// string DirectoryPath = "c:\\Documents\\Project7"; /// using (ZipFile zip = new ZipFile()) /// { /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); /// zip.Comment = "This will be embedded into a self-extracting console-based exe"; /// zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication); /// } /// </code> /// <code lang="VB"> /// Dim DirectoryPath As String = "c:\Documents\Project7" /// Using zip As New ZipFile() /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) /// zip.Comment = "This will be embedded into a self-extracting console-based exe" /// zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication) /// End Using /// </code> /// </example> /// /// <param name="exeToGenerate"> /// a pathname, possibly fully qualified, to be created. Typically it /// will end in an .exe extension.</param> /// <param name="flavor"> /// Indicates whether a Winforms or Console self-extractor is /// desired. </param> public void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor) { SelfExtractorSaveOptions options = new SelfExtractorSaveOptions(); options.Flavor = flavor; SaveSelfExtractor(exeToGenerate, options); }
/// <summary> /// Saves the ZipFile instance to a self-extracting zip archive, using /// the specified save options. /// </summary> /// /// <remarks> /// <para> /// This method saves a self extracting archive, using the specified save /// options. These options include the flavor of the SFX, the default extract /// directory, the icon file, and so on. See the documentation /// for <see cref="SaveSelfExtractor(string , SelfExtractorFlavor)"/> for more /// details. /// </para> /// /// <para> /// The user who runs the SFX will have the opportunity to change the extract /// directory before extracting. If at the time of extraction, the specified /// directory does not exist, the SFX will create the directory before /// extracting the files. /// </para> /// /// </remarks> /// /// <example> /// This example saves a WinForms-based self-extracting archive EXE that /// will use c:\ExtractHere as the default extract location. The C# code /// shows syntax for .NET 3.0, which uses an object initializer for /// the SelfExtractorOptions object. /// <code> /// string DirectoryPath = "c:\\Documents\\Project7"; /// using (ZipFile zip = new ZipFile()) /// { /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); /// zip.Comment = "This will be embedded into a self-extracting WinForms-based exe"; /// var options = new SelfExtractorOptions /// { /// Flavor = SelfExtractorFlavor.WinFormsApplication, /// DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere", /// PostExtractCommandLine = ExeToRunAfterExtract, /// SfxExeWindowTitle = "My Custom Window Title", /// RemoveUnpackedFilesAfterExecute = true /// }; /// zip.SaveSelfExtractor("archive.exe", options); /// } /// </code> /// <code lang="VB"> /// Dim DirectoryPath As String = "c:\Documents\Project7" /// Using zip As New ZipFile() /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) /// zip.Comment = "This will be embedded into a self-extracting console-based exe" /// Dim options As New SelfExtractorOptions() /// options.Flavor = SelfExtractorFlavor.WinFormsApplication /// options.DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere" /// options.PostExtractCommandLine = ExeToRunAfterExtract /// options.SfxExeWindowTitle = "My Custom Window Title" /// options.RemoveUnpackedFilesAfterExecute = True /// zip.SaveSelfExtractor("archive.exe", options) /// End Using /// </code> /// </example> /// /// <param name="exeToGenerate">The name of the EXE to generate.</param> /// <param name="options">provides the options for creating the /// Self-extracting archive.</param> public void SaveSelfExtractor(string exeToGenerate, SelfExtractorSaveOptions options) { // Save an SFX that is both an EXE and a ZIP. // Check for the case where we are re-saving a zip archive // that was originally instantiated with a stream. In that case, // the _name will be null. If so, we set _writestream to null, // which insures that we'll cons up a new WriteStream (with a filesystem // file backing it) in the Save() method. if (_name == null) { _writestream = null; } _SavingSfx = true; _name = exeToGenerate; if (Directory.Exists(_name)) { throw new ZipException("Bad Directory", new System.ArgumentException("That name specifies an existing directory. Please specify a filename.", "exeToGenerate")); } _contentsChanged = true; _fileAlreadyExists = File.Exists(_name); _SaveSfxStub(exeToGenerate, options); Save(); _SavingSfx = false; }
private void button1_Click(object sender, EventArgs e) { if (!created) { string DirectoryPath = @"C:\SOURCE\DSPControlCenter\Setup\Setup\Express\SingleImage\DiskImages\DISK1"; using (ZipFile zip = new ZipFile()) { zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); zip.Comment = "This will be embedded into a self-extracting console-based exe"; SelfExtractorSaveOptions options = new SelfExtractorSaveOptions(); options.Flavor = SelfExtractorFlavor.ConsoleApplication; options.Quiet = true; options.DefaultExtractDirectory = "%TEMP%\\DSPCC"; options.PostExtractCommandLine = "%TEMP%\\DSPCC\\DISK1\\setup.exe"; options.RemoveUnpackedFilesAfterExecute = true; options.FileVersion = new Version(2, 1, 0); options.Description = "DSP Control Center Installer Package"; options.Copyright = "© 2013 Stewart Audio, Inc."; options.IconFile = @"C:\SOURCE\DSPControlCenter\DSP Control Center v4.ico"; options.ProductName = "DSP Control Center"; options.ProductVersion = "2.1.0"; options.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; zip.SaveSelfExtractor(txtFilename.Text + " v" + txtVersion.Text + ".exe", options); button1.Text = "Open Folder"; created = true; } } else { string myPath = @"C:\SOURCE\DSPControlCenter\Setup\SetupLauncher\SetupLauncher\bin\Debug"; System.Diagnostics.Process prc = new System.Diagnostics.Process(); prc.StartInfo.FileName = myPath; prc.Start(); } }
public void run() { logger.Info("Making archive [what's it called?]"); using (ZipFile zip = new ZipFile()) { if (Directory.Exists(SourceDir)) { zip.AddDirectory(SourceDir, Path.GetFileName(SourceDir)); } else { // logger? Console.WriteLine("{0} is not a valid directory", SourceDir); Environment.Exit(1); } // these files install and log the patch zip.AddFile("Clyde.exe"); zip.AddFile("PatchLib.dll"); zip.AddFile("Nini.dll"); zip.AddFile("NLog.dll"); zip.AddFile("NLog.config"); SelfExtractorSaveOptions options = new SelfExtractorSaveOptions(); options.Flavor = SelfExtractorFlavor.ConsoleApplication; options.ProductVersion = VersionInfo.PRODUCT_VERSION; options.DefaultExtractDirectory = ExtractDir; options.Copyright = VersionInfo.COPYRIGHT; options.PostExtractCommandLine = "Clyde.exe"; // false for dev, (maybe) true for production options.RemoveUnpackedFilesAfterExecute = false; string patchName = @"envision-installer-" + PatchVersion + @".exe"; zip.SaveSelfExtractor(patchName, options); } }
private void _SaveSfxStub(string exeToGenerate, SelfExtractorSaveOptions options) { string nameOfIconFile = null; string stubExe = null; string unpackedResourceDir = null; string tmpDir = null; try { if (File.Exists(exeToGenerate)) { if (Verbose) { StatusMessageTextWriter.WriteLine("The existing file ({0}) will be overwritten.", exeToGenerate); } } if (!exeToGenerate.EndsWith(".exe")) { if (Verbose) { StatusMessageTextWriter.WriteLine("Warning: The generated self-extracting file will not have an .exe extension."); } } // workitem 10553 tmpDir = TempFileFolder ?? Path.GetDirectoryName(exeToGenerate); stubExe = GenerateTempPathname(tmpDir, "exe"); // get the Ionic.Zip assembly Assembly a1 = typeof(ZipFile).Assembly; using (var csharp = new Microsoft.CSharp.CSharpCodeProvider (new Dictionary <string, string>() { { "CompilerVersion", "v2.0" } })) { // The following is a perfect opportunity for a linq query, but // I cannot use it. DotNetZip needs to run on .NET 2.0, // and using LINQ would break that. Here's what it would look // like: // // var settings = (from x in SettingsList // where x.Flavor == flavor // select x).First(); ExtractorSettings settings = null; foreach (var x in SettingsList) { if (x.Flavor == options.Flavor) { settings = x; break; } } // sanity check; should never happen if (settings == null) { throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", options.Flavor)); } // This is the list of referenced assemblies. Ionic.Zip is // needed here. Also if it is the winforms (gui) extractor, we // need other referenced assemblies, like // System.Windows.Forms.dll, etc. var cp = new System.CodeDom.Compiler.CompilerParameters(); cp.ReferencedAssemblies.Add(a1.Location); if (settings.ReferencedAssemblies != null) { foreach (string ra in settings.ReferencedAssemblies) { cp.ReferencedAssemblies.Add(ra); } } cp.GenerateInMemory = false; cp.GenerateExecutable = true; cp.IncludeDebugInformation = false; cp.CompilerOptions = ""; Assembly a2 = Assembly.GetExecutingAssembly(); // Use this to concatenate all the source code resources into a // single module. var sb = new System.Text.StringBuilder(); // In case there are compiler errors later, we allocate a source // file name now. If errors are detected, we'll spool the source // code as well as the errors (in comments) into that filename, // and throw an exception with the filename. Makes it easier to // diagnose. This should be rare; most errors happen only // during devlpmt of DotNetZip itself, but there are rare // occasions when they occur in other cases. string sourceFile = GenerateTempPathname(tmpDir, "cs"); // // debugging: enumerate the resources in this assembly // Console.WriteLine("Resources in this assembly:"); // foreach (string rsrc in a2.GetManifestResourceNames()) // { // Console.WriteLine(rsrc); // } // Console.WriteLine(); // all the source code is embedded in the DLL as a zip file. using (ZipFile zip = ZipFile.Read(a2.GetManifestResourceStream("Ionic.Zip.Resources.ZippedResources.zip"))) { // // debugging: enumerate the files in the embedded zip // Console.WriteLine("Entries in the embbedded zip:"); // foreach (ZipEntry entry in zip) // { // Console.WriteLine(entry.FileName); // } // Console.WriteLine(); unpackedResourceDir = GenerateTempPathname(tmpDir, "tmp"); if (String.IsNullOrEmpty(options.IconFile)) { // Use the ico file that is embedded into the Ionic.Zip // DLL itself. To do this we must unpack the icon to // the filesystem, in order to specify it on the cmdline // of csc.exe. This method will remove the unpacked // file later. System.IO.Directory.CreateDirectory(unpackedResourceDir); ZipEntry e = zip["zippedFile.ico"]; // Must not extract a readonly file - it will be impossible to // delete later. if ((e.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { e.Attributes ^= FileAttributes.ReadOnly; } e.Extract(unpackedResourceDir); nameOfIconFile = Path.Combine(unpackedResourceDir, "zippedFile.ico"); cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", nameOfIconFile); } else { cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", options.IconFile); } cp.OutputAssembly = stubExe; if (options.Flavor == SelfExtractorFlavor.WinFormsApplication) { cp.CompilerOptions += " /target:winexe"; } if (!String.IsNullOrEmpty(options.AdditionalCompilerSwitches)) { cp.CompilerOptions += " " + options.AdditionalCompilerSwitches; } if (String.IsNullOrEmpty(cp.CompilerOptions)) { cp.CompilerOptions = null; } if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0)) { if (!Directory.Exists(unpackedResourceDir)) { System.IO.Directory.CreateDirectory(unpackedResourceDir); } foreach (string re in settings.CopyThroughResources) { string filename = Path.Combine(unpackedResourceDir, re); ExtractResourceToFile(a2, re, filename); // add the file into the target assembly as an embedded resource cp.EmbeddedResources.Add(filename); } } // add the Ionic.Utils.Zip DLL as an embedded resource cp.EmbeddedResources.Add(a1.Location); // file header sb.Append("// " + Path.GetFileName(sourceFile) + "\n") .Append("// --------------------------------------------\n//\n") .Append("// This SFX source file was generated by DotNetZip ") .Append(ZipFile.LibraryVersion.ToString()) .Append("\n// at ") .Append(System.DateTime.Now.ToString("yyyy MMMM dd HH:mm:ss")) .Append("\n//\n// --------------------------------------------\n\n\n"); // assembly attributes if (!String.IsNullOrEmpty(options.Description)) { sb.Append("[assembly: System.Reflection.AssemblyTitle(\"" + options.Description.Replace("\"", "") + "\")]\n"); } else { sb.Append("[assembly: System.Reflection.AssemblyTitle(\"DotNetZip SFX Archive\")]\n"); } if (!String.IsNullOrEmpty(options.ProductVersion)) { sb.Append("[assembly: System.Reflection.AssemblyInformationalVersion(\"" + options.ProductVersion.Replace("\"", "") + "\")]\n"); } // workitem string copyright = (String.IsNullOrEmpty(options.Copyright)) ? "Extractor: Copyright © Dino Chiesa 2008-2011" : options.Copyright.Replace("\"", ""); if (!String.IsNullOrEmpty(options.ProductName)) { sb.Append("[assembly: System.Reflection.AssemblyProduct(\"") .Append(options.ProductName.Replace("\"", "")) .Append("\")]\n"); } else { sb.Append("[assembly: System.Reflection.AssemblyProduct(\"DotNetZip\")]\n"); } sb.Append("[assembly: System.Reflection.AssemblyCopyright(\"" + copyright + "\")]\n") .Append(String.Format("[assembly: System.Reflection.AssemblyVersion(\"{0}\")]\n", ZipFile.LibraryVersion.ToString())); if (options.FileVersion != null) { sb.Append(String.Format("[assembly: System.Reflection.AssemblyFileVersion(\"{0}\")]\n", options.FileVersion.ToString())); } sb.Append("\n\n\n"); // Set the default extract location if it is available string extractLoc = options.DefaultExtractDirectory; if (extractLoc != null) { // remove double-quotes and replace slash with double-slash. // This, because the value is going to be embedded into a // cs file as a quoted string, and it needs to be escaped. extractLoc = extractLoc.Replace("\"", "").Replace("\\", "\\\\"); } string postExCmdLine = options.PostExtractCommandLine; if (postExCmdLine != null) { postExCmdLine = postExCmdLine.Replace("\\", "\\\\"); postExCmdLine = postExCmdLine.Replace("\"", "\\\""); } foreach (string rc in settings.ResourcesToCompile) { using (Stream s = zip[rc].OpenReader()) { if (s == null) { throw new ZipException(String.Format("missing resource '{0}'", rc)); } using (StreamReader sr = new StreamReader(s)) { while (sr.Peek() >= 0) { string line = sr.ReadLine(); if (extractLoc != null) { line = line.Replace("@@EXTRACTLOCATION", extractLoc); } line = line.Replace("@@REMOVE_AFTER_EXECUTE", options.RemoveUnpackedFilesAfterExecute.ToString()); line = line.Replace("@@QUIET", options.Quiet.ToString()); if (!String.IsNullOrEmpty(options.SfxExeWindowTitle)) { line = line.Replace("@@SFX_EXE_WINDOW_TITLE", options.SfxExeWindowTitle); } line = line.Replace("@@EXTRACT_EXISTING_FILE", ((int)options.ExtractExistingFile).ToString()); if (postExCmdLine != null) { line = line.Replace("@@POST_UNPACK_CMD_LINE", postExCmdLine); } sb.Append(line).Append("\n"); } } sb.Append("\n\n"); } } } string LiteralSource = sb.ToString(); #if DEBUGSFX // for debugging only string sourceModule = GenerateTempPathname(tmpDir, "cs"); using (StreamWriter sw = File.CreateText(sourceModule)) { sw.Write(LiteralSource); } Console.WriteLine("source: {0}", sourceModule); #endif var cr = csharp.CompileAssemblyFromSource(cp, LiteralSource); if (cr == null) { throw new SfxGenerationException("Cannot compile the extraction logic!"); } if (Verbose) { foreach (string output in cr.Output) { StatusMessageTextWriter.WriteLine(output); } } if (cr.Errors.Count != 0) { using (var sourceFileStream = new FileStream(sourceFile, FileMode.Create)) using (TextWriter tw = new StreamWriter(sourceFileStream)) { // first, the source we compiled tw.Write(LiteralSource); // now, append the compile errors tw.Write("\n\n\n// ------------------------------------------------------------------\n"); tw.Write("// Errors during compilation: \n//\n"); string p = Path.GetFileName(sourceFile); foreach (System.CodeDom.Compiler.CompilerError error in cr.Errors) { tw.Write(String.Format("// {0}({1},{2}): {3} {4}: {5}\n//\n", p, // 0 error.Line, // 1 error.Column, // 2 error.IsWarning ? "Warning" : "error", // 3 error.ErrorNumber, // 4 error.ErrorText)); // 5 } } throw new SfxGenerationException(String.Format("Errors compiling the extraction logic! {0}", sourceFile)); } OnSaveEvent(ZipProgressEventType.Saving_AfterCompileSelfExtractor); // Now, copy the resulting EXE image to the _writestream. // Because this stub exe is being saved first, the effect will be to // concatenate the exe and the zip data together. using (System.IO.Stream input = System.IO.File.OpenRead(stubExe)) { byte[] buffer = new byte[4000]; int n = 1; while (n != 0) { n = input.Read(buffer, 0, buffer.Length); if (n != 0) { WriteStream.Write(buffer, 0, n); } } } } OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); } finally { try { if (Directory.Exists(unpackedResourceDir)) { try { Directory.Delete(unpackedResourceDir, true); } catch (System.IO.IOException exc1) { StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); } } if (File.Exists(stubExe)) { try { File.Delete(stubExe); } catch (System.IO.IOException exc1) { StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); } } } catch (System.IO.IOException) { } } return; }
private void _SaveSfxStub(string exeToGenerate, SelfExtractorSaveOptions options) { string nameOfIconFile = null; string stubExe = null; string unpackedResourceDir = null; string tmpDir = null; try { if (File.Exists(exeToGenerate)) { if (Verbose) StatusMessageTextWriter.WriteLine("The existing file ({0}) will be overwritten.", exeToGenerate); } if (!exeToGenerate.EndsWith(".exe")) { if (Verbose) StatusMessageTextWriter.WriteLine("Warning: The generated self-extracting file will not have an .exe extension."); } // workitem 10553 tmpDir = TempFileFolder ?? Path.GetDirectoryName(exeToGenerate); stubExe = GenerateTempPathname(tmpDir, "exe"); // get the Ionic.Zip assembly Assembly a1 = typeof(ZipFile).Assembly; using (var csharp = new Microsoft.CSharp.CSharpCodeProvider (new Dictionary<string,string>() { { "CompilerVersion", "v2.0" } })) { // The following is a perfect opportunity for a linq query, but // I cannot use it. DotNetZip needs to run on .NET 2.0, // and using LINQ would break that. Here's what it would look // like: // // var settings = (from x in SettingsList // where x.Flavor == flavor // select x).First(); ExtractorSettings settings = null; foreach (var x in SettingsList) { if (x.Flavor == options.Flavor) { settings = x; break; } } // sanity check; should never happen if (settings == null) throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", options.Flavor)); // This is the list of referenced assemblies. Ionic.Zip is // needed here. Also if it is the winforms (gui) extractor, we // need other referenced assemblies, like // System.Windows.Forms.dll, etc. var cp = new System.CodeDom.Compiler.CompilerParameters(); cp.ReferencedAssemblies.Add(a1.Location); if (settings.ReferencedAssemblies != null) foreach (string ra in settings.ReferencedAssemblies) cp.ReferencedAssemblies.Add(ra); cp.GenerateInMemory = false; cp.GenerateExecutable = true; cp.IncludeDebugInformation = false; cp.CompilerOptions = ""; Assembly a2 = Assembly.GetExecutingAssembly(); // Use this to concatenate all the source code resources into a // single module. var sb = new System.Text.StringBuilder(); // In case there are compiler errors later, we allocate a source // file name now. If errors are detected, we'll spool the source // code as well as the errors (in comments) into that filename, // and throw an exception with the filename. Makes it easier to // diagnose. This should be rare; most errors happen only // during devlpmt of DotNetZip itself, but there are rare // occasions when they occur in other cases. string sourceFile = GenerateTempPathname(tmpDir, "cs"); // // debugging: enumerate the resources in this assembly // Console.WriteLine("Resources in this assembly:"); // foreach (string rsrc in a2.GetManifestResourceNames()) // { // Console.WriteLine(rsrc); // } // Console.WriteLine(); // all the source code is embedded in the DLL as a zip file. using (ZipFile zip = ZipFile.Read(a2.GetManifestResourceStream("Ionic.Zip.Resources.ZippedResources.zip"))) { // // debugging: enumerate the files in the embedded zip // Console.WriteLine("Entries in the embbedded zip:"); // foreach (ZipEntry entry in zip) // { // Console.WriteLine(entry.FileName); // } // Console.WriteLine(); unpackedResourceDir = GenerateTempPathname(tmpDir, "tmp"); if (String.IsNullOrEmpty(options.IconFile)) { // Use the ico file that is embedded into the Ionic.Zip // DLL itself. To do this we must unpack the icon to // the filesystem, in order to specify it on the cmdline // of csc.exe. This method will remove the unpacked // file later. System.IO.Directory.CreateDirectory(unpackedResourceDir); ZipEntry e = zip["zippedFile.ico"]; // Must not extract a readonly file - it will be impossible to // delete later. if ((e.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) e.Attributes ^= FileAttributes.ReadOnly; e.Extract(unpackedResourceDir); nameOfIconFile = Path.Combine(unpackedResourceDir, "zippedFile.ico"); cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", nameOfIconFile); } else cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", options.IconFile); cp.OutputAssembly = stubExe; if (options.Flavor == SelfExtractorFlavor.WinFormsApplication) cp.CompilerOptions += " /target:winexe"; if (!String.IsNullOrEmpty(options.AdditionalCompilerSwitches)) cp.CompilerOptions += " " + options.AdditionalCompilerSwitches; if (String.IsNullOrEmpty(cp.CompilerOptions)) cp.CompilerOptions = null; if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0)) { if (!Directory.Exists(unpackedResourceDir)) System.IO.Directory.CreateDirectory(unpackedResourceDir); foreach (string re in settings.CopyThroughResources) { string filename = Path.Combine(unpackedResourceDir, re); ExtractResourceToFile(a2, re, filename); // add the file into the target assembly as an embedded resource cp.EmbeddedResources.Add(filename); } } // add the Ionic.Utils.Zip DLL as an embedded resource cp.EmbeddedResources.Add(a1.Location); // file header sb.Append("// " + Path.GetFileName(sourceFile) + "\n") .Append("// --------------------------------------------\n//\n") .Append("// This SFX source file was generated by DotNetZip ") .Append(ZipFile.LibraryVersion.ToString()) .Append("\n// at ") .Append(System.DateTime.Now.ToString("yyyy MMMM dd HH:mm:ss")) .Append("\n//\n// --------------------------------------------\n\n\n"); // assembly attributes if (!String.IsNullOrEmpty(options.Description)) sb.Append("[assembly: System.Reflection.AssemblyTitle(\"" + options.Description.Replace("\"", "") + "\")]\n"); else sb.Append("[assembly: System.Reflection.AssemblyTitle(\"DotNetZip SFX Archive\")]\n"); if (!String.IsNullOrEmpty(options.ProductVersion)) sb.Append("[assembly: System.Reflection.AssemblyInformationalVersion(\"" + options.ProductVersion.Replace("\"", "") + "\")]\n"); // workitem string copyright = (String.IsNullOrEmpty(options.Copyright)) ? "Extractor: Copyright © Dino Chiesa 2008-2011" : options.Copyright.Replace("\"", ""); if (!String.IsNullOrEmpty(options.ProductName)) sb.Append("[assembly: System.Reflection.AssemblyProduct(\"") .Append(options.ProductName.Replace("\"", "")) .Append("\")]\n"); else sb.Append("[assembly: System.Reflection.AssemblyProduct(\"DotNetZip\")]\n"); sb.Append("[assembly: System.Reflection.AssemblyCopyright(\"" + copyright + "\")]\n") .Append(String.Format("[assembly: System.Reflection.AssemblyVersion(\"{0}\")]\n", ZipFile.LibraryVersion.ToString())); if (options.FileVersion != null) sb.Append(String.Format("[assembly: System.Reflection.AssemblyFileVersion(\"{0}\")]\n", options.FileVersion.ToString())); sb.Append("\n\n\n"); // Set the default extract location if it is available string extractLoc = options.DefaultExtractDirectory; if (extractLoc != null) { // remove double-quotes and replace slash with double-slash. // This, because the value is going to be embedded into a // cs file as a quoted string, and it needs to be escaped. extractLoc = extractLoc.Replace("\"", "").Replace("\\", "\\\\"); } string postExCmdLine = options.PostExtractCommandLine; if (postExCmdLine != null) { postExCmdLine = postExCmdLine.Replace("\\", "\\\\"); postExCmdLine = postExCmdLine.Replace("\"", "\\\""); } foreach (string rc in settings.ResourcesToCompile) { using (Stream s = zip[rc].OpenReader()) { if (s == null) throw new ZipException(String.Format("missing resource '{0}'", rc)); using (StreamReader sr = new StreamReader(s)) { while (sr.Peek() >= 0) { string line = sr.ReadLine(); if (extractLoc != null) line = line.Replace("@@EXTRACTLOCATION", extractLoc); line = line.Replace("@@REMOVE_AFTER_EXECUTE", options.RemoveUnpackedFilesAfterExecute.ToString()); line = line.Replace("@@QUIET", options.Quiet.ToString()); if (!String.IsNullOrEmpty(options.SfxExeWindowTitle)) line = line.Replace("@@SFX_EXE_WINDOW_TITLE", options.SfxExeWindowTitle); line = line.Replace("@@EXTRACT_EXISTING_FILE", ((int)options.ExtractExistingFile).ToString()); if (postExCmdLine != null) line = line.Replace("@@POST_UNPACK_CMD_LINE", postExCmdLine); sb.Append(line).Append("\n"); } } sb.Append("\n\n"); } } } string LiteralSource = sb.ToString(); #if DEBUGSFX // for debugging only string sourceModule = GenerateTempPathname(tmpDir, "cs"); using (StreamWriter sw = File.CreateText(sourceModule)) { sw.Write(LiteralSource); } Console.WriteLine("source: {0}", sourceModule); #endif var cr = csharp.CompileAssemblyFromSource(cp, LiteralSource); if (cr == null) throw new SfxGenerationException("Cannot compile the extraction logic!"); if (Verbose) foreach (string output in cr.Output) StatusMessageTextWriter.WriteLine(output); if (cr.Errors.Count != 0) { using (TextWriter tw = new StreamWriter(sourceFile)) { // first, the source we compiled tw.Write(LiteralSource); // now, append the compile errors tw.Write("\n\n\n// ------------------------------------------------------------------\n"); tw.Write("// Errors during compilation: \n//\n"); string p = Path.GetFileName(sourceFile); foreach (System.CodeDom.Compiler.CompilerError error in cr.Errors) { tw.Write(String.Format("// {0}({1},{2}): {3} {4}: {5}\n//\n", p, // 0 error.Line, // 1 error.Column, // 2 error.IsWarning ? "Warning" : "error", // 3 error.ErrorNumber, // 4 error.ErrorText)); // 5 } } throw new SfxGenerationException(String.Format("Errors compiling the extraction logic! {0}", sourceFile)); } OnSaveEvent(ZipProgressEventType.Saving_AfterCompileSelfExtractor); // Now, copy the resulting EXE image to the _writestream. // Because this stub exe is being saved first, the effect will be to // concatenate the exe and the zip data together. using (System.IO.Stream input = System.IO.File.OpenRead(stubExe)) { byte[] buffer = new byte[4000]; int n = 1; while (n != 0) { n = input.Read(buffer, 0, buffer.Length); if (n != 0) WriteStream.Write(buffer, 0, n); } } } OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); } finally { try { if (Directory.Exists(unpackedResourceDir)) { try { Directory.Delete(unpackedResourceDir, true); } catch (System.IO.IOException exc1) { StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); } } if (File.Exists(stubExe)) { try { File.Delete(stubExe); } catch (System.IO.IOException exc1) { StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); } } } catch (System.IO.IOException) { } } return; }
/// <summary> /// Saves the ZipFile instance to a self-extracting zip archive, using /// the specified save options. /// </summary> /// /// <remarks> /// <para> /// This method saves a self extracting archive, using the specified save /// options. These options include the flavor of the SFX, the default extract /// directory, the icon file, and so on. See the documentation /// for <see cref="SaveSelfExtractor(string , SelfExtractorFlavor)"/> for more /// details. /// </para> /// /// <para> /// The user who runs the SFX will have the opportunity to change the extract /// directory before extracting. If at the time of extraction, the specified /// directory does not exist, the SFX will create the directory before /// extracting the files. /// </para> /// /// </remarks> /// /// <example> /// This example saves a WinForms-based self-extracting archive EXE that /// will use c:\ExtractHere as the default extract location. The C# code /// shows syntax for .NET 3.0, which uses an object initializer for /// the SelfExtractorOptions object. /// <code> /// string DirectoryPath = "c:\\Documents\\Project7"; /// using (ZipFile zip = new ZipFile()) /// { /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); /// zip.Comment = "This will be embedded into a self-extracting WinForms-based exe"; /// var options = new SelfExtractorOptions /// { /// Flavor = SelfExtractorFlavor.WinFormsApplication, /// DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere", /// PostExtractCommandLine = ExeToRunAfterExtract, /// SfxExeWindowTitle = "My Custom Window Title", /// RemoveUnpackedFilesAfterExecute = true /// }; /// zip.SaveSelfExtractor("archive.exe", options); /// } /// </code> /// <code lang="VB"> /// Dim DirectoryPath As String = "c:\Documents\Project7" /// Using zip As New ZipFile() /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) /// zip.Comment = "This will be embedded into a self-extracting console-based exe" /// Dim options As New SelfExtractorOptions() /// options.Flavor = SelfExtractorFlavor.WinFormsApplication /// options.DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere" /// options.PostExtractCommandLine = ExeToRunAfterExtract /// options.SfxExeWindowTitle = "My Custom Window Title" /// options.RemoveUnpackedFilesAfterExecute = True /// zip.SaveSelfExtractor("archive.exe", options) /// End Using /// </code> /// </example> /// /// <param name="exeToGenerate">The name of the EXE to generate.</param> /// <param name="options">provides the options for creating the /// Self-extracting archive.</param> public void SaveSelfExtractor(string exeToGenerate, SelfExtractorSaveOptions options) { // Save an SFX that is both an EXE and a ZIP. // Check for the case where we are re-saving a zip archive // that was originally instantiated with a stream. In that case, // the _name will be null. If so, we set _writestream to null, // which insures that we'll cons up a new WriteStream (with a filesystem // file backing it) in the Save() method. if (_name == null) _writestream = null; _SavingSfx = true; _name = exeToGenerate; if (Directory.Exists(_name)) throw new ZipException("Bad Directory", new System.ArgumentException("That name specifies an existing directory. Please specify a filename.", "exeToGenerate")); _contentsChanged = true; _fileAlreadyExists = File.Exists(_name); _SaveSfxStub(exeToGenerate, options); Save(); _SavingSfx = false; }
private void Convert() { string TargetName = ZipFileToConvert.Replace(".zip", ".exe"); Console.WriteLine("Converting file {0} to SFX {1}", ZipFileToConvert, TargetName); var options = new ReadOptions { StatusMessageWriter = System.Console.Out }; using (ZipFile zip = ZipFile.Read(ZipFileToConvert, options)) { zip.Comment = ZipComment; SelfExtractorSaveOptions sfxOptions = new SelfExtractorSaveOptions(); sfxOptions.Flavor = flavor; sfxOptions.DefaultExtractDirectory = ExtractDir; sfxOptions.PostExtractCommandLine = ExeOnUnpack; zip.SaveSelfExtractor(TargetName, sfxOptions ); } }
private bool ZipFiles() { try { Log.LogMessage(Resources.ZipCreating, ZipFileName); string directoryName = Path.GetDirectoryName(Path.GetFullPath(ZipFileName)); if (!Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); using (var zip = new ZipFile()) { if (!ParallelCompression) { zip.ParallelDeflateThreshold = -1; } zip.AlternateEncoding = System.Text.Encoding.Unicode; zip.AlternateEncodingUsage = ZipOption.AsNecessary; // make sure level in range ZipLevel = System.Math.Max(0, ZipLevel); ZipLevel = System.Math.Min(9, ZipLevel); zip.CompressionLevel = (CompressionLevel)ZipLevel; zip.UseZip64WhenSaving = Zip64 ? Zip64Option.AsNecessary: Zip64Option.Never; if (!string.IsNullOrEmpty(Password)) zip.Password = Password; if (string.Equals(Encryption, "PkzipWeak", StringComparison.OrdinalIgnoreCase)) zip.Encryption = EncryptionAlgorithm.PkzipWeak; else if (string.Equals(Encryption, "WinZipAes128", StringComparison.OrdinalIgnoreCase)) zip.Encryption = EncryptionAlgorithm.WinZipAes128; else if (string.Equals(Encryption, "WinZipAes256", StringComparison.OrdinalIgnoreCase)) zip.Encryption = EncryptionAlgorithm.WinZipAes256; else zip.Encryption = EncryptionAlgorithm.None; if (!string.IsNullOrEmpty(Comment)) zip.Comment = Comment; foreach (ITaskItem fileItem in Files) { string name = fileItem.ItemSpec; string directoryPathInArchive; // clean up name if (Flatten) directoryPathInArchive = string.Empty; else if (!string.IsNullOrEmpty(WorkingDirectory)) directoryPathInArchive = GetPath(name, WorkingDirectory); else directoryPathInArchive = null; if (!File.Exists(name)) { // maybe a directory if (Directory.Exists(name)) { var directoryEntry = zip.AddDirectory(name, directoryPathInArchive); if (!Quiet) Log.LogMessage(Resources.ZipAdded, directoryEntry.FileName); continue; } Log.LogWarning(Resources.FileNotFound, name); continue; } //remove file name if (!string.IsNullOrEmpty(directoryPathInArchive) && Path.GetFileName(directoryPathInArchive) == Path.GetFileName(name)) directoryPathInArchive = Path.GetDirectoryName(directoryPathInArchive); var entry = zip.AddFile(name, directoryPathInArchive); if (!Quiet) Log.LogMessage(Resources.ZipAdded, entry.FileName); } if (SelfExtracting) { var options = new SelfExtractorSaveOptions { AdditionalCompilerSwitches = AdditionalCompilerSwitches, Copyright = Copyright, DefaultExtractDirectory = DefaultExtractDirectory, Description = Description, ExtractExistingFile = (ExtractExistingFileAction) ExtractExistingFileAction, Flavor = ConsoleSelfExtractor ? SelfExtractorFlavor.ConsoleApplication : SelfExtractorFlavor.WinFormsApplication, IconFile = IconFile, PostExtractCommandLine = PostExtractCommandLine, ProductName = ProductName, ProductVersion = ProductVersion, Quiet = QuietExtraction, RemoveUnpackedFilesAfterExecute = RemoveUnpackedFilesAfterExecute, SfxExeWindowTitle = SelfExtractingArchiveWindowTitle }; if (!string.IsNullOrWhiteSpace(FileVersion)) { options.FileVersion = new System.Version(FileVersion); } zip.SaveSelfExtractor(ZipFileName, options); } else { zip.Save(ZipFileName); } Log.LogMessage(Resources.ZipSuccessfully, ZipFileName); } } catch (Exception exc) { Log.LogErrorFromException(exc); return false; } return true; }
public void SFX_RemoveFilesAfterUnpack_wi10682() { string subdir = "files"; string[] filesToZip; Dictionary<string, byte[]> checksums; CreateFilesAndChecksums(subdir, out filesToZip, out checksums); string password = Path.GetFileNameWithoutExtension(Path.GetRandomFileName()); string postExeFormat = "post-extract-{0:D4}.exe"; string postExtractExe = String.Format(postExeFormat, _rnd.Next(10000)); CompileApp(0, postExtractExe); // pass 1 to run SFX and verify files are present; // pass 2 to run SFX and verify that it deletes files after extracting. // 2 passes: one for no cmd line overload, one with overload of -r+/-r- for (int j=0; j < 2; j++) { // 2 passes: with RemoveUnpackedFiles set or unset for (int k=0; k < 2; k++) { string sfxFileToCreate = String.Format("SFX_RemoveFilesAfterUnpack.{0}.{1}.exe",j,k); using (ZipFile zip = new ZipFile()) { zip.Password = password; zip.Encryption = Ionic.Zip.EncryptionAlgorithm.WinZipAes256; Array.ForEach(filesToZip, x => { zip.AddFile(x, "files");}); zip.AddFile(postExtractExe, "files"); var sfxOptions = new SelfExtractorSaveOptions { Flavor = SelfExtractorFlavor.ConsoleApplication, Quiet = true, PostExtractCommandLine = Path.Combine("files",postExtractExe) }; if (k==1) sfxOptions.RemoveUnpackedFilesAfterExecute = true; zip.SaveSelfExtractor(sfxFileToCreate, sfxOptions); } string extractDir = String.Format("extract.{0}.{1}",j,k); string sfxCmdLineArgs = String.Format("-p {0} -d {1}", password, extractDir); if (j==1) { // override the option set at time of zip.SaveSfx() sfxCmdLineArgs += (k==0) ? " -r+" : " -r-"; } // invoke the SFX this.Exec(sfxFileToCreate, sfxCmdLineArgs, true, true); if (k==j) { // verify that the files are extracted, and match VerifyChecksums(Path.Combine(extractDir, "files"), filesToZip, checksums); } else { // verify that no files exist in the extract directory var remainingFiles = Directory.GetFiles(extractDir); Assert.IsTrue(remainingFiles.Length == 0); } } } }
public void _Internal_SelfExtractor_Command(string cmdFormat, SelfExtractorFlavor flavor, bool runSfx, bool quiet, bool forceNoninteractive, bool wantArgs) { TestContext.WriteLine("=============================="); TestContext.WriteLine("SFX_RunOnExit({0})", flavor.ToString()); //int entriesAdded = 0; //String filename = null; string postExtractExe = String.Format(cmdFormat, _rnd.Next(3000)); // If WinForms and want forceNoninteractive, have the post-extract-exe return 0, // else, select a random number. int expectedReturnCode = (forceNoninteractive && flavor == SelfExtractorFlavor.WinFormsApplication) ? 0 : _rnd.Next(1024) + 20; TestContext.WriteLine("The post-extract command ({0}) will return {1}", postExtractExe, expectedReturnCode); string subdir = "A"; string[] filesToZip; Dictionary<string, byte[]> checksums; CreateFilesAndChecksums(subdir, out filesToZip, out checksums); for (int k = 0; k < 2; k++) { string readmeString = String.Format("Hey! This zipfile entry was created directly from " + "a string in application code. Flavor ({0}) Trial({1})", flavor.ToString(), k); string exeFileToCreate = String.Format("SFX_Command.{0}.{1}.exe", flavor.ToString(), k); TestContext.WriteLine("----------------------"); TestContext.WriteLine("Trial {0}", k); string unpackDir = String.Format("unpack.{0}", k); var sw = new System.IO.StringWriter(); using (ZipFile zip = new ZipFile()) { zip.StatusMessageTextWriter = sw; zip.AddDirectory(subdir, subdir); // Path.GetFileName(subdir)); zip.Comment = String.Format("Trial options: fl({0}) cmd ({3})\r\n"+ "actuallyRun({1})\r\nquiet({2})\r\n"+ "exists? {4}\r\nexpected rc={5}", flavor, runSfx, quiet, postExtractExe, k!=0, expectedReturnCode ); var ms1 = new MemoryStream(Encoding.UTF8.GetBytes(readmeString)); zip.AddEntry("Readme.txt", ms1); if (k != 0) { CompileApp(expectedReturnCode, postExtractExe); zip.AddFile(postExtractExe); } var sfxOptions = new SelfExtractorSaveOptions { Flavor = flavor, DefaultExtractDirectory = unpackDir, SfxExeWindowTitle = "Custom SFX Title " + DateTime.Now.ToString("G"), Quiet = quiet }; // In the case of k==0, this exe does not exist. It will result in // a return code of 5. In k == 1, the exe exists and will succeed. if (postExtractExe.Contains(' ')) sfxOptions.PostExtractCommandLine= "\"" + postExtractExe + "\""; else sfxOptions.PostExtractCommandLine= postExtractExe; if (wantArgs) sfxOptions.PostExtractCommandLine += " arg1 arg2"; zip.SaveSelfExtractor(exeFileToCreate, sfxOptions); } TestContext.WriteLine("status output: " + sw.ToString()); if (k != 0) File.Delete(postExtractExe); // Run the generated Self-extractor, conditionally. // // We always run, unless specifically asked not to, OR if it's a // winforms app and we want it to be noninteractive and there's no // EXE to run. If we try running a non-existent app, it will pop an // error message, hence user interaction, which we need to avoid for // the automated test. if (runSfx && (k != 0 || !forceNoninteractive || flavor != SelfExtractorFlavor.WinFormsApplication)) { TestContext.WriteLine("Running the SFX... "); System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(exeFileToCreate); psi.WorkingDirectory = TopLevelDir; psi.UseShellExecute = false; psi.CreateNoWindow = true; // false; System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi); process.WaitForExit(); int rc = process.ExitCode; TestContext.WriteLine("SFX exit code: ({0})", rc); // The exit code is returned only if it's a console SFX. if (flavor == SelfExtractorFlavor.ConsoleApplication) { // The program actually runs if k != 0 if (k == 0) { // The file to execute should not have been found, hence rc==5. Assert.AreEqual<Int32> (5, rc, "In trial {0}, the exit code was unexpected.", k); } else { // The file to execute should have returned a specific code. Assert.AreEqual<Int32> (expectedReturnCode, rc, "In trial {0}, the exit code did not match.", k); } } else Assert.AreEqual<Int32>(0, rc, "In trial {0}, the exit code did not match.", k); VerifyChecksums(Path.Combine(unpackDir, "A"), filesToZip, checksums); } } }
public void SFX_WinForms() { string[] Passwords = { null, "12345" }; for (int k = 0; k < Passwords.Length; k++) { string exeFileToCreate = Path.Combine(TopLevelDir, String.Format("SFX_WinForms-{0}.exe", k)); string DesiredunpackDir = Path.Combine(TopLevelDir, String.Format("unpack{0}", k)); String filename = null; string Subdir = Path.Combine(TopLevelDir, String.Format("A{0}", k)); Directory.CreateDirectory(Subdir); var checksums = new Dictionary<string, string>(); int fileCount = _rnd.Next(10) + 10; for (int j = 0; j < fileCount; j++) { filename = Path.Combine(Subdir, String.Format("file{0:D3}.txt", j)); TestUtilities.CreateAndFillFileText(filename, _rnd.Next(34000) + 5000); var chk = TestUtilities.ComputeChecksum(filename); checksums.Add(filename, TestUtilities.CheckSumToString(chk)); } using (ZipFile zip = new ZipFile()) { zip.Password = Passwords[k]; zip.AddDirectory(Subdir, Path.GetFileName(Subdir)); zip.Comment = "For testing purposes, please extract to: " + DesiredunpackDir; if (Passwords[k] != null) zip.Comment += String.Format("\r\n\r\nThe password for all entries is: {0}\n", Passwords[k]); var sfxOptions = new SelfExtractorSaveOptions { Flavor = Ionic.Zip.SelfExtractorFlavor.WinFormsApplication, // workitem 12608 SfxExeWindowTitle = "Custom SFX Title " + DateTime.Now.ToString("G"), DefaultExtractDirectory = DesiredunpackDir }; zip.SaveSelfExtractor(exeFileToCreate, sfxOptions); } // run the self-extracting EXE we just created System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(exeFileToCreate); psi.Arguments = DesiredunpackDir; psi.WorkingDirectory = TopLevelDir; psi.UseShellExecute = false; psi.CreateNoWindow = true; System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi); process.WaitForExit(); // now, compare the output in TargetDirectory with the original string DirToCheck = Path.Combine(DesiredunpackDir, String.Format("A{0}", k)); // verify the checksum of each file matches with its brother var fileList = Directory.GetFiles(DirToCheck); Assert.AreEqual<Int32>(checksums.Keys.Count, fileList.Length, "Trial {0}: Inconsistent results.", k); foreach (string fname in fileList) { string expectedCheckString = checksums[fname.Replace(String.Format("\\unpack{0}", k), "")]; string actualCheckString = TestUtilities.CheckSumToString(TestUtilities.ComputeChecksum(fname)); Assert.AreEqual<String>(expectedCheckString, actualCheckString, "Trial {0}: Unexpected checksum on extracted filesystem file ({1}).", k, fname); } } }
public void SFX_Console() { string exeFileToCreate = Path.Combine(TopLevelDir, "SFX_Console.exe"); string unpackDir = Path.Combine(TopLevelDir, "unpack"); string readmeString = "Hey there! This zipfile entry was created directly from a string in application code."; int entriesAdded = 0; String filename = null; string Subdir = Path.Combine(TopLevelDir, "A"); Directory.CreateDirectory(Subdir); var checksums = new Dictionary<string, string>(); int fileCount = _rnd.Next(10) + 10; for (int j = 0; j < fileCount; j++) { filename = Path.Combine(Subdir, String.Format("file{0:D3}.txt", j)); TestUtilities.CreateAndFillFileText(filename, _rnd.Next(34000) + 5000); entriesAdded++; var chk = TestUtilities.ComputeChecksum(filename); checksums.Add(filename, TestUtilities.CheckSumToString(chk)); } using (ZipFile zip = new ZipFile()) { zip.AddDirectory(Subdir, Path.GetFileName(Subdir)); zip.Comment = "This will be embedded into a self-extracting exe"; MemoryStream ms1 = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(readmeString)); zip.AddEntry("Readme.txt", ms1); var sfxOptions = new SelfExtractorSaveOptions { Flavor = Ionic.Zip.SelfExtractorFlavor.ConsoleApplication, DefaultExtractDirectory = unpackDir }; zip.SaveSelfExtractor(exeFileToCreate, sfxOptions); } var psi = new System.Diagnostics.ProcessStartInfo(exeFileToCreate); psi.WorkingDirectory = TopLevelDir; psi.UseShellExecute = false; psi.CreateNoWindow = true; System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi); process.WaitForExit(); // now, compare the output in unpackDir with the original string DirToCheck = Path.Combine(unpackDir, "A"); // verify the checksum of each file matches with its brother foreach (string fname in Directory.GetFiles(DirToCheck)) { string originalName = fname.Replace("\\unpack", ""); if (checksums.ContainsKey(originalName)) { string expectedCheckString = checksums[originalName]; string actualCheckString = TestUtilities.CheckSumToString(TestUtilities.ComputeChecksum(fname)); Assert.AreEqual<String>(expectedCheckString, actualCheckString, "Unexpected checksum on extracted filesystem file ({0}).", fname); } else Assert.AreEqual<string>("Readme.txt", originalName); } }
private void SFX_Update(SelfExtractorFlavor flavor) { string sfxFileToCreate = Path.Combine(TopLevelDir, String.Format("SFX_Update{0}.exe", flavor.ToString())); string unpackDir = Path.Combine(TopLevelDir, "unpack"); if (Directory.Exists(unpackDir)) Directory.Delete(unpackDir, true); string readmeString = "Hey there! This zipfile entry was created directly from a string in application code."; // create a file and compute the checksum string Subdir = Path.Combine(TopLevelDir, "files"); Directory.CreateDirectory(Subdir); var checksums = new Dictionary<string, string>(); string filename = Path.Combine(Subdir, "file1.txt"); TestUtilities.CreateAndFillFileText(filename, _rnd.Next(34000) + 5000); var chk = TestUtilities.ComputeChecksum(filename); checksums.Add(filename.Replace(TopLevelDir + "\\", "").Replace('\\', '/'), TestUtilities.CheckSumToString(chk)); // create the SFX using (ZipFile zip1 = new ZipFile()) { zip1.AddFile(filename, Path.GetFileName(Subdir)); zip1.Comment = "This will be embedded into a self-extracting exe"; MemoryStream ms1 = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(readmeString)); zip1.AddEntry("Readme.txt", ms1); var sfxOptions = new SelfExtractorSaveOptions { Flavor = flavor, Quiet = true, DefaultExtractDirectory = unpackDir }; zip1.SaveSelfExtractor(sfxFileToCreate, sfxOptions); } // verify count Assert.AreEqual<int>(TestUtilities.CountEntries(sfxFileToCreate), 2, "The Zip file has the wrong number of entries."); // create another file filename = Path.Combine(Subdir, "file2.txt"); TestUtilities.CreateAndFillFileText(filename, _rnd.Next(34000) + 5000); chk = TestUtilities.ComputeChecksum(filename); checksums.Add(filename.Replace(TopLevelDir + "\\", "").Replace('\\', '/'), TestUtilities.CheckSumToString(chk)); string password = "******"; // update the SFX using (ZipFile zip1 = ZipFile.Read(sfxFileToCreate)) { zip1.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression; zip1.Encryption = EncryptionAlgorithm.WinZipAes256; zip1.Comment = "The password is: " + password; zip1.Password = password; zip1.AddFile(filename, Path.GetFileName(Subdir)); var sfxOptions = new SelfExtractorSaveOptions { Flavor = flavor, Quiet = true, DefaultExtractDirectory = unpackDir }; zip1.SaveSelfExtractor(sfxFileToCreate, sfxOptions); } // verify count Assert.AreEqual<int>(TestUtilities.CountEntries(sfxFileToCreate), 3, "The Zip file has the wrong number of entries."); // read the SFX TestContext.WriteLine("---------------Reading {0}...", sfxFileToCreate); using (ZipFile zip2 = ZipFile.Read(sfxFileToCreate)) { zip2.Password = password; //string extractDir = String.Format("extract{0}", j); foreach (var e in zip2) { TestContext.WriteLine(" Entry: {0} c({1}) u({2})", e.FileName, e.CompressedSize, e.UncompressedSize); e.Extract(unpackDir); if (!e.IsDirectory) { if (checksums.ContainsKey(e.FileName)) { filename = Path.Combine(unpackDir, e.FileName); string actualCheckString = TestUtilities.CheckSumToString(TestUtilities.ComputeChecksum(filename)); Assert.AreEqual<string>(checksums[e.FileName], actualCheckString, "Checksums for ({1}) do not match.", e.FileName); //TestContext.WriteLine(" Checksums match ({0}).\n", actualCheckString); } else { Assert.AreEqual<string>("Readme.txt", e.FileName); } } } } int N = (flavor == SelfExtractorFlavor.ConsoleApplication) ? 2 : 1; for (int j = 0; j < N; j++) { // run the SFX TestContext.WriteLine("Running the SFX... "); var psi = new System.Diagnostics.ProcessStartInfo(sfxFileToCreate); if (flavor == SelfExtractorFlavor.ConsoleApplication) { if (j == 0) psi.Arguments = "-o -p " + password; // overwrite else psi.Arguments = "-p " + password; } psi.WorkingDirectory = TopLevelDir; psi.UseShellExecute = false; psi.CreateNoWindow = true; System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi); process.WaitForExit(); int rc = process.ExitCode; TestContext.WriteLine("SFX exit code: ({0})", rc); if (j == 0) { Assert.AreEqual<Int32>(0, rc, "The exit code from the SFX was nonzero ({0}).", rc); } else { Assert.AreNotEqual<Int32>(0, rc, "The exit code from the SFX was zero ({0})."); } } // verify the unpacked files? }