Example #1
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);
                        }
                    }
                }
            }
        }
Example #2
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?
        }
Example #3
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?
        }
Example #4
0
        public void _Internal_SelfExtractor_Command(string cmdFormat,
                                                    SelfExtractorFlavor flavor,
                                                    bool runSfx,
                                                    bool quiet,
                                                    bool forceNoninteractive,
                                                    bool wantArgs)
        {
            TestContext.WriteLine("==============================");
            TestContext.WriteLine("SFX_RunOnExit({0})", flavor.ToString());

            //int entriesAdded = 0;
            //String filename = null;
            string postExtractExe = String.Format(cmdFormat, _rnd.Next(3000));

            // If WinForms and want forceNoninteractive, have the post-extract-exe return 0,
            // else, select a random number.
            int expectedReturnCode = (forceNoninteractive &&
                                      flavor == SelfExtractorFlavor.WinFormsApplication)
                ? 0
                : _rnd.Next(1024) + 20;
            TestContext.WriteLine("The post-extract command ({0}) will return {1}",
                                  postExtractExe, expectedReturnCode);

            string subdir = "A";
            string[] filesToZip;
            Dictionary<string, byte[]> checksums;
            CreateFilesAndChecksums(subdir, out filesToZip, out checksums);

            for (int k = 0; k < 2; k++)
            {
                string readmeString =
                    String.Format("Hey! This zipfile entry was created directly from " +
                                  "a string in application code. Flavor ({0}) Trial({1})",
                                  flavor.ToString(), k);
                string exeFileToCreate = String.Format("SFX_Command.{0}.{1}.exe",
                                                       flavor.ToString(), k);

                TestContext.WriteLine("----------------------");
                TestContext.WriteLine("Trial {0}", k);
                string unpackDir = String.Format("unpack.{0}", k);

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

                    var sfxOptions = new SelfExtractorSaveOptions
                    {
                        Flavor = flavor,
                        DefaultExtractDirectory = unpackDir,
                        SfxExeWindowTitle = "Custom SFX Title " + DateTime.Now.ToString("G"),
                        Quiet = quiet
                    };

                    // In the case of k==0, this exe does not exist.  It will result in
                    // a return code of 5.  In k == 1, the exe exists and will succeed.
                    if (postExtractExe.Contains(' '))
                        sfxOptions.PostExtractCommandLine= "\"" + postExtractExe + "\"";
                    else
                        sfxOptions.PostExtractCommandLine= postExtractExe;

                    if (wantArgs)
                        sfxOptions.PostExtractCommandLine += " arg1 arg2";

                    zip.SaveSelfExtractor(exeFileToCreate, sfxOptions);
                }

                TestContext.WriteLine("status output: " + sw.ToString());

                if (k != 0) File.Delete(postExtractExe);

                // Run the generated Self-extractor, conditionally.
                //
                // We always run, unless specifically asked not to, OR if it's a
                // winforms app and we want it to be noninteractive and there's no
                // EXE to run.  If we try running a non-existent app, it will pop an
                // error message, hence user interaction, which we need to avoid for
                // the automated test.
                if (runSfx &&
                    (k != 0 || !forceNoninteractive ||
                     flavor != SelfExtractorFlavor.WinFormsApplication))
                {
                    TestContext.WriteLine("Running the SFX... ");
                    System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(exeFileToCreate);
                    psi.WorkingDirectory = TopLevelDir;
                    psi.UseShellExecute = false;
                    psi.CreateNoWindow = true; // false;
                    System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi);
                    process.WaitForExit();
                    int rc = process.ExitCode;
                    TestContext.WriteLine("SFX exit code: ({0})", rc);

                    // The exit code is returned only if it's a console SFX.
                    if (flavor == SelfExtractorFlavor.ConsoleApplication)
                    {
                        // The program actually runs if k != 0
                        if (k == 0)
                        {
                            // The file to execute should not have been found, hence rc==5.
                            Assert.AreEqual<Int32>
                                (5, rc, "In trial {0}, the exit code was unexpected.", k);
                        }
                        else
                        {
                            // The file to execute should have returned a specific code.
                            Assert.AreEqual<Int32>
                                (expectedReturnCode, rc,
                                 "In trial {0}, the exit code did not match.", k);
                        }
                    }
                    else
                        Assert.AreEqual<Int32>(0, rc, "In trial {0}, the exit code did not match.", k);

                    VerifyChecksums(Path.Combine(unpackDir, "A"),
                                    filesToZip, checksums);
                }
            }
        }
        public void _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);
                }
            }
        }