| // ZipFile.saveSelfExtractor.cs | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // Copyright (c) 2008-2011 Dino Chiesa. | 
 | // All rights reserved. | 
 | // | 
 | // This code module is part of DotNetZip, a zipfile class library. | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // This code is licensed under the Microsoft Public License. | 
 | // See the file License.txt for the license details. | 
 | // More info on: http://dotnetzip.codeplex.com | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // last saved (in emacs): | 
 | // Time-stamp: <2011-August-10 19:22:46> | 
 | // | 
 | // ------------------------------------------------------------------ | 
 | // | 
 | // This is a the source module that implements the stuff for saving to a | 
 | // self-extracting Zip archive. | 
 | // | 
 | // ZipFile is set up as a "partial class" - defined in multiple .cs source modules. | 
 | // This is one of the source modules for the ZipFile class. | 
 | // | 
 | // Here's the design: The self-extracting zip file is just a regular managed EXE | 
 | // file, with embedded resources.  The managed code logic instantiates a ZipFile, and | 
 | // then extracts each entry.  The embedded resources include the zip archive content, | 
 | // as well as the Zip library itself.  The latter is required so that self-extracting | 
 | // can work on any machine, whether or not it has the DotNetZip library installed on | 
 | // it. | 
 | // | 
 | // What we need to do is create the animal I just described, within a method on the | 
 | // ZipFile class.  This source module provides that capability. The method is | 
 | // SaveSelfExtractor(). | 
 | // | 
 | // The way the method works: it uses the programmatic interface to the csc.exe | 
 | // compiler, Microsoft.CSharp.CSharpCodeProvider, to compile "boilerplate" | 
 | // extraction logic into a new assembly.  As part of that compile, we embed within | 
 | // that assembly the zip archive itself, as well as the Zip library. | 
 | // | 
 | // Therefore we need to first save to a temporary zip file, then produce the exe. | 
 | // | 
 | // There are a few twists. | 
 | // | 
 | // The Visual Studio Project structure is a little weird.  There are code files | 
 | // that ARE NOT compiled during a normal build of the VS Solution.  They are | 
 | // marked as embedded resources.  These are the various "boilerplate" modules that | 
 | // are used in the self-extractor. These modules are: WinFormsSelfExtractorStub.cs | 
 | // WinFormsSelfExtractorStub.Designer.cs CommandLineSelfExtractorStub.cs | 
 | // PasswordDialog.cs PasswordDialog.Designer.cs | 
 | // | 
 | // At design time, if you want to modify the way the GUI looks, you have to | 
 | // mark those modules to have a "compile" build action.  Then tweak em, test, | 
 | // etc.  Then again mark them as "Embedded resource". | 
 | // | 
 | // ------------------------------------------------------------------ | 
 |  | 
 | using System; | 
 | using System.Reflection; | 
 | using System.IO; | 
 | using System.Collections.Generic; | 
 |  | 
 |  | 
 | namespace OfficeOpenXml.Packaging.Ionic.Zip | 
 | { | 
 | #if !NO_SFX | 
 |     /// <summary> | 
 |     /// An enum that provides the different self-extractor flavors | 
 |     /// </summary> | 
 |     internal enum SelfExtractorFlavor | 
 |     { | 
 |         /// <summary> | 
 |         /// A self-extracting zip archive that runs from the console or | 
 |         /// command line. | 
 |         /// </summary> | 
 |         ConsoleApplication = 0, | 
 |  | 
 |         /// <summary> | 
 |         /// A self-extracting zip archive that presents a graphical user | 
 |         /// interface when it is executed. | 
 |         /// </summary> | 
 |         WinFormsApplication, | 
 |     } | 
 |  | 
 |     /// <summary> | 
 |     /// The options for generating a self-extracting archive. | 
 |     /// </summary> | 
 |     internal class SelfExtractorSaveOptions | 
 |     { | 
 |         /// <summary> | 
 |         ///   The type of SFX to create. | 
 |         /// </summary> | 
 |         public SelfExtractorFlavor Flavor | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The command to run after extraction. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This is optional. Leave it empty (<c>null</c> in C# or <c>Nothing</c> in | 
 |         ///   VB) to run no command after extraction. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   If it is non-empty, the SFX will execute the command specified in this | 
 |         ///   string on the user's machine, and using the extract directory as the | 
 |         ///   working directory for the process, after unpacking the archive. The | 
 |         ///   program to execute can include a path, if you like. If you want to execute | 
 |         ///   a program that accepts arguments, specify the program name, followed by a | 
 |         ///   space, and then the arguments for the program, each separated by a space, | 
 |         ///   just as you would on a normal command line. Example: <c>program.exe arg1 | 
 |         ///   arg2</c>.  The string prior to the first space will be taken as the | 
 |         ///   program name, and the string following the first space specifies the | 
 |         ///   arguments to the program. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   If you want to execute a program that has a space in the name or path of | 
 |         ///   the file, surround the program name in double-quotes. The first character | 
 |         ///   of the command line should be a double-quote character, and there must be | 
 |         ///   a matching double-quote following the end of the program file name. Any | 
 |         ///   optional arguments to the program follow that, separated by | 
 |         ///   spaces. Example: <c>"c:\project files\program name.exe" arg1 arg2</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   If the flavor of the SFX is <c>SelfExtractorFlavor.ConsoleApplication</c>, | 
 |         ///   then the SFX starts a new process, using this string as the post-extract | 
 |         ///   command line.  The SFX waits for the process to exit.  The exit code of | 
 |         ///   the post-extract command line is returned as the exit code of the | 
 |         ///   command-line 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-after-extract program if specified, OR, it may indicate | 
 |         ///   the run-after-extract program could not be fuond. There is no way to | 
 |         ///   distinguish these conditions from the calling shell, aside from parsing | 
 |         ///   the output of the SFX. If you have Quiet set to <c>true</c>, you may not | 
 |         ///   see error messages, if a problem occurs. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   If the flavor of the SFX is | 
 |         ///   <c>SelfExtractorFlavor.WinFormsApplication</c>, then the SFX starts a new | 
 |         ///   process, using this string as the post-extract command line, and using the | 
 |         ///   extract directory as the working directory for the process. The SFX does | 
 |         ///   not wait for the command to complete, and does not check the exit code of | 
 |         ///   the program. If the run-after-extract program cannot be fuond, a message | 
 |         ///   box is displayed indicating that fact. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   You can specify environment variables within this string, with a format like | 
 |         ///   <c>%NAME%</c>. The value of these variables will be expanded at the time | 
 |         ///   the SFX is run. Example: <c>%WINDIR%\system32\xcopy.exe</c> may expand at | 
 |         ///   runtime to <c>c:\Windows\System32\xcopy.exe</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   By combining this with the <c>RemoveUnpackedFilesAfterExecute</c> | 
 |         ///   flag, you can create an SFX that extracts itself, runs a file that | 
 |         ///   was extracted, then deletes all the files that were extracted. If | 
 |         ///   you want it to run "invisibly" then set <c>Flavor</c> to | 
 |         ///   <c>SelfExtractorFlavor.ConsoleApplication</c>, and set <c>Quiet</c> | 
 |         ///   to true.  The user running such an EXE will see a console window | 
 |         ///   appear, then disappear quickly.  You may also want to specify the | 
 |         ///   default extract location, with <c>DefaultExtractDirectory</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   If you set <c>Flavor</c> to | 
 |         ///   <c>SelfExtractorFlavor.WinFormsApplication</c>, and set <c>Quiet</c> to | 
 |         ///   true, then a GUI with progressbars is displayed, but it is | 
 |         ///   "non-interactive" - it accepts no input from the user.  Instead the SFX | 
 |         ///   just automatically unpacks and exits. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         public String PostExtractCommandLine | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The default extract directory the user will see when | 
 |         ///   running the self-extracting archive. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   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. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   This is only a default location.  The actual extract location will be | 
 |         ///   settable on the command line when the SFX is executed. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   You can specify environment variables within this string, | 
 |         ///   with <c>%NAME%</c>. The value of these variables will be | 
 |         ///   expanded at the time the SFX is run. Example: | 
 |         ///   <c>%USERPROFILE%\Documents\unpack</c> may expand at runtime to | 
 |         ///   <c>c:\users\melvin\Documents\unpack</c>. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         public String DefaultExtractDirectory | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The name of an .ico file in the filesystem to use for the application icon | 
 |         ///   for the generated SFX. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   Normally, DotNetZip will embed an "zipped folder" icon into the generated | 
 |         ///   SFX.  If you prefer to use a different icon, you can specify it here. It | 
 |         ///   should be a .ico file.  This file is passed as the <c>/win32icon</c> | 
 |         ///   option to the csc.exe compiler when constructing the SFX file. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         public string IconFile | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   Whether the ConsoleApplication SFX will be quiet during extraction. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This option affects the way the generated SFX runs. By default it is | 
 |         ///   false.  When you set it to true,... | 
 |         /// </para> | 
 |         /// | 
 |         /// <list type="table"> | 
 |         ///   <listheader> | 
 |         ///     <term>Flavor</term> | 
 |         ///     <description>Behavior</description> | 
 |         ///   </listheader> | 
 |         /// | 
 |         /// <item> | 
 |         ///   <term><c>ConsoleApplication</c></term> | 
 |         ///   <description><para>no messages will be emitted during successful | 
 |         ///     operation.</para> <para> Double-clicking the SFX in Windows | 
 |         ///     Explorer or as an attachment in an email will cause a console | 
 |         ///     window to appear briefly, before it disappears. If you run the | 
 |         ///     ConsoleApplication SFX from the cmd.exe prompt, it runs as a | 
 |         ///     normal console app; by default, because it is quiet, it displays | 
 |         ///     no messages to the console.  If you pass the -v+ command line | 
 |         ///     argument to the Console SFX when you run it, you will get verbose | 
 |         ///     messages to the console. </para> | 
 |         ///   </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         ///   <term><c>WinFormsApplication</c></term> | 
 |         ///   <description>the SFX extracts automatically when the application | 
 |         ///        is launched, with no additional user input. | 
 |         ///   </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// </list> | 
 |         /// | 
 |         /// <para> | 
 |         ///   When you set it to false,... | 
 |         /// </para> | 
 |         /// | 
 |         /// <list type="table"> | 
 |         ///   <listheader> | 
 |         ///     <term>Flavor</term> | 
 |         ///     <description>Behavior</description> | 
 |         ///   </listheader> | 
 |         /// | 
 |         /// <item> | 
 |         ///   <term><c>ConsoleApplication</c></term> | 
 |         ///   <description><para>the extractor will emit a | 
 |         ///     message to the console for each entry extracted.</para> | 
 |         ///     <para> | 
 |         ///       When double-clicking to launch the SFX, the console window will | 
 |         ///       remain, and the SFX will emit a message for each file as it | 
 |         ///       extracts. The messages fly by quickly, they won't be easily | 
 |         ///       readable, unless the extracted files are fairly large. | 
 |         ///     </para> | 
 |         ///   </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// <item> | 
 |         ///   <term><c>WinFormsApplication</c></term> | 
 |         ///   <description>the SFX presents a forms UI and allows the user to select | 
 |         ///     options before extracting. | 
 |         ///   </description> | 
 |         /// </item> | 
 |         /// | 
 |         /// </list> | 
 |         /// | 
 |         /// </remarks> | 
 |         public bool Quiet | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Specify what the self-extractor will do when extracting an entry | 
 |         ///   would overwrite an existing file. | 
 |         /// </summary> | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   The default behavvior is to Throw. | 
 |         /// </para> | 
 |         /// </remarks> | 
 |         public Ionic.Zip.ExtractExistingFileAction ExtractExistingFile | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Whether to remove the files that have been unpacked, after executing the | 
 |         ///   PostExtractCommandLine. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   If true, and if there is a <see | 
 |         ///   cref="SelfExtractorSaveOptions.PostExtractCommandLine"> | 
 |         ///   PostExtractCommandLine</see>, and if the command runs successfully, | 
 |         ///   then the files that the SFX unpacked will be removed, afterwards.  If | 
 |         ///   the command does not complete successfully (non-zero return code), | 
 |         ///   that is interpreted as a failure, and the extracted files will not be | 
 |         ///   removed. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   Setting this flag, and setting <c>Flavor</c> to | 
 |         ///   <c>SelfExtractorFlavor.ConsoleApplication</c>, and setting <c>Quiet</c> to | 
 |         ///   true, results in an SFX that extracts itself, runs a file that was | 
 |         ///   extracted, then deletes all the files that were extracted, with no | 
 |         ///   intervention by the user.  You may also want to specify the default | 
 |         ///   extract location, with <c>DefaultExtractDirectory</c>. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         public bool RemoveUnpackedFilesAfterExecute | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   The file version number to embed into the generated EXE. It will show up, for | 
 |         ///   example, during a mouseover in Windows Explorer. | 
 |         /// </summary> | 
 |         /// | 
 |         public Version FileVersion | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The product version to embed into the generated EXE. It will show up, for | 
 |         ///   example, during a mouseover in Windows Explorer. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   You can use any arbitrary string, but a human-readable version number is | 
 |         ///   recommended. For example "v1.2 alpha" or "v4.2 RC2".  If you specify nothing, | 
 |         ///   then there is no product version embedded into the EXE. | 
 |         /// </remarks> | 
 |         /// | 
 |         public String ProductVersion | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The copyright notice, if any, to embed into the generated EXE. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   It will show up, for example, while viewing properties of the file in | 
 |         ///   Windows Explorer.  You can use any arbitrary string, but typically you | 
 |         ///   want something like "Copyright � Dino Chiesa 2011". | 
 |         /// </remarks> | 
 |         /// | 
 |         public String Copyright | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   The description to embed into the generated EXE. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Use any arbitrary string.  This text will be displayed during a | 
 |         ///   mouseover in Windows Explorer.  If you specify nothing, then the string | 
 |         ///   "DotNetZip SFX Archive" is embedded into the EXE as the description. | 
 |         /// </remarks> | 
 |         /// | 
 |         public String Description | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The product name to embed into the generated EXE. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   Use any arbitrary string. This text will be displayed | 
 |         ///   while viewing properties of the EXE file in | 
 |         ///   Windows Explorer. | 
 |         /// </remarks> | 
 |         /// | 
 |         public String ProductName | 
 |         { | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   The title to display in the Window of a GUI SFX, while it extracts. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         ///   <para> | 
 |         ///     By default the title show in the GUI window of a self-extractor | 
 |         ///     is "DotNetZip Self-extractor (http://DotNetZip.codeplex.com/)". | 
 |         ///     You can change that by setting this property before saving the SFX. | 
 |         ///   </para> | 
 |         /// | 
 |         ///   <para> | 
 |         ///     This property has an effect only when producing a Self-extractor | 
 |         ///     of flavor <c>SelfExtractorFlavor.WinFormsApplication</c>. | 
 |         ///   </para> | 
 |         /// </remarks> | 
 |         /// | 
 |         public String SfxExeWindowTitle | 
 |         { | 
 |             // workitem 12608 | 
 |             get; | 
 |             set; | 
 |         } | 
 |  | 
 |         /// <summary> | 
 |         ///   Additional options for the csc.exe compiler, when producing the SFX | 
 |         ///   EXE. | 
 |         /// </summary> | 
 |         /// <exclude/> | 
 |         public string AdditionalCompilerSwitches | 
 |         { | 
 |             get; set; | 
 |         } | 
 |     } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |     partial class ZipFile | 
 |     { | 
 |         class ExtractorSettings | 
 |         { | 
 |             public SelfExtractorFlavor Flavor; | 
 |             public List<string> ReferencedAssemblies; | 
 |             public List<string> CopyThroughResources; | 
 |             public List<string> ResourcesToCompile; | 
 |         } | 
 |  | 
 |  | 
 |         private static ExtractorSettings[] SettingsList = { | 
 |             new ExtractorSettings() { | 
 |                 Flavor = SelfExtractorFlavor.WinFormsApplication, | 
 |                 ReferencedAssemblies= new List<string>{ | 
 |                     "System.dll", "System.Windows.Forms.dll", "System.Drawing.dll"}, | 
 |                 CopyThroughResources = new List<string>{ | 
 |                     "Ionic.Zip.WinFormsSelfExtractorStub.resources", | 
 |                     "Ionic.Zip.Forms.PasswordDialog.resources", | 
 |                     "Ionic.Zip.Forms.ZipContentsDialog.resources"}, | 
 |                 ResourcesToCompile = new List<string>{ | 
 |                     "WinFormsSelfExtractorStub.cs", | 
 |                     "WinFormsSelfExtractorStub.Designer.cs", // .Designer.cs? | 
 |                     "PasswordDialog.cs", | 
 |                     "PasswordDialog.Designer.cs",             //.Designer.cs" | 
 |                     "ZipContentsDialog.cs", | 
 |                     "ZipContentsDialog.Designer.cs",             //.Designer.cs" | 
 |                     "FolderBrowserDialogEx.cs", | 
 |                 } | 
 |             }, | 
 |             new ExtractorSettings() { | 
 |                 Flavor = SelfExtractorFlavor.ConsoleApplication, | 
 |                 ReferencedAssemblies= new List<string> { "System.dll", }, | 
 |                 CopyThroughResources = null, | 
 |                 ResourcesToCompile = new List<string>{"CommandLineSelfExtractorStub.cs"} | 
 |             } | 
 |         }; | 
 |  | 
 |  | 
 |  | 
 |         //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); | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         /// <summary> | 
 |         ///   Saves the ZipFile instance to a self-extracting zip archive, using | 
 |         ///   the specified save options. | 
 |         /// </summary> | 
 |         /// | 
 |         /// <remarks> | 
 |         /// <para> | 
 |         ///   This method saves a self extracting archive, using the specified save | 
 |         ///   options. These options include the flavor of the SFX, the default extract | 
 |         ///   directory, the icon file, and so on.  See the documentation | 
 |         ///   for <see cref="SaveSelfExtractor(string , SelfExtractorFlavor)"/> for more | 
 |         ///   details. | 
 |         /// </para> | 
 |         /// | 
 |         /// <para> | 
 |         ///   The user who runs the SFX will have the opportunity to change the extract | 
 |         ///   directory before extracting. If at the time of extraction, the specified | 
 |         ///   directory does not exist, the SFX will create the directory before | 
 |         ///   extracting the files. | 
 |         /// </para> | 
 |         /// | 
 |         /// </remarks> | 
 |         /// | 
 |         /// <example> | 
 |         ///   This example saves a WinForms-based self-extracting archive EXE that | 
 |         ///   will use c:\ExtractHere as the default extract location. The C# code | 
 |         ///   shows syntax for .NET 3.0, which uses an object initializer for | 
 |         ///   the SelfExtractorOptions object. | 
 |         /// <code> | 
 |         /// string DirectoryPath = "c:\\Documents\\Project7"; | 
 |         /// using (ZipFile zip = new ZipFile()) | 
 |         /// { | 
 |         ///     zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); | 
 |         ///     zip.Comment = "This will be embedded into a self-extracting WinForms-based exe"; | 
 |         ///     var options = new SelfExtractorOptions | 
 |         ///     { | 
 |         ///       Flavor = SelfExtractorFlavor.WinFormsApplication, | 
 |         ///       DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere", | 
 |         ///       PostExtractCommandLine = ExeToRunAfterExtract, | 
 |         ///       SfxExeWindowTitle = "My Custom Window Title", | 
 |         ///       RemoveUnpackedFilesAfterExecute = true | 
 |         ///     }; | 
 |         ///     zip.SaveSelfExtractor("archive.exe", options); | 
 |         /// } | 
 |         /// </code> | 
 |         /// <code lang="VB"> | 
 |         /// Dim DirectoryPath As String = "c:\Documents\Project7" | 
 |         /// Using zip As New ZipFile() | 
 |         ///     zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) | 
 |         ///     zip.Comment = "This will be embedded into a self-extracting console-based exe" | 
 |         ///     Dim options As New SelfExtractorOptions() | 
 |         ///     options.Flavor = SelfExtractorFlavor.WinFormsApplication | 
 |         ///     options.DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere" | 
 |         ///     options.PostExtractCommandLine = ExeToRunAfterExtract | 
 |         ///     options.SfxExeWindowTitle = "My Custom Window Title" | 
 |         ///     options.RemoveUnpackedFilesAfterExecute = True | 
 |         ///     zip.SaveSelfExtractor("archive.exe", options) | 
 |         /// End Using | 
 |         /// </code> | 
 |         /// </example> | 
 |         /// | 
 |         /// <param name="exeToGenerate">The name of the EXE to generate.</param> | 
 |         /// <param name="options">provides the options for creating the | 
 |         /// Self-extracting archive.</param> | 
 |         internal void SaveSelfExtractor(string exeToGenerate, SelfExtractorSaveOptions options) | 
 |         { | 
 |             // Save an SFX that is both an EXE and a ZIP. | 
 |  | 
 |             // Check for the case where we are re-saving a zip archive | 
 |             // that was originally instantiated with a stream.  In that case, | 
 |             // the _name will be null. If so, we set _writestream to null, | 
 |             // which insures that we'll cons up a new WriteStream (with a filesystem | 
 |             // file backing it) in the Save() method. | 
 |             if (_name == null) | 
 |                 _writestream = null; | 
 |  | 
 |             _SavingSfx = true; | 
 |             _name = exeToGenerate; | 
 |             if (Directory.Exists(_name)) | 
 |                 throw new ZipException("Bad Directory", new System.ArgumentException("That name specifies an existing directory. Please specify a filename.", "exeToGenerate")); | 
 |             _contentsChanged = true; | 
 |             _fileAlreadyExists = File.Exists(_name); | 
 |  | 
 |             _SaveSfxStub(exeToGenerate, options); | 
 |  | 
 |             Save(); | 
 |             _SavingSfx = false; | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |         private static void ExtractResourceToFile(Assembly a, string resourceName, string filename) | 
 |         { | 
 |             int n = 0; | 
 |             byte[] bytes = new byte[1024]; | 
 |             using (Stream instream = a.GetManifestResourceStream(resourceName)) | 
 |             { | 
 |                 if (instream == null) | 
 |                     throw new ZipException(String.Format("missing resource '{0}'", resourceName)); | 
 |  | 
 |                 using (FileStream outstream = File.OpenWrite(filename)) | 
 |                 { | 
 |                     do | 
 |                     { | 
 |                         n = instream.Read(bytes, 0, bytes.Length); | 
 |                         outstream.Write(bytes, 0, n); | 
 |                     } while (n > 0); | 
 |                 } | 
 |             } | 
 |         } | 
 |  | 
 |  | 
 |         private void _SaveSfxStub(string exeToGenerate, SelfExtractorSaveOptions options) | 
 |         { | 
 |             string nameOfIconFile = null; | 
 |             string stubExe = null; | 
 |             string unpackedResourceDir = null; | 
 |             string tmpDir = null; | 
 |             try | 
 |             { | 
 |                 if (File.Exists(exeToGenerate)) | 
 |                 { | 
 |                     if (Verbose) StatusMessageTextWriter.WriteLine("The existing file ({0}) will be overwritten.", exeToGenerate); | 
 |                 } | 
 |                 if (!exeToGenerate.EndsWith(".exe")) | 
 |                 { | 
 |                     if (Verbose) StatusMessageTextWriter.WriteLine("Warning: The generated self-extracting file will not have an .exe extension."); | 
 |                 } | 
 |  | 
 |                 // workitem 10553 | 
 |                 tmpDir = TempFileFolder ?? Path.GetDirectoryName(exeToGenerate); | 
 |                 stubExe = GenerateTempPathname(tmpDir, "exe"); | 
 |  | 
 |                 // get the Ionic.Zip assembly | 
 |                 Assembly a1 = typeof(ZipFile).Assembly; | 
 |  | 
 |                 using (var csharp = new Microsoft.CSharp.CSharpCodeProvider | 
 |                        (new Dictionary<string,string>() { { "CompilerVersion", "v2.0" } })) { | 
 |  | 
 |                     // The following is a perfect opportunity for a linq query, but | 
 |                     // I cannot use it.  DotNetZip needs to run on .NET 2.0, | 
 |                     // and using LINQ would break that. Here's what it would look | 
 |                     // like: | 
 |                     // | 
 |                     //   var settings = (from x in SettingsList | 
 |                     //                   where x.Flavor == flavor | 
 |                     //                   select x).First(); | 
 |  | 
 |                     ExtractorSettings settings = null; | 
 |                     foreach (var x in SettingsList) | 
 |                     { | 
 |                         if (x.Flavor == options.Flavor) | 
 |                         { | 
 |                             settings = x; | 
 |                             break; | 
 |                         } | 
 |                     } | 
 |  | 
 |                     // sanity check; should never happen | 
 |                     if (settings == null) | 
 |                         throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", options.Flavor)); | 
 |  | 
 |                     // This is the list of referenced assemblies.  Ionic.Zip is | 
 |                     // needed here.  Also if it is the winforms (gui) extractor, we | 
 |                     // need other referenced assemblies, like | 
 |                     // System.Windows.Forms.dll, etc. | 
 |                     var cp = new System.CodeDom.Compiler.CompilerParameters(); | 
 |                     cp.ReferencedAssemblies.Add(a1.Location); | 
 |                     if (settings.ReferencedAssemblies != null) | 
 |                         foreach (string ra in settings.ReferencedAssemblies) | 
 |                             cp.ReferencedAssemblies.Add(ra); | 
 |  | 
 |                     cp.GenerateInMemory = false; | 
 |                     cp.GenerateExecutable = true; | 
 |                     cp.IncludeDebugInformation = false; | 
 |                     cp.CompilerOptions = ""; | 
 |  | 
 |                     Assembly a2 = Assembly.GetExecutingAssembly(); | 
 |  | 
 |                     // Use this to concatenate all the source code resources into a | 
 |                     // single module. | 
 |                     var sb = new System.Text.StringBuilder(); | 
 |  | 
 |                     // In case there are compiler errors later, we allocate a source | 
 |                     // file name now. If errors are detected, we'll spool the source | 
 |                     // code as well as the errors (in comments) into that filename, | 
 |                     // and throw an exception with the filename.  Makes it easier to | 
 |                     // diagnose.  This should be rare; most errors happen only | 
 |                     // during devlpmt of DotNetZip itself, but there are rare | 
 |                     // occasions when they occur in other cases. | 
 |                     string sourceFile = GenerateTempPathname(tmpDir, "cs"); | 
 |  | 
 |  | 
 |                     // // debugging: enumerate the resources in this assembly | 
 |                     // Console.WriteLine("Resources in this assembly:"); | 
 |                     // foreach (string rsrc in a2.GetManifestResourceNames()) | 
 |                     //   { | 
 |                     //     Console.WriteLine(rsrc); | 
 |                     //   } | 
 |                     // Console.WriteLine(); | 
 |  | 
 |  | 
 |                     // all the source code is embedded in the DLL as a zip file. | 
 |                     using (ZipFile zip = ZipFile.Read(a2.GetManifestResourceStream("Ionic.Zip.Resources.ZippedResources.zip"))) | 
 |                     { | 
 |                         // // debugging: enumerate the files in the embedded zip | 
 |                         // Console.WriteLine("Entries in the embbedded zip:"); | 
 |                         // foreach (ZipEntry entry in zip) | 
 |                         //   { | 
 |                         //     Console.WriteLine(entry.FileName); | 
 |                         //   } | 
 |                         // Console.WriteLine(); | 
 |  | 
 |                         unpackedResourceDir = GenerateTempPathname(tmpDir, "tmp"); | 
 |  | 
 |                         if (String.IsNullOrEmpty(options.IconFile)) | 
 |                         { | 
 |                             // Use the ico file that is embedded into the Ionic.Zip | 
 |                             // DLL itself.  To do this we must unpack the icon to | 
 |                             // the filesystem, in order to specify it on the cmdline | 
 |                             // of csc.exe.  This method will remove the unpacked | 
 |                             // file later. | 
 |                             System.IO.Directory.CreateDirectory(unpackedResourceDir); | 
 |                             ZipEntry e = zip["zippedFile.ico"]; | 
 |                             // Must not extract a readonly file - it will be impossible to | 
 |                             // delete later. | 
 |                             if ((e.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) | 
 |                                 e.Attributes ^= FileAttributes.ReadOnly; | 
 |                             e.Extract(unpackedResourceDir); | 
 |                             nameOfIconFile = Path.Combine(unpackedResourceDir, "zippedFile.ico"); | 
 |                             cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", nameOfIconFile); | 
 |                         } | 
 |                         else | 
 |                             cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", options.IconFile); | 
 |  | 
 |                         cp.OutputAssembly = stubExe; | 
 |  | 
 |                         if (options.Flavor == SelfExtractorFlavor.WinFormsApplication) | 
 |                             cp.CompilerOptions += " /target:winexe"; | 
 |  | 
 |                         if (!String.IsNullOrEmpty(options.AdditionalCompilerSwitches)) | 
 |                             cp.CompilerOptions += " " + options.AdditionalCompilerSwitches; | 
 |  | 
 |                         if (String.IsNullOrEmpty(cp.CompilerOptions)) | 
 |                             cp.CompilerOptions = null; | 
 |  | 
 |                         if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0)) | 
 |                         { | 
 |                             if (!Directory.Exists(unpackedResourceDir)) System.IO.Directory.CreateDirectory(unpackedResourceDir); | 
 |                             foreach (string re in settings.CopyThroughResources) | 
 |                             { | 
 |                                 string filename = Path.Combine(unpackedResourceDir, re); | 
 |  | 
 |                                 ExtractResourceToFile(a2, re, filename); | 
 |                                 // add the file into the target assembly as an embedded resource | 
 |                                 cp.EmbeddedResources.Add(filename); | 
 |                             } | 
 |                         } | 
 |  | 
 |                         // add the Ionic.Utils.Zip DLL as an embedded resource | 
 |                         cp.EmbeddedResources.Add(a1.Location); | 
 |  | 
 |                         // file header | 
 |                         sb.Append("// " + Path.GetFileName(sourceFile) + "\n") | 
 |                             .Append("// --------------------------------------------\n//\n") | 
 |                             .Append("// This SFX source file was generated by DotNetZip ") | 
 |                             .Append(ZipFile.LibraryVersion.ToString()) | 
 |                             .Append("\n//         at ") | 
 |                             .Append(System.DateTime.Now.ToString("yyyy MMMM dd  HH:mm:ss")) | 
 |                             .Append("\n//\n// --------------------------------------------\n\n\n"); | 
 |  | 
 |                         // assembly attributes | 
 |                         if (!String.IsNullOrEmpty(options.Description)) | 
 |                             sb.Append("[assembly: System.Reflection.AssemblyTitle(\"" | 
 |                                       + options.Description.Replace("\"", "") | 
 |                                       + "\")]\n"); | 
 |                         else | 
 |                             sb.Append("[assembly: System.Reflection.AssemblyTitle(\"DotNetZip SFX Archive\")]\n"); | 
 |  | 
 |                         if (!String.IsNullOrEmpty(options.ProductVersion)) | 
 |                             sb.Append("[assembly: System.Reflection.AssemblyInformationalVersion(\"" | 
 |                                       + options.ProductVersion.Replace("\"", "") | 
 |                                       + "\")]\n"); | 
 |  | 
 |                         // workitem | 
 |                         string copyright = | 
 |                             (String.IsNullOrEmpty(options.Copyright)) | 
 |                             ? "Extractor: Copyright � Dino Chiesa 2008-2011" | 
 |                             : options.Copyright.Replace("\"", ""); | 
 |  | 
 |                         if (!String.IsNullOrEmpty(options.ProductName)) | 
 |                             sb.Append("[assembly: System.Reflection.AssemblyProduct(\"") | 
 |                                 .Append(options.ProductName.Replace("\"", "")) | 
 |                                 .Append("\")]\n"); | 
 |                         else | 
 |                             sb.Append("[assembly: System.Reflection.AssemblyProduct(\"DotNetZip\")]\n"); | 
 |  | 
 |  | 
 |                         sb.Append("[assembly: System.Reflection.AssemblyCopyright(\"" + copyright + "\")]\n") | 
 |                             .Append(String.Format("[assembly: System.Reflection.AssemblyVersion(\"{0}\")]\n", ZipFile.LibraryVersion.ToString())); | 
 |                         if (options.FileVersion != null) | 
 |                             sb.Append(String.Format("[assembly: System.Reflection.AssemblyFileVersion(\"{0}\")]\n", | 
 |                                                     options.FileVersion.ToString())); | 
 |  | 
 |                         sb.Append("\n\n\n"); | 
 |  | 
 |                         // Set the default extract location if it is available | 
 |                         string extractLoc = options.DefaultExtractDirectory; | 
 |                         if (extractLoc != null) | 
 |                         { | 
 |                             // remove double-quotes and replace slash with double-slash. | 
 |                             // This, because the value is going to be embedded into a | 
 |                             // cs file as a quoted string, and it needs to be escaped. | 
 |                             extractLoc = extractLoc.Replace("\"", "").Replace("\\", "\\\\"); | 
 |                         } | 
 |  | 
 |                         string postExCmdLine = options.PostExtractCommandLine; | 
 |                         if (postExCmdLine != null) | 
 |                         { | 
 |                             postExCmdLine = postExCmdLine.Replace("\\", "\\\\"); | 
 |                             postExCmdLine = postExCmdLine.Replace("\"", "\\\""); | 
 |                         } | 
 |  | 
 |  | 
 |                         foreach (string rc in settings.ResourcesToCompile) | 
 |                         { | 
 |                             using (Stream s = zip[rc].OpenReader()) | 
 |                             { | 
 |                                 if (s == null) | 
 |                                     throw new ZipException(String.Format("missing resource '{0}'", rc)); | 
 |                                 using (StreamReader sr = new StreamReader(s)) | 
 |                                 { | 
 |                                     while (sr.Peek() >= 0) | 
 |                                     { | 
 |                                         string line = sr.ReadLine(); | 
 |                                         if (extractLoc != null) | 
 |                                             line = line.Replace("@@EXTRACTLOCATION", extractLoc); | 
 |  | 
 |                                         line = line.Replace("@@REMOVE_AFTER_EXECUTE", options.RemoveUnpackedFilesAfterExecute.ToString()); | 
 |                                         line = line.Replace("@@QUIET", options.Quiet.ToString()); | 
 |                                         if (!String.IsNullOrEmpty(options.SfxExeWindowTitle)) | 
 |  | 
 |                                             line = line.Replace("@@SFX_EXE_WINDOW_TITLE", options.SfxExeWindowTitle); | 
 |  | 
 |                                         line = line.Replace("@@EXTRACT_EXISTING_FILE", ((int)options.ExtractExistingFile).ToString()); | 
 |  | 
 |                                         if (postExCmdLine != null) | 
 |                                             line = line.Replace("@@POST_UNPACK_CMD_LINE", postExCmdLine); | 
 |  | 
 |                                         sb.Append(line).Append("\n"); | 
 |                                     } | 
 |                                 } | 
 |                                 sb.Append("\n\n"); | 
 |                             } | 
 |                         } | 
 |                     } | 
 |  | 
 |                     string LiteralSource = sb.ToString(); | 
 |  | 
 | #if DEBUGSFX | 
 |                     // for debugging only | 
 |                     string sourceModule = GenerateTempPathname(tmpDir, "cs"); | 
 |                     using (StreamWriter sw = File.CreateText(sourceModule)) | 
 |                     { | 
 |                         sw.Write(LiteralSource); | 
 |                     } | 
 |                     Console.WriteLine("source: {0}", sourceModule); | 
 | #endif | 
 |  | 
 |                     var cr = csharp.CompileAssemblyFromSource(cp, LiteralSource); | 
 |  | 
 |  | 
 |                     if (cr == null) | 
 |                         throw new SfxGenerationException("Cannot compile the extraction logic!"); | 
 |  | 
 |                     if (Verbose) | 
 |                         foreach (string output in cr.Output) | 
 |                             StatusMessageTextWriter.WriteLine(output); | 
 |  | 
 |                     if (cr.Errors.Count != 0) | 
 |                     { | 
 |                         using (TextWriter tw = new StreamWriter(sourceFile)) | 
 |                         { | 
 |                             // first, the source we compiled | 
 |                             tw.Write(LiteralSource); | 
 |  | 
 |                             // now, append the compile errors | 
 |                             tw.Write("\n\n\n// ------------------------------------------------------------------\n"); | 
 |                             tw.Write("// Errors during compilation: \n//\n"); | 
 |                             string p = Path.GetFileName(sourceFile); | 
 |  | 
 |                             foreach (System.CodeDom.Compiler.CompilerError error in cr.Errors) | 
 |                             { | 
 |                                 tw.Write(String.Format("//   {0}({1},{2}): {3} {4}: {5}\n//\n", | 
 |                                                        p,                                   // 0 | 
 |                                                        error.Line,                          // 1 | 
 |                                                        error.Column,                        // 2 | 
 |                                                        error.IsWarning ? "Warning" : "error",   // 3 | 
 |                                                        error.ErrorNumber,                   // 4 | 
 |                                                        error.ErrorText));                  // 5 | 
 |                             } | 
 |                         } | 
 |                         throw new SfxGenerationException(String.Format("Errors compiling the extraction logic!  {0}", sourceFile)); | 
 |                     } | 
 |  | 
 |                     OnSaveEvent(ZipProgressEventType.Saving_AfterCompileSelfExtractor); | 
 |  | 
 |                     // Now, copy the resulting EXE image to the _writestream. | 
 |                     // Because this stub exe is being saved first, the effect will be to | 
 |                     // concatenate the exe and the zip data together. | 
 |                     using (System.IO.Stream input = System.IO.File.OpenRead(stubExe)) | 
 |                     { | 
 |                         byte[] buffer = new byte[4000]; | 
 |                         int n = 1; | 
 |                         while (n != 0) | 
 |                         { | 
 |                             n = input.Read(buffer, 0, buffer.Length); | 
 |                             if (n != 0) | 
 |                                 WriteStream.Write(buffer, 0, n); | 
 |                         } | 
 |                     } | 
 |                 } | 
 |  | 
 |                 OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); | 
 |             } | 
 |             finally | 
 |             { | 
 |                 try | 
 |                 { | 
 |                     if (Directory.Exists(unpackedResourceDir)) | 
 |                     { | 
 |                         try { Directory.Delete(unpackedResourceDir, true); } | 
 |                         catch (System.IO.IOException exc1) | 
 |                         { | 
 |                             StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); | 
 |                         } | 
 |                     } | 
 |                     if (File.Exists(stubExe)) | 
 |                     { | 
 |                         try { File.Delete(stubExe); } | 
 |                         catch (System.IO.IOException exc1) | 
 |                         { | 
 |                             StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); | 
 |                         } | 
 |                     } | 
 |                 } | 
 |                 catch (System.IO.IOException) { } | 
 |             } | 
 |  | 
 |             return; | 
 |  | 
 |         } | 
 |  | 
 |  | 
 |  | 
 |         internal static string GenerateTempPathname(string dir, string extension) | 
 |         { | 
 |             string candidate = null; | 
 |             String AppName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; | 
 |             do | 
 |             { | 
 |                 // workitem 13475 | 
 |                 string uuid = System.Guid.NewGuid().ToString(); | 
 |  | 
 |                 string Name = String.Format("{0}-{1}-{2}.{3}", | 
 |                         AppName, System.DateTime.Now.ToString("yyyyMMMdd-HHmmss"), | 
 |                                             uuid, extension); | 
 |                 candidate = System.IO.Path.Combine(dir, Name); | 
 |             } while (System.IO.File.Exists(candidate) || System.IO.Directory.Exists(candidate)); | 
 |  | 
 |             // The candidate path does not exist as a file or directory. | 
 |             // It can now be created, as a file or directory. | 
 |             return candidate; | 
 |         } | 
 |  | 
 |     } | 
 | #endif | 
 | } |