Exemple #1
0
        //string _defaultExtractLocation;
        //string _postExtractCmdLine;
        //         string _SetDefaultLocationCode =
        //         "namespace OfficeOpenXml.Packaging.Ionic.Zip { internal 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>
        internal void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor)
        {
            SelfExtractorSaveOptions options = new SelfExtractorSaveOptions();

            options.Flavor = flavor;
            SaveSelfExtractor(exeToGenerate, options);
        }
Exemple #2
0
        /// <summary>
        /// Saves the ZipFile instance to a self-extracting zip archive, using the specified
        /// default extract directory, post-extract command, and icon.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method saves a self extracting archive, with a specified default
        /// extracting location, a command to run after extraction, and application
        /// icon.  Actually, the default extract directory applies only if the flavor is
        /// <see cref="SelfExtractorFlavor.WinFormsApplication"/>.  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 self-extracting archive that will use c:\ExtractHere as the default
        /// extract location.
        /// <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, "c:\\ExtractHere");
        /// }
        /// </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, "c:\ExtractHere");
        /// End Using
        /// </code>
        /// </example>
        ///
        /// <param name="exeToGenerate">The name of the EXE to generate.</param>
        /// <param name="flavor">Indicates whether a Winforms or Console self-extractor is desired.</param>
        /// <param name="defaultExtractDirectory">
        /// The default extract directory the user will see when running the self-extracting
        /// archive. Passing null (or Nothing in VB) here, if flavor is
        /// <c>SelfExtractorFlavor.WinFormsApplication</c>, will cause the Self Extractor to
        /// use the the user's personal directory (<see
        /// cref="Environment.SpecialFolder.Personal"/>) for the default extract location.
        /// Passing null when flavor is <c>SelfExtractorFlavor.ConsoleApplication</c> will
        /// cause the self-extractor to use the current directory for the default extract
        /// location; it will also be settable on the command line when the SFX is executed.
        /// </param>
        /// <param name ="postExtractCommandToExecute">
        /// The command to execute on the user's machine, after unpacking the archive. If the
        /// flavor is <c>SelfExtractorFlavor.ConsoleApplication</c>, then the SFX changes the
        /// current directory to the extract directory, and starts the post-extract command
        /// and waits for it to exit.  The exit code of the post-extract command line is
        /// returned as the exit code of the self-extractor exe.  A non-zero exit code is
        /// typically used to indicated a failure by the program. In the case of an SFX, a
        /// non-zero exit code may indicate a failure during extraction, OR, it may indicate a
        /// failure of the run-on-extract program if specified. There is no way to distinguish
        /// these conditions from the calling shell, aside from parsing output.  The GUI self
        /// extractor simply starts the post-extract command and exits; it does not wait for
        /// the command to exit first.
        /// </param>
        /// <param name ="iconFile">
        /// the name of a .ico file in the filesystem to use for the application icon
        /// </param>
        public void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor, string defaultExtractDirectory, string postExtractCommandToExecute, string iconFile)
        {
            // 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, flavor, defaultExtractDirectory, postExtractCommandToExecute, iconFile);

            Save();
            _SavingSfx = false;
        }
Exemple #3
0
        /// <summary>フォルダ以下を圧縮</summary>
        /// <param name="zipFileToCreate">圧縮ファイル名(zip、exe)</param>
        /// <param name="directoryToZip">圧縮対象フォルダ</param>
        /// <param name="selectionDlgt">ファイル選択デリゲード</param>
        /// <param name="selectionCriteriaInfo">ファイル選択基準情報</param>
        /// <param name="rootPathInArchive">書庫内ルートフォルダ</param>
        /// <param name="enc">エンコーディング</param>
        /// <param name="cyp">暗号化</param>
        /// <param name="zipPassword">パスワード</param>
        /// <param name="cmpLv">圧縮レベル</param>
        /// <param name="selfEx">書庫形式(zip形式はnullを指定)</param>
        public void CreateZipFromFolder(
            string zipFileToCreate,
            string directoryToZip,
            SelectionDelegate selectionDlgt,
            object selectionCriteriaInfo,
            string rootPathInArchive,
            Encoding enc,
            EncryptionAlgorithm cyp,
            string zipPassword,
            CompressionLevel cmpLv,
            SelfExtractorFlavor? selfEx)
        {
            #region ファイル選択基準

            // ファイル選択デリゲード
            if (selectionDlgt != null)
            {
                // 指定のデリゲード
                this._selectionDlgt = selectionDlgt;
                // ファイル選択基準情報
                this._selectionCriteriaInfo = selectionCriteriaInfo;
            }

            #endregion

            // ZipFileを取得
            ZipFile zip = this.GetZipFile(
                enc, cyp, zipPassword, cmpLv, selfEx);

            using (zip) // 使い終ったら「zip.Dispose」する。
            {
                //// ● フォルダのアーカイブ
                //zip.AddDirectory(directoryToZip, rootPathInArchive);

                // ● ファイルを個別に追加する(UOCにて実装)。
                this.CreateZipFromFolderRecursive(
                    zip, directoryToZip, rootPathInArchive);

                if (selfEx == null)
                {
                    // ZIPファイル
                    zip.Save(zipFileToCreate + ".zip");
                }
                else
                {
                    // 自動解凍書庫
                    zip.SaveSelfExtractor(
                        zipFileToCreate + ".exe",
                        (SelfExtractorFlavor)selfEx);
                }
            }
        }
Exemple #4
0
        /// <summary>ZipFileを取得</summary>
        /// <param name="enc">エンコーディング</param>
        /// <param name="cyp">暗号化</param>
        /// <param name="zipPassword">パスワード</param>
        /// <param name="cmpLv">圧縮レベル</param>
        /// <param name="selfEx">書庫形式(zip形式はnullを指定)</param>
        /// <returns>ZipFile</returns>
        protected ZipFile GetZipFile(
            Encoding enc,
            EncryptionAlgorithm cyp,
            string zipPassword,
            CompressionLevel cmpLv,
            SelfExtractorFlavor? selfEx)
        {
            // ZipFileの初期化
            ZipFile zip = null;
            if (enc == null) { zip = new ZipFile(); }
            else { zip = new ZipFile(enc); }
            zip = base.SetZipFile(zip, selfEx);

            // 圧縮方法の指定

            // 暗号化
            if (cyp != EncryptionAlgorithm.Unsupported)
            {
                // EncryptionAlgorithm.Unsupportedは設定不可能。
                zip.Encryption = cyp;

                // 解凍パスワード
                if (zipPassword == null || zipPassword == "")
                {
                    // null、空文字なので設定しない。
                    if (cyp != EncryptionAlgorithm.None)
                    { throw new ArgumentException(PublicExceptionMessage.ZIP_PASSWORD, "zipPassword"); }
                }
                else
                {
                    // null、空文字で無いので設定する。
                    zip.Password = zipPassword;
                }
            }

            // 圧縮レベル
            zip.CompressionLevel = cmpLv;

            return zip;
        }
Exemple #5
0
        /// <summary>フォルダ以下を圧縮</summary>
        /// <param name="zipFileToCreate">圧縮ファイル名(zip、exe)</param>
        /// <param name="directoryToZip">圧縮対象フォルダ</param>
        /// <param name="selectionCriteriaString">ファイル選択基準文字列</param>
        /// <param name="rootPathInArchive">書庫内ルートフォルダ</param>
        /// <param name="enc">エンコーディング</param>
        /// <param name="cyp">暗号化</param>
        /// <param name="zipPassword">パスワード</param>
        /// <param name="cmpLv">圧縮レベル</param>
        /// <param name="selfEx">書庫形式(zip形式はnullを指定)</param>
        public void CreateZipFromFolder(
            string zipFileToCreate,
            string directoryToZip,
            string selectionCriteriaString,
            string rootPathInArchive,
            Encoding enc,
            EncryptionAlgorithm cyp,
            string zipPassword,
            CompressionLevel cmpLv,
            SelfExtractorFlavor? selfEx)
        {
            // ZipFileを取得
            ZipFile zip = this.GetZipFile(
                enc, cyp, zipPassword, cmpLv, selfEx);

            using (zip)
            {
                // フィルタ条件を確認
                if (selectionCriteriaString == null || selectionCriteriaString == "")
                {
                    // ● フォルダのアーカイブ
                    zip.AddDirectory(directoryToZip, rootPathInArchive);
                }
                else
                {
                    // ● フォルダのアーカイブ
                    //    ファイルをフィルタして追加
                    //    selectionCriteriaがファイル選択基準文字列
                    zip.AddSelectedFiles(selectionCriteriaString, directoryToZip, rootPathInArchive, true);
                }

                if (selfEx == null)
                {
                    // ZIPファイル
                    zip.Save(zipFileToCreate + ".zip");
                }
                else
                {
                    // 自動解凍書庫
                    zip.SaveSelfExtractor(
                        zipFileToCreate + ".exe",
                        (SelfExtractorFlavor)selfEx);
                }
            }
        }
Exemple #6
0
        /// <summary>ZipFileを取得</summary>
        /// <param name="zip">ZipFile</param>
        /// <param name="selfEx">書庫形式(zip形式はnullを指定)</param>
        /// <returns>ZipFile</returns>
        protected ZipFile SetZipFile(ZipFile zip, SelfExtractorFlavor? selfEx)
        {
            // 状態ライタの指定
            this._statusMSGWriter = new StringWriter();
            zip.StatusMessageTextWriter = this._statusMSGWriter;

            // 各種ハンドラ指定
            zip.AddProgress += this._addProgress;
            zip.ExtractProgress += this._extractProgress;
            zip.ReadProgress += this._readProgress;
            zip.SaveProgress += this._saveProgress;
            zip.ZipError += this._zipError;

            // 4G以上のファイルがある時には、ZIP64を使用
            zip.UseZip64WhenSaving = Zip64Option.AsNecessary;

            // 必要に応じてUnicodeを使用
            // (自動解凍書庫の文字化け対策)
            if (selfEx != null)
            {
                zip.UseUnicodeAsNecessary = true;
            }

            // コメント付与
            zip.Comment = "Zipper @ Powered by DotNetZip";

            return zip;
        }
        /// <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.
        /// </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 normally stored in the directory pointed to by the TEMP environment
        /// variable, and they are removed upon successful completion of this method. 
        /// </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)
        {
            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.");
            }

            string TempZipFile = SfxSaveTemporary();

            if (TempZipFile == null)
                return; // cancelled

            // look for myself (ZipFile will be present in the Zip assembly)
            Assembly a1 = typeof(ZipFile).Assembly;
            //Console.WriteLine("DotNetZip assembly loc: {0}", a1.Location);

            Microsoft.CSharp.CSharpCodeProvider csharp = new Microsoft.CSharp.CSharpCodeProvider();

            // I'd like to do linq query, but the resulting image has to run on .NET 2.0!!
            // 	var settings = (from x in SettingsList
            // 			where x.Flavor == flavor
            // 			select x).First();

            ExtractorSettings settings = null;
            foreach (var x in SettingsList)
            {
                if (x.Flavor == flavor)
                {
                    settings = x;
                    break;
                }
            }

            if (settings == null)
                throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", flavor));

            // This is the list of referenced assemblies.  Zip is needed here.
            // Also if it is the winforms (gui) extractor, we need other referenced assemblies.
            System.CodeDom.Compiler.CompilerParameters 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.OutputAssembly = exeToGenerate;

            Assembly a2 = Assembly.GetExecutingAssembly();

            string TempDir = GenerateUniquePathname("tmp", null);
            if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0))
            {
                System.IO.Directory.CreateDirectory(TempDir);
                int n = 0;
                byte[] bytes = new byte[1024];
                foreach (string re in settings.CopyThroughResources)
                {
                    string filename = Path.Combine(TempDir, re);
                    using (Stream instream = a2.GetManifestResourceStream(re))
                    {
                        using (FileStream outstream = File.OpenWrite(filename))
                        {
                            do
                            {
                                n = instream.Read(bytes, 0, bytes.Length);
                                outstream.Write(bytes, 0, n);
                            } while (n > 0);
                        }
                    }
                    // add the embedded resource in our own assembly into the target assembly as an embedded resource
                    cp.EmbeddedResources.Add(filename);
                }
            }

            // add the zip file as an embedded resource
            cp.EmbeddedResources.Add(TempZipFile);

            // add the Zip DLL as an embedded resource
            cp.EmbeddedResources.Add(a1.Location);

            //Console.WriteLine("Resources in this assembly:");
            //foreach (string rsrc in a2.GetManifestResourceNames())
            //{
            //    Console.WriteLine(rsrc);
            //}
            //Console.WriteLine();

            //Console.WriteLine("reading source code resources:");
            // concatenate all the source code resources into a single module
            var sb = new System.Text.StringBuilder();
            foreach (string rc in settings.ResourcesToCompile)
            {
                //Console.WriteLine("  trying to read stream: ({0})", rc);
                Stream s = a2.GetManifestResourceStream(rc);
                using (StreamReader sr = new StreamReader(s))
                {
                    while (sr.Peek() >= 0)
                        sb.Append(sr.ReadLine()).Append("\n");
                }
                sb.Append("\n\n");
            }
            string LiteralSource = sb.ToString();

            System.CodeDom.Compiler.CompilerResults cr = csharp.CompileAssemblyFromSource(cp, LiteralSource);
            if (cr == null)
                throw new SfxGenerationException("Errors compiling the extraction logic!");

            foreach (string output in cr.Output)
                if (Verbose) StatusMessageTextWriter.WriteLine(output);

            if (cr.Errors.Count != 0)
                throw new SfxGenerationException("Errors compiling the extraction logic!");

            try
            {
                if (Directory.Exists(TempDir))
                {
                    try { Directory.Delete(TempDir, true); }
                    catch { }
                }

                if (File.Exists(TempZipFile))
                {
                    try { File.Delete(TempZipFile);}
                    catch { }
                }
            }
            catch { }

            if (Verbose) StatusMessageTextWriter.WriteLine("Created self-extracting zip file {0}.", cr.PathToAssembly);
            return;

            //       catch (Exception e1)
            //       {
            // 	StatusMessageTextWriter.WriteLine("****Exception: " + e1);
            // 	throw;
            //       }
            //       return;
        }
Exemple #8
0
        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?
        }
        /// <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.
        /// </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 SFX, the user's personal directory
        /// (<see cref="Environment.SpecialFolder.Personal"/>)
        /// will be used as the default extract location.
        /// The user who runs the SFX will have the opportunity to change the extract
        /// directory before extracting.
        /// </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)
        {
            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.");
                }
            }

            string TempZipFile = SfxSaveTemporary();

            OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

            if (TempZipFile == null)
            {
                return; // cancelled
            }
            // look for myself (ZipFile will be present in the Ionic.Utils.Zip assembly)
            Assembly a1 = typeof(ZipFile).Assembly;

            //Console.WriteLine("DotNetZip assembly loc: {0}", a1.Location);

            Microsoft.CSharp.CSharpCodeProvider csharp = new Microsoft.CSharp.CSharpCodeProvider();

            // Perfect opportunity for a linq query, but I cannot use it.
            // The DotNetZip library can compile into 2.0, but needs to run on .NET 2.0.
            // 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 == flavor)
                {
                    settings = x;
                    break;
                }
            }

            if (settings == null)
            {
                throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", flavor));
            }

            // This is the list of referenced assemblies.  Ionic.Utils.Zip is needed here.
            // Also if it is the winforms (gui) extractor, we need other referenced assemblies.
            System.CodeDom.Compiler.CompilerParameters 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.OutputAssembly          = exeToGenerate;

            Assembly a2 = Assembly.GetExecutingAssembly();

            string TempDir = GenerateUniquePathname("tmp", null);

            if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0))
            {
                System.IO.Directory.CreateDirectory(TempDir);
                int    n     = 0;
                byte[] bytes = new byte[1024];
                foreach (string re in settings.CopyThroughResources)
                {
                    string filename = Path.Combine(TempDir, re);
                    using (Stream instream = a2.GetManifestResourceStream(re))
                    {
                        using (FileStream outstream = File.OpenWrite(filename))
                        {
                            do
                            {
                                n = instream.Read(bytes, 0, bytes.Length);
                                outstream.Write(bytes, 0, n);
                            } while (n > 0);
                        }
                    }
                    // add the embedded resource in our own assembly into the target assembly as an embedded resource
                    cp.EmbeddedResources.Add(filename);
                }
            }

            // add the zip file as an embedded resource
            cp.EmbeddedResources.Add(TempZipFile);

            // add the Ionic.Utils.Zip DLL as an embedded resource
            cp.EmbeddedResources.Add(a1.Location);

            //Console.WriteLine("Resources in this assembly:");
            //foreach (string rsrc in a2.GetManifestResourceNames())
            //{
            //    Console.WriteLine(rsrc);
            //}
            //Console.WriteLine();

            //Console.WriteLine("reading source code resources:");


            // concatenate all the source code resources into a single module
            var sb = new System.Text.StringBuilder();

            // set the default extract location if it is available
            bool wantCodeReplace = (flavor == SelfExtractorFlavor.WinFormsApplication && _defaultExtractLocation != null);

            if (wantCodeReplace)
            {
                _defaultExtractLocation = _defaultExtractLocation.Replace("\"", "");
            }

            foreach (string rc in settings.ResourcesToCompile)
            {
                //Console.WriteLine("  trying to read stream: ({0})", rc);
                Stream s = a2.GetManifestResourceStream(rc);
                using (StreamReader sr = new StreamReader(s))
                {
                    while (sr.Peek() >= 0)
                    {
                        string line = sr.ReadLine();
                        if (wantCodeReplace)
                        {
                            line = line.Replace("@@VALUE", _defaultExtractLocation);
                        }
                        sb.Append(line).Append("\n");
                    }
                }
                sb.Append("\n\n");
            }

            string LiteralSource = sb.ToString();

            System.CodeDom.Compiler.CompilerResults 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)
            {
                throw new SfxGenerationException("Errors compiling the extraction logic!");
            }

            OnSaveEvent(ZipProgressEventType.Saving_AfterCompileSelfExtractor);

            try
            {
                if (Directory.Exists(TempDir))
                {
                    try { Directory.Delete(TempDir, true); }
                    catch { }
                }

                if (File.Exists(TempZipFile))
                {
                    try { File.Delete(TempZipFile); }
                    catch { }
                }
            }
            catch { }

            OnSaveCompleted();

            if (Verbose)
            {
                StatusMessageTextWriter.WriteLine("Created self-extracting zip file {0}.", cr.PathToAssembly);
            }
            return;


            //       catch (Exception e1)
            //       {
            //  StatusMessageTextWriter.WriteLine("****Exception: " + e1);
            //  throw;
            //       }
            //       return;
        }
Exemple #10
0
 /// <summary>
 /// Saves the ZipFile instance to a self-extracting zip archive, using the specified
 /// default extract directory, and a post-extract command to run.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method saves a self extracting archive, with a specified default
 /// extracting location, and a command to run after extraction.  Actually, the
 /// default extract directory applies only if the flavor is <see
 /// cref="SelfExtractorFlavor.WinFormsApplication"/>.  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 self-extracting archive that will use c:\ExtractHere as the default
 /// extract location.
 /// <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, "c:\\ExtractHere");
 /// }
 /// </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, "c:\ExtractHere");
 /// End Using
 /// </code>
 /// </example>
 ///
 /// <param name="exeToGenerate">The name of the EXE to generate.</param>
 /// <param name="flavor">Indicates whether a Winforms or Console self-extractor is desired.</param>
 /// <param name="defaultExtractDirectory">
 /// The default extract directory the user will see when running the self-extracting
 /// archive. Passing null (or Nothing in VB) here, if flavor is
 /// <c>SelfExtractorFlavor.WinFormsApplication</c>, will cause the Self Extractor to
 /// use the the user's personal directory (<see
 /// cref="Environment.SpecialFolder.Personal"/>) for the default extract location.
 /// Passing null when flavor is <c>SelfExtractorFlavor.ConsoleApplication</c> will
 /// cause the self-extractor to use the current directory for the default extract
 /// location; it will also be settable on the command line when the SFX is executed.
 /// </param>
 /// <param name ="postExtractCommandToExecute">
 /// The command to execute on the user's machine, after unpacking the archive. If the
 /// flavor is <c>SelfExtractorFlavor.ConsoleApplication</c>, then the SFX changes the
 /// current directory to the extract directory, and starts the post-extract command
 /// and waits for it to exit.  The exit code of the post-extract command line is
 /// returned as the exit code of the self-extractor exe.  A non-zero exit code is
 /// typically used to indicated a failure by the program. In the case of an SFX, a
 /// non-zero exit code may indicate a failure during extraction, OR, it may indicate a
 /// failure of the run-on-extract program if specified. There is no way to distinguish
 /// these conditions from the calling shell, aside from parsing output.  The GUI self
 /// extractor simply starts the post-extract command and exits; it does not wait for
 /// the command to exit first.
 /// </param>
 public void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor, string defaultExtractDirectory, string postExtractCommandToExecute)
 {
     SaveSelfExtractor(exeToGenerate, flavor, defaultExtractDirectory, postExtractCommandToExecute, null);
 }
Exemple #11
0
 /// <summary>
 /// Saves the ZipFile instance to a self-extracting zip archive, using the specified
 /// default extract directory.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method saves a self extracting archive, with a specified default extracting
 /// location.  Actually, the default extract directory applies only if the flavor is <see
 /// cref="SelfExtractorFlavor.WinFormsApplication"/>.  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 self-extracting archive that will use c:\ExtractHere as the default
 /// extract location.
 /// <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, "c:\\ExtractHere");
 /// }
 /// </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, "c:\ExtractHere");
 /// End Using
 /// </code>
 /// </example>
 ///
 /// <param name="exeToGenerate">The name of the EXE to generate.</param>
 /// <param name="flavor">Indicates whether a Winforms or Console self-extractor is desired.</param>
 /// <param name="defaultExtractDirectory">
 /// The default extract directory the user will see when running the self-extracting
 /// archive. Passing null (or Nothing in VB) here will cause the Self Extractor to
 /// use the the user's personal directory
 /// (<see cref="Environment.SpecialFolder.Personal"/>) for the default extract
 /// location.
 /// </param>
 public void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor, string defaultExtractDirectory)
 {
     SaveSelfExtractor(exeToGenerate, flavor, defaultExtractDirectory, null, null);
 }
Exemple #12
0
        //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"/>) will be used as the default extract
        /// location.  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)
        {
            SaveSelfExtractor(exeToGenerate, flavor, null, null, null);
        }
Exemple #13
0
        public void _Internal_SelfExtractor_Command(string cmdFormat,
                                                    SelfExtractorFlavor flavor,
                                                    bool runPostExtract,
                                                    bool quiet,
                                                    bool forceNoninteractive,
                                                    bool wantArgs)
        {
            TestContext.WriteLine("==============================");
            TestContext.WriteLine("SelfExtractor_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 = 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));
                TestContext.WriteLine("checksum({0})= ({1})", filename, checksums[filename]);
            }

            Directory.SetCurrentDirectory(TopLevelDir);
            for (int k = 0; k < 2; k++)
            {
                string ReadmeString = String.Format("Hey there!  This zipfile entry was created directly " +
                                                    "from a string in application code. Flavor ({0}) Trial({1})",
                                                    flavor.ToString(), k);
                string exeFileToCreate = Path.Combine(TopLevelDir,
                                                      String.Format("SelfExtractor_Command.{0}.{1}.exe",
                                                                    flavor.ToString(), k));
                TestContext.WriteLine("----------------------");
                TestContext.WriteLine("Trial {0}", k);
                string UnpackDirectory = String.Format("unpack.{0}", k);

                if (k != 0)
                {
                    CompileApp(expectedReturnCode, postExtractExe);
                }

                var sw = new System.IO.StringWriter();
                using (ZipFile zip = new ZipFile())
                {
                    zip.StatusMessageTextWriter = sw;
                    zip.AddDirectory(Subdir, Path.GetFileName(Subdir));
                    zip.Comment = String.Format("Trial options: flavor({0})  command: ({3})\r\n" +
                                                "actuallyRun({1})\r\nquiet({2})\r\n" +
                                                "exists? {4}\r\nexpected rc={5}",
                                                flavor,
                                                runPostExtract,
                                                quiet,
                                                postExtractExe,
                                                k != 0,
                                                expectedReturnCode
                                                );
                    MemoryStream ms1 = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(ReadmeString));
                    zip.AddEntry("Readme.txt", ms1);
                    if (k != 0)
                    {
                        zip.AddFile(postExtractExe);
                    }

                    SelfExtractorSaveOptions sfxOptions = new SelfExtractorSaveOptions();
                    sfxOptions.Flavor = flavor;
                    sfxOptions.DefaultExtractDirectory = UnpackDirectory;
                    sfxOptions.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 post-extract-exe, 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 (runPostExtract &&
                    (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 have returned a specific code.
                            Assert.AreEqual <Int32>(expectedReturnCode, rc, "In trial {0}, the exit code did not match.", k);
                        }
                        else
                        {
                            // 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
                    {
                        Assert.AreEqual <Int32>(0, rc, "In trial {0}, the exit code did not match.", k);
                    }



                    // now, compare the output in UnpackDirectory with the original
                    string DirToCheck = Path.Combine(TopLevelDir, Path.Combine(UnpackDirectory, "A"));
                    // verify the checksum of each file matches with its brother
                    foreach (string fname in Directory.GetFiles(DirToCheck))
                    {
                        string originalName = fname.Replace("\\" + UnpackDirectory, "");
                        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);
                        }
                    }
                }
            }
        }
Exemple #14
0
        private void SelfExtractor_Update(SelfExtractorFlavor flavor)
        {
            string SfxFileToCreate = Path.Combine(TopLevelDir,
                                                  String.Format("SelfExtractor_Update{0}.exe",
                                                                flavor.ToString()));
            string UnpackDirectory = Path.Combine(TopLevelDir, "unpack");

            if (Directory.Exists(UnpackDirectory))
            {
                Directory.Delete(UnpackDirectory, 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);
                SelfExtractorSaveOptions sfxOptions = new SelfExtractorSaveOptions();
                sfxOptions.Flavor = flavor;
                sfxOptions.Quiet  = true;
                sfxOptions.DefaultExtractDirectory = UnpackDirectory;
                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));
                SelfExtractorSaveOptions sfxOptions = new SelfExtractorSaveOptions();
                sfxOptions.Flavor = flavor;
                sfxOptions.Quiet  = true;
                sfxOptions.DefaultExtractDirectory = UnpackDirectory;
                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(UnpackDirectory);
                    if (!e.IsDirectory)
                    {
                        if (checksums.ContainsKey(e.FileName))
                        {
                            filename = Path.Combine(UnpackDirectory, 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?
        }
Exemple #15
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);
                }
            }
        }
        //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);
        }
//         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, using the specified
        /// default extract directory.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method saves a self extracting archive,
        /// with a specified default extracting location.  Actually, the
        /// default extract directory applies only if the flavor is
        ///  <see cref="SelfExtractorFlavor.WinFormsApplication"/>.
        /// 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>
        /// <param name="exeToGenerate">The name of the EXE to generate.</param>
        /// <param name="flavor">Indicates whether a Winforms or Console self-extractor is desired.</param>
        /// <param name="defaultExtractDirectory">
        /// The default extract directory the user will see when running the self-extracting
        /// archive. Passing null (or Nothing in VB) here will cause the Self Extractor to
        /// use the the user's personal directory
        /// (<see cref="Environment.SpecialFolder.Personal"/>) for the default extract
        /// location.
        /// </param>
        public void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor, string defaultExtractDirectory)
        {
            this._defaultExtractLocation = defaultExtractDirectory;
            SaveSelfExtractor(exeToGenerate, flavor);
            this._defaultExtractLocation = null;
        }
Exemple #18
0
        private void _SaveSfxStub(string exeToGenerate, SelfExtractorFlavor flavor, string defaultExtractLocation, string postExtractCmdLine, string nameOfIconFile)
        {
            bool   removeIconFile = false;
            string StubExe        = null;
            string TempDir        = 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.");
                    }
                }

                StubExe = GenerateTempPathname("exe", null);

                // get the Ionic.Zip assembly
                Assembly a1 = typeof(ZipFile).Assembly;

                Microsoft.CSharp.CSharpCodeProvider csharp = new Microsoft.CSharp.CSharpCodeProvider();

                // Perfect opportunity for a linq query, but I cannot use it.
                // The DotNetZip library can compile into 2.0, but needs to run on .NET 2.0.
                // 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 == flavor)
                    {
                        settings = x;
                        break;
                    }
                }

                if (settings == null)
                {
                    throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", 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.
                System.CodeDom.Compiler.CompilerParameters 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();

                if (nameOfIconFile == null)
                {
                    removeIconFile = true;
                    nameOfIconFile = GenerateTempPathname("ico", null);
                    ExtractResourceToFile(a2, "Ionic.Zip.Resources.zippedFile.ico", nameOfIconFile);
                    cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", nameOfIconFile);
                }
                else if (nameOfIconFile != "")
                {
                    cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", nameOfIconFile);
                }

                //cp.IncludeDebugInformation = true;
                cp.OutputAssembly = StubExe;
                if (flavor == SelfExtractorFlavor.WinFormsApplication)
                {
                    cp.CompilerOptions += " /target:winexe";
                }

                if (cp.CompilerOptions == "")
                {
                    cp.CompilerOptions = null;
                }

                TempDir = GenerateTempPathname("tmp", null);
                if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0))
                {
                    System.IO.Directory.CreateDirectory(TempDir);
                    foreach (string re in settings.CopyThroughResources)
                    {
                        string filename = Path.Combine(TempDir, 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);

                //Console.WriteLine("Resources in this assembly:");
                //foreach (string rsrc in a2.GetManifestResourceNames())
                //{
                //    Console.WriteLine(rsrc);
                //}
                //Console.WriteLine();

                //Console.WriteLine("reading source code resources:");


                // concatenate all the source code resources into a single module
                var sb = new System.Text.StringBuilder();

                // assembly attributes
                sb.Append("[assembly: System.Reflection.AssemblyTitle(\"DotNetZip SFX Archive\")]\n");
                sb.Append("[assembly: System.Reflection.AssemblyProduct(\"ZipLibrary\")]\n");
                sb.Append("[assembly: System.Reflection.AssemblyCopyright(\"Copyright © Dino Chiesa 2008, 2009\")]\n");
                sb.Append(String.Format("[assembly: System.Reflection.AssemblyVersion(\"{0}\")]\n\n", ZipFile.LibraryVersion.ToString()));


                // Set the default extract location if it is available, and if supported.

                bool haveLocation = (defaultExtractLocation != null);
                if (haveLocation)
                {
                    defaultExtractLocation = defaultExtractLocation.Replace("\"", "").Replace("\\", "\\\\");
                }

                foreach (string rc in settings.ResourcesToCompile)
                {
                    //Console.WriteLine("  trying to read stream: ({0})", rc);
                    Stream s = a2.GetManifestResourceStream(rc);
                    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 (haveLocation)
                            {
                                line = line.Replace("@@EXTRACTLOCATION", defaultExtractLocation);
                            }

                            if (postExtractCmdLine != null)
                            {
                                line = line.Replace("@@POST_UNPACK_CMD_LINE", postExtractCmdLine.Replace("\\", "\\\\"));
                            }

                            sb.Append(line).Append("\n");
                        }
                    }
                    sb.Append("\n\n");
                }

                string LiteralSource = sb.ToString();

                #if DEBUGSFX
                // for debugging only
                string sourceModule = GenerateTempPathname("cs", null);
                using (StreamWriter sw = File.CreateText(sourceModule))
                {
                    sw.Write(LiteralSource);
                }
                Console.WriteLine("source: {0}", sourceModule);
                #endif

                System.CodeDom.Compiler.CompilerResults 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)
                {
                    //Console.ReadLine();
                    string sourcefile = GenerateTempPathname("cs", null);
                    using (TextWriter tw = new StreamWriter(sourcefile))
                    {
                        tw.Write(LiteralSource);
                    }
                    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(TempDir))
                    {
                        try { Directory.Delete(TempDir, true); }
                        catch { }
                    }
                    if (File.Exists(StubExe))
                    {
                        try { File.Delete(StubExe); }
                        catch { }
                    }
                    if (removeIconFile && File.Exists(nameOfIconFile))
                    {
                        try { File.Delete(nameOfIconFile); }
                        catch { }
                    }
                }
                catch { }
            }

            return;
        }
        public ConvertZipToSfx(string[] args)
        {
            const string parameterDuplicated = "The parameter {0} is duplicated.";

            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i].ToLower())
                {
                case "-extractdir":
                    if (i >= args.Length - 1 || ExtractDir != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "'extractdir");
                        Usage();
                        return;
                    }
                    ExtractDir = args[++i];
                    break;

                case "-cmdline":
                    flavor = SelfExtractorFlavor.ConsoleApplication;
                    break;

                case "-comment":
                    if (i >= args.Length - 1 || ZipComment != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "comment");
                        Usage();
                        return;
                    }
                    ZipComment = args[++i];
                    break;

                case "-exeonunpack":
                    if (i >= args.Length - 1 || ExeOnUnpack != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "exeonunpack");
                        Usage();
                        return;
                    }
                    ExeOnUnpack = args[++i];
                    break;

                case "-description":
                    if (i >= args.Length - 1 || Description != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "description");
                        Usage();
                        return;
                    }
                    Description = args[++i];
                    break;

                case "-fileversion":
                    if (i >= args.Length - 1 || FileVersion != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "fileversion");
                        Usage();
                        return;
                    }
                    FileVersion = new Version(args[++i]);
                    break;

                case "-title":
                    if (i >= args.Length - 1 || Title != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "title");
                        Usage();
                        return;
                    }
                    Title = args[++i];
                    break;

                case "-iconfile":
                    if (i >= args.Length - 1 || IconFile != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "iconfile");
                        Usage();
                        return;
                    }
                    IconFile = args[++i];
                    break;

                case "-name":
                    if (i >= args.Length - 1 || Name != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "name");
                        Usage();
                        return;
                    }
                    Name = args[++i];
                    break;

                case "-version":
                    if (i >= args.Length - 1 || Version != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "version");
                        Usage();
                        return;
                    }
                    Version = args[++i];
                    break;

                case "-copyright":
                    if (i >= args.Length - 1 || Copyright != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "copyright");
                        Usage();
                        return;
                    }
                    Copyright = args[++i];
                    break;

                case "-compiler":
                    if (i >= args.Length - 1 || Compiler != null)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "compiler");
                        Usage();
                        return;
                    }
                    Compiler = args[++i];
                    break;

                case "-quiet":
                    if (i >= args.Length - 1 || Quiet == true)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "Quiet");
                        Usage();
                        return;
                    }
                    Quiet = true;
                    break;

                case "-remove":
                    if (i >= args.Length - 1 || Remove == true)
                    {
                        Console.Error.WriteLine(parameterDuplicated, "remove");
                        Usage();
                        return;
                    }
                    Remove = true;
                    break;

                case "-?":
                case "-help":
                    Usage();
                    return;

                default:
                    // positional args
                    if (ZipFileToConvert == null)
                    {
                        ZipFileToConvert = args[i];
                        targetName       = ZipFileToConvert.Replace(".zip", ".exe");
                    }
                    else
                    {
                        Usage();
                        return;
                    }
                    break;
                }
            }
        }
        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);
                }
            }
        }