Esempio n. 1
0
 /// <summary>
 /// Display a package creation message to the user.
 /// </summary>
 /// <param name="sender">The sender of the message.</param>
 /// <param name="mea">Arguments for the message event.</param>
 private void MessageHandler(object sender, MessageEventArgs mea)
 {
     if (mea is WixErrorEventArgs)
     {
         string message = String.Format(mea.ResourceManager.GetString(mea.ResourceName), mea.MessageArgs);
         this.OnMessage(ClickThroughErrors.WixError(message));
     }
     else if (mea is WixWarningEventArgs)
     {
         string message = String.Format(mea.ResourceManager.GetString(mea.ResourceName), mea.MessageArgs);
         this.OnMessage(ClickThroughWarnings.WixWarning(message));
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Builds a setup package to the specified output path.
        /// </summary>
        /// <param name="outputPath">Location to build the setup package to.</param>
        /// <param name="outputSourcePath">Optional path where the package's .wxs file will be written.</param>
        public bool Build(string outputPath, string outputSourcePath)
        {
            this.buildError = null; // clear out any previous errors

            int currentProgress = 0;
            int totalProgress   = 7;

            // calculate the upper progress
            if (outputSourcePath != null)
            {
                ++totalProgress;
            }
            if (this.previousPackagePath != null)
            {
                ++totalProgress;
            }

            this.VerifyRequiredInformation();

            if (!this.OnProgress(currentProgress++, totalProgress, "Initialized package builder..."))
            {
                return(false);
            }

            // Calculate where everything is going
            string localSetupExe  = outputPath;
            string localSetupFeed = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileName(this.updateUrl.AbsolutePath));

            Uri urlSetupExe  = new Uri(this.updateUrl, Path.GetFileName(localSetupExe));
            Uri urlSetupFeed = new Uri(this.updateUrl, Path.GetFileName(localSetupFeed));

            Guid    previousUpgradeCode = Guid.Empty;
            Version previousVersion     = null;
            Uri     previousSetupFeed   = null;

            // if a previous package was provided, go read the key information out of it now
            if (this.previousPackagePath != null)
            {
                if (!this.OnProgress(currentProgress++, totalProgress, "Reading previous package..."))
                {
                    return(false);
                }

                this.ReadPreviousPackage(this.previousPackagePath, out previousUpgradeCode, out previousVersion, out previousSetupFeed);
            }

            //
            // if a upgrade code and/or version has not been specified use one
            // from the previous package or create new.
            //
            if (this.upgradeCode == Guid.Empty)
            {
                if (previousUpgradeCode == Guid.Empty)
                {
                    this.upgradeCode = Guid.NewGuid();
                }
                else
                {
                    this.upgradeCode = previousUpgradeCode;
                }
            }

            if (this.version == null)
            {
                if (previousVersion == null)
                {
                    FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(Path.Combine(this.applicationRoot.Content, this.applicationEntry.Content));
                    this.version = new Version(fileVersionInfo.FileVersion);
                }
                else
                {
                    this.version = previousVersion;
                }
            }

            // verify that new data is okay when compared to previous package
            if (previousUpgradeCode != Guid.Empty && previousUpgradeCode != this.upgradeCode)
            {
                this.OnMessage(ClickThroughErrors.UpgradeCodeChanged(previousUpgradeCode, this.upgradeCode));
            }
            if (previousVersion != null && previousVersion >= this.version)
            {
                this.OnMessage(ClickThroughErrors.NewVersionIsNotGreater(previousVersion, this.version));
            }

            if (this.buildError != null)
            {
                throw new InvalidOperationException(String.Format(this.buildError.ResourceManager.GetString(this.buildError.ResourceName), this.buildError.MessageArgs));
            }
            else if (!this.OnProgress(currentProgress++, totalProgress, "Processing package information..."))
            {
                return(false);
            }

            // Product information
            Application application = new Application();

            application.Product.Id           = Guid.NewGuid().ToString();
            application.Product.Language     = "1033";
            application.Product.Manufacturer = this.manufacturerName.Content;
            application.Product.Name         = this.applicationName.Content;
            application.Package.Description  = this.description.Content;
            application.Product.UpgradeCode  = this.upgradeCode.ToString();
            application.Product.Version      = this.version.ToString();

            Wix.WixVariable variable = new Wix.WixVariable();
            variable       = new Wix.WixVariable();
            variable.Id    = "ProductName";
            variable.Value = application.Product.Name;
            application.Product.AddChild(variable);

            variable       = new Wix.WixVariable();
            variable.Id    = "ProductCode";
            variable.Value = application.Product.Id;
            application.Product.AddChild(variable);

            variable       = new Wix.WixVariable();
            variable.Id    = "ProductVersion";
            variable.Value = application.Product.Version;
            application.Product.AddChild(variable);

            variable       = new Wix.WixVariable();
            variable.Id    = "ShortcutFileId";
            variable.Value = "todoFileIdHere";
            application.Product.AddChild(variable);

            // Upgrade logic
            Wix.Upgrade upgrade = new Wix.Upgrade();
            upgrade.Id = application.Product.UpgradeCode;
            application.Product.AddChild(upgrade);

            Wix.UpgradeVersion minUpgrade = new Wix.UpgradeVersion();
            minUpgrade.Minimum    = application.Product.Version;
            minUpgrade.OnlyDetect = Wix.YesNoType.yes;
            minUpgrade.Property   = "NEWERVERSIONDETECTED";
            upgrade.AddChild(minUpgrade);

            Wix.UpgradeVersion maxUpgrade = new Wix.UpgradeVersion();
            maxUpgrade.Maximum        = application.Product.Version;
            maxUpgrade.IncludeMaximum = Wix.YesNoType.no;
            maxUpgrade.Property       = "OLDERVERSIONBEINGUPGRADED";
            upgrade.AddChild(maxUpgrade);

            // Update Feed
            Wix.Property property = new Wix.Property();
            property.Id    = "ARPURLUPDATEINFO";
            property.Value = urlSetupFeed.AbsoluteUri;
            application.Product.AddChild(property);

#if false
            // Directory tree
            Wix.DirectoryRef applicationCacheRef = new Wix.DirectoryRef();
            applicationCacheRef.Id = "ApplicationsCacheFolder";
            application.Product.AddChild(applicationCacheRef);
#endif

            Wix.DirectoryRef directoryRef = new Wix.DirectoryRef();
            directoryRef.Id = "ApplicationsFolder";
            application.Product.AddChild(directoryRef);

            this.applicationRootDirectory.Name = String.Concat(application.Product.UpgradeCode, "v", application.Product.Version);
            directoryRef.AddChild(this.applicationRootDirectory);

#if false
            // System registry keys
            Wix.Component registryComponent = new Wix.Component();
            registryComponent.Id   = "SystemVersionRegistryKeyComponent";
            registryComponent.Guid = Guid.NewGuid().ToString();
            directoryRef.AddChild(registryComponent);

            Wix.Registry productRegKey = new Wix.Registry();
            productRegKey.Root   = Wix.RegistryRootType.HKCU;
            productRegKey.Key    = @"Software\WiX\ClickThrough\Applications\[UpgradeCode]";
            productRegKey.Action = Wix.Registry.ActionType.createKeyAndRemoveKeyOnUninstall;
            registryComponent.AddChild(productRegKey);

            Wix.Registry versionRegKey = new Wix.Registry();
            versionRegKey.Name  = "Version";
            versionRegKey.Type  = Wix.Registry.TypeType.@string;
            versionRegKey.Value = "[ProductVersion]";
            productRegKey.AddChild(versionRegKey);

            Wix.Registry sourceRegKey = new Wix.Registry();
            sourceRegKey.Name  = "UpdateInfoSource";
            sourceRegKey.Type  = Wix.Registry.TypeType.@string;
            sourceRegKey.Value = "[ARPURLUPDATEINFO]";
            productRegKey.AddChild(sourceRegKey);

            // Shortcut
            Wix.DirectoryRef programMenuRef = new Wix.DirectoryRef();
            programMenuRef.Id = "ProgramMenuFolder";
            Wix.Directory shortcutsDirectory = new Wix.Directory();
            shortcutsDirectory.Id       = "ThisAppShortcuts";
            shortcutsDirectory.LongName = application.Product.Name;
            shortcutsDirectory.Name     = "AppSCDir";
            programMenuRef.AddChild(shortcutsDirectory);
            application.Product.AddChild(programMenuRef);

            Wix.Component shortcutsComponent = new Wix.Component();
            shortcutsComponent.Id      = "ThisApplicationShortcutComponent";
            shortcutsComponent.Guid    = Guid.NewGuid().ToString();
            shortcutsComponent.KeyPath = Wix.YesNoType.yes;
            shortcutsDirectory.AddChild(shortcutsComponent);

            Wix.CreateFolder shortcutsCreateFolder = new Wix.CreateFolder();
            shortcutsComponent.AddChild(shortcutsCreateFolder);

            Wix.Shortcut shortcut = this.GetShortcut(this.applicationEntry.Content, rootDirectory, shortcutsDirectory);
            shortcutsComponent.AddChild(shortcut);

            // Remove cached MSI file.
            Wix.Component removeComponent = new Wix.Component();
            removeComponent.Id      = "ThisApplicationRemoveComponent";
            removeComponent.Guid    = Guid.NewGuid().ToString();
            removeComponent.KeyPath = Wix.YesNoType.yes;
            applicationCacheRef.AddChild(removeComponent);

            Wix.RemoveFile cacheRemoveFile = new Wix.RemoveFile();
            cacheRemoveFile.Id        = "ThisApplicationRemoveCachedMsi";
            cacheRemoveFile.Directory = "ApplicationsCacheFolder";
            cacheRemoveFile.Name      = "unknown.msi";
            cacheRemoveFile.LongName  = String.Concat("{", application.Product.Id.ToUpper(CultureInfo.InvariantCulture), "}v", application.Version.ToString(), ".msi");
            cacheRemoveFile.On        = Wix.RemoveFile.OnType.uninstall;
            removeComponent.AddChild(cacheRemoveFile);

            Wix.RemoveFile cacheRemoveFolder = new Wix.RemoveFile();
            cacheRemoveFolder.Id        = "ThisApplicationRemoveCacheFolder";
            cacheRemoveFolder.Directory = "ApplicationsCacheFolder";
            cacheRemoveFolder.On        = Wix.RemoveFile.OnType.uninstall;
            removeComponent.AddChild(cacheRemoveFolder);

            Wix.RemoveFile applicationRemoveFolder = new Wix.RemoveFile();
            applicationRemoveFolder.Id        = "ThisApplicationRemoveApplicationsFolder";
            applicationRemoveFolder.Directory = "ApplicationsFolder";
            applicationRemoveFolder.On        = Wix.RemoveFile.OnType.uninstall;
            removeComponent.AddChild(applicationRemoveFolder);
#endif
            // Feature tree
            Wix.FeatureRef applicationFeatureRef = new Wix.FeatureRef();
            applicationFeatureRef.Id = "ApplicationFeature";
            application.Product.AddChild(applicationFeatureRef);

#if false
            Wix.Feature applicationFeature = new Wix.Feature();
            applicationFeature.Id             = "ApplicationFeature";
            applicationFeature.Display        = "expand";
            applicationFeature.Level          = 1;
            applicationFeature.Absent         = Wix.Feature.AbsentType.disallow;
            applicationFeature.AllowAdvertise = Wix.Feature.AllowAdvertiseType.yes;
            applicationFeature.InstallDefault = Wix.Feature.InstallDefaultType.local;
            applicationFeature.TypicalDefault = Wix.Feature.TypicalDefaultType.install;
            application.Product.AddChild(applicationFeature);

            Wix.ComponentRef shortcutsComponentRef = new Wix.ComponentRef();
            shortcutsComponentRef.Id = shortcutsComponent.Id;
            applicationFeature.AddChild(shortcutsComponentRef);

            Wix.ComponentRef removeComponentRef = new Wix.ComponentRef();
            removeComponentRef.Id = removeComponent.Id;
            applicationFeature.AddChild(removeComponentRef);
#endif

            Wix.ComponentRef[] componentRefs = this.GetComponentRefs(this.applicationRootDirectory);
            foreach (Wix.ComponentRef componentRef in componentRefs)
            {
                applicationFeatureRef.AddChild(componentRef);
            }

            if (!this.OnProgress(currentProgress++, totalProgress, "Serializing package information into XML..."))
            {
                return(false);
            }

            // serialize to an xml string
            string xml;
            using (StringWriter sw = new StringWriter())
            {
                XmlTextWriter writer = null;
                try
                {
                    writer = new XmlTextWriter(sw);

                    application.WixRoot.OutputXml(writer);

                    xml = sw.ToString();
                }
                finally
                {
                    if (writer != null)
                    {
                        writer.Close();
                    }
                }
            }

            // load the xml into a document
            XmlDocument sourceDoc = new XmlDocument();
            sourceDoc.LoadXml(xml);

            if (outputSourcePath != null)
            {
                if (!this.OnProgress(currentProgress++, totalProgress, "Saving .wxs file..."))
                {
                    return(false);
                }

                sourceDoc.Save(outputSourcePath);
            }

            // generate the MSI, create the setup.exe, and generate the RSS feed.
            string outputMsi = null;
            try
            {
                outputMsi = Path.GetTempFileName();

                if (!this.OnProgress(currentProgress++, totalProgress, "Generating .msi file..."))
                {
                    return(false);
                }

                this.GenerateMsi(sourceDoc, outputMsi);
                if (this.buildError != null)
                {
                    throw new InvalidOperationException(String.Format(this.buildError.ResourceManager.GetString(this.buildError.ResourceName), this.buildError.MessageArgs));
                }

                string assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

                if (!this.OnProgress(currentProgress++, totalProgress, "Generating setup bootstrapper..."))
                {
                    return(false);
                }

                /*
                 * NativeMethods.CREATE_SETUP_PACKAGE[] createSetup = new Microsoft.Tools.WindowsInstallerXml.ClickThrough.NativeMethods.CREATE_SETUP_PACKAGE[1];
                 * createSetup[0].fPrivileged = false;
                 * createSetup[0].fCache = true;
                 * createSetup[0].wzSourcePath = outputMsi;
                 *
                 * int hr = NativeMethods.CreateSetup(Path.Combine(assemblyPath, "setup.exe"), createSetup, createSetup.Length, localSetupExe);
                 */
                int hr = NativeMethods.CreateSimpleSetup(Path.Combine(assemblyPath, "setup.exe"), outputMsi, localSetupExe);
                if (hr != 0)
                {
                    this.OnMessage(ClickThroughErrors.FailedSetupExeCreation(Path.Combine(assemblyPath, "setup.exe"), localSetupExe));
                }

                if (!this.OnProgress(currentProgress++, totalProgress, "Generating update feed..."))
                {
                    return(false);
                }
                this.GenerateRssFeed(localSetupFeed, localSetupExe, urlSetupExe, application.Product.Id, application.Product.UpgradeCode, application.Product.Version);
            }
            finally
            {
                this.OnProgress(currentProgress++, totalProgress, "Cleaning up...");
                if (outputMsi != null)
                {
                    File.Delete(outputMsi);
                }
            }

            if (this.buildError != null)
            {
                throw new InvalidOperationException(String.Format(this.buildError.ResourceManager.GetString(this.buildError.ResourceName), this.buildError.MessageArgs));
            }
            else if (!this.OnProgress(currentProgress++, totalProgress, "Package build complete."))
            {
                return(false);
            }

            return(true);
        }
Esempio n. 3
0
        /// <summary>
        /// Generates the appropriate MSI file for the package.
        /// </summary>
        /// <param name="sourceDoc">WiX document to create MSI from.</param>
        /// <param name="filePath">File path for the RSS feed.</param>
        private void GenerateMsi(XmlDocument sourceDoc, string filePath)
        {
            // Compile
            Compiler compiler = new Compiler();

            compiler.Message += new MessageEventHandler(this.MessageHandler);

            Intermediate intermediate = compiler.Compile(sourceDoc);

            if (intermediate == null)
            {
                return;
            }

            // locate the applib.wixlib
            string assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string applibPath   = Path.Combine(assemblyPath, "applib.wixlib");

            if (!File.Exists(applibPath))
            {
                this.OnMessage(ClickThroughErrors.CannotLoadApplib(applibPath));
                return;
            }

            WixVariableResolver wixVariableResolver = new WixVariableResolver();

            wixVariableResolver.Message += new MessageEventHandler(this.MessageHandler);

            // create the linker
            Linker linker = new Linker();

            linker.Message            += new MessageEventHandler(this.MessageHandler);
            linker.WixVariableResolver = wixVariableResolver;

            // load applib.wixlib
            Library           lowImpactAppLib = Library.Load(applibPath, linker.TableDefinitions, false, false);
            SectionCollection sections        = new SectionCollection();

            sections.AddRange(intermediate.Sections);
            sections.AddRange(lowImpactAppLib.Sections);

            // Link
            Output output = linker.Link(sections);

            if (output == null)
            {
                return;
            }

            Table components = output.Tables["Component"];

            foreach (Row row in components.Rows)
            {
                switch ((string)row[0])
                {
                case "ThisApplicationVersionRegistryKeyComponent":
                    row[1] = String.Concat("{", Guid.NewGuid().ToString().ToUpper(), "}");
                    break;

                case "ThisApplicationCacheFolderComponent":
                    row[1] = String.Concat("{", Guid.NewGuid().ToString().ToUpper(), "}");
                    break;

                case "ThisApplicationShortcutComponent":
                    row[1] = String.Concat("{", Guid.NewGuid().ToString().ToUpper(), "}");
                    break;
                }
            }

            // Bind
            Binder binder = new Binder();

            binder.Extension = new BinderExtension();
            binder.Extension.SourcePaths.Add(Path.GetDirectoryName(filePath));
            binder.Extension.SourcePaths.Add(assemblyPath);
            binder.WixVariableResolver = wixVariableResolver;
            binder.Message            += new MessageEventHandler(this.MessageHandler);
            binder.Bind(output, filePath);

            return;
        }