/// <summary>
        /// Decompile the Shortcut table.
        /// </summary>
        /// <param name="table">The table to decompile.</param>
        private void DecompileShortcutTable(Table table)
        {
            foreach (Row row in table.Rows)
            {
                Wix.Shortcut shortcut = new Wix.Shortcut();

                shortcut.Id = Convert.ToString(row[0]);

                shortcut.Directory = Convert.ToString(row[1]);

                string[] names = Installer.GetNames(Convert.ToString(row[2]));
                if (null != names[0] && null != names[1])
                {
                    shortcut.ShortName = names[0];
                    shortcut.Name = names[1];
                }
                else if (null != names[0])
                {
                    shortcut.Name = names[0];
                }

                string target = Convert.ToString(row[4]);
                if (target.StartsWith("[", StringComparison.Ordinal) && target.EndsWith("]", StringComparison.Ordinal))
                {
                    // TODO: use this value to do a "more-correct" nesting under the indicated File or CreateDirectory element
                    shortcut.Target = target;
                }
                else
                {
                    shortcut.Advertise = Wix.YesNoType.yes;

                    // primary feature is set in FinalizeFeatureComponentsTable
                }

                if (null != row[5])
                {
                    shortcut.Arguments = Convert.ToString(row[5]);
                }

                if (null != row[6])
                {
                    shortcut.Description = Convert.ToString(row[6]);
                }

                if (null != row[7])
                {
                    shortcut.Hotkey = Convert.ToInt32(row[7]);
                }

                if (null != row[8])
                {
                    shortcut.Icon = Convert.ToString(row[8]);
                }

                if (null != row[9])
                {
                    shortcut.IconIndex = Convert.ToInt32(row[9]);
                }

                if (null != row[10])
                {
                    switch (Convert.ToInt32(row[10]))
                    {
                        case 1:
                            shortcut.Show = Wix.Shortcut.ShowType.normal;
                            break;
                        case 3:
                            shortcut.Show = Wix.Shortcut.ShowType.maximized;
                            break;
                        case 7:
                            shortcut.Show = Wix.Shortcut.ShowType.minimized;
                            break;
                        default:
                            this.core.OnMessage(WixWarnings.IllegalColumnValue(row.SourceLineNumbers, table.Name, row.Fields[10].Column.Name, row[10]));
                            break;
                    }
                }

                if (null != row[11])
                {
                    shortcut.WorkingDirectory = Convert.ToString(row[11]);
                }

                // Only try to read the MSI 4.0-specific columns if they actually exist
                if (15 < row.Fields.Length)
                {
                    if (null != row[12])
                    {
                        shortcut.DisplayResourceDll = Convert.ToString(row[12]);
                    }

                    if (null != row[13])
                    {
                        shortcut.DisplayResourceId = Convert.ToInt32(row[13]);
                    }

                    if (null != row[14])
                    {
                        shortcut.DescriptionResourceDll = Convert.ToString(row[14]);
                    }

                    if (null != row[15])
                    {
                        shortcut.DescriptionResourceId = Convert.ToInt32(row[15]);
                    }
                }

                Wix.Component component = (Wix.Component)this.core.GetIndexedElement("Component", Convert.ToString(row[3]));
                if (null != component)
                {
                    component.AddChild(shortcut);
                }
                else
                {
                    this.core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerCore.PrimaryKeyDelimiter), "Component_", Convert.ToString(row[3]), "Component"));
                }

                this.core.IndexElement(row, shortcut);
            }
        }
Beispiel #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);
        }
Beispiel #3
0
        /// <summary>
        /// Returns a Shortcut for each Component in the Directory tree.
        /// </summary>
        /// <param name="">The root Directory of the components.</param>
        private Wix.Shortcut GetShortcut(string relativePath, Wix.Directory directory, Wix.Directory shortcutDirectory)
        {
            Wix.Shortcut shortcut   = null;
            IEnumerable  enumerable = directory.Children;

            string[] dir = relativePath.Split(Path.DirectorySeparatorChar);

            for (int i = 0; i < dir.Length; ++i)
            {
                bool found = false;

                if (i < dir.Length - 1)
                {
                    foreach (Wix.ISchemaElement element in enumerable)
                    {
                        if (element is Wix.Directory)
                        {
                            Wix.Directory dirx = (Wix.Directory)element;
                            if (dir[i] == dirx.LongName)
                            {
                                enumerable = dirx.Children;

                                found = true;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    foreach (Wix.ISchemaElement element in enumerable)
                    {
                        if (element is Wix.Component)
                        {
                            enumerable = ((Wix.Component)element).Children;
                            foreach (Wix.ISchemaElement elementx in enumerable)
                            {
                                if (elementx is Wix.File)
                                {
                                    Wix.File fil = (Wix.File)elementx;
                                    if (dir[i] == fil.LongName)
                                    {
                                        shortcut = new Wix.Shortcut();

                                        shortcut.Id        = String.Concat(fil.Id, "Shortcut");
                                        shortcut.Directory = shortcutDirectory.Id;
                                        shortcut.Target    = "[!SystemApplicationUpdateExeFile]";
                                        shortcut.Name      = "shortcu1";
                                        shortcut.LongName  = Path.GetFileNameWithoutExtension(fil.LongName);
                                        shortcut.Arguments = String.Format(CultureInfo.InvariantCulture, "-ac [UpgradeCode] -cl \"[#{0}]\"", fil.Id);

                                        found = true;
                                        break;
                                    }
                                }
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }
                }

                if (!found)
                {
                    throw new ApplicationException("did not find file name");
                }
            }

            return(shortcut);
        }
Beispiel #4
0
        /// <summary>
        /// Returns a Shortcut for each Component in the Directory tree.
        /// </summary>
        /// <param name="">The root Directory of the components.</param>
        private Wix.Shortcut GetShortcut(string relativePath, Wix.Directory directory, Wix.Directory shortcutDirectory)
        {
            Wix.Shortcut shortcut = null;
            IEnumerable enumerable = directory.Children;
            string[] dir = relativePath.Split(Path.DirectorySeparatorChar);

            for (int i = 0; i < dir.Length; ++i)
            {
                bool found = false;

                if (i < dir.Length - 1)
                {
                    foreach (Wix.ISchemaElement element in enumerable)
                    {
                        if (element is Wix.Directory)
                        {
                            Wix.Directory dirx = (Wix.Directory)element;
                            if (dir[i] == dirx.LongName)
                            {
                                enumerable = dirx.Children;

                                found = true;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    foreach (Wix.ISchemaElement element in enumerable)
                    {
                        if (element is Wix.Component)
                        {
                            enumerable = ((Wix.Component)element).Children;
                            foreach (Wix.ISchemaElement elementx in enumerable)
                            {
                                if (elementx is Wix.File)
                                {
                                    Wix.File fil = (Wix.File)elementx;
                                    if (dir[i] == fil.LongName)
                                    {
                                        shortcut = new Wix.Shortcut();

                                        shortcut.Id = String.Concat(fil.Id, "Shortcut");
                                        shortcut.Directory = shortcutDirectory.Id;
                                        shortcut.Target = "[!SystemApplicationUpdateExeFile]";
                                        shortcut.Name = "shortcu1";
                                        shortcut.LongName = Path.GetFileNameWithoutExtension(fil.LongName);
                                        shortcut.Arguments = String.Format(CultureInfo.InvariantCulture, "-ac [UpgradeCode] -cl \"[#{0}]\"", fil.Id);

                                        found = true;
                                        break;
                                    }
                                }
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }
                }

                if (!found)
                {
                    throw new ApplicationException("did not find file name");
                }
            }

            return shortcut;
        }