示例#1
0
        /// <summary>
        /// Gets whether certain properties are the same.
        /// </summary>
        /// <param name="other">Another <see cref="ProvidesDependency"/> to compare.</param>
        /// <remarks>This is not the same as object equality, but only checks a subset of properties
        /// to determine if the objects are similar and could be merged into a collection.</remarks>
        /// <returns>True if certain properties are the same.</returns>
        internal bool Equals(ProvidesDependency other)
        {
            if (null != other)
            {
                return(this.Key == other.Key &&
                       this.Version == other.Version &&
                       this.DisplayName == other.DisplayName);
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Initializes package state from the MSI contents.
        /// </summary>
        private void ResolveMsiPackage(BinderFileManager fileManager, Dictionary<string, PayloadInfoRow> allPayloads, Dictionary<string, ContainerInfo> containers, YesNoType suppressLooseFilePayloadGeneration, YesNoType enableFeatureSelection, YesNoType forcePerMachine, Output bundle)
        {
            string sourcePath = this.PackagePayload.FullFileName;
            bool longNamesInImage = false;
            bool compressed = false;
            try
            {
                // Read data out of the msi database...
                using (Microsoft.Deployment.WindowsInstaller.SummaryInfo sumInfo = new Microsoft.Deployment.WindowsInstaller.SummaryInfo(sourcePath, false))
                {
                    // 1 is the Word Count summary information stream bit that means
                    // the MSI uses short file names when set. We care about long file
                    // names so check when the bit is not set.
                    longNamesInImage = 0 == (sumInfo.WordCount & 1);

                    // 2 is the Word Count summary information stream bit that means
                    // files are compressed in the MSI by default when the bit is set.
                    compressed = 2 == (sumInfo.WordCount & 2);

                    // 8 is the Word Count summary information stream bit that means
                    // "Elevated privileges are not required to install this package."
                    // in MSI 4.5 and below, if this bit is 0, elevation is required.
                    this.PerMachine = (0 == (sumInfo.WordCount & 8)) ? YesNoDefaultType.Yes : YesNoDefaultType.No;
                }

                using (Microsoft.Deployment.WindowsInstaller.Database db = new Microsoft.Deployment.WindowsInstaller.Database(sourcePath))
                {
                    this.ProductCode = ChainPackageInfo.GetProperty(db, "ProductCode");
                    this.Language = ChainPackageInfo.GetProperty(db, "ProductLanguage");
                    this.Version = ChainPackageInfo.GetProperty(db, "ProductVersion");

                    if (!Common.IsValidModuleOrBundleVersion(this.Version))
                    {
                        // not a proper .NET version (i.e., five fields); can we get a valid version number up to four fields?
                        string version = null;
                        string[] versionParts = this.Version.Split('.');
                        int count = versionParts.Length;
                        if (0 < count)
                        {
                            version = versionParts[0];
                            for (int i = 1; i < 4 && i < count; ++i)
                            {
                                version = String.Concat(version, ".", versionParts[i]);
                            }
                        }

                        if (!String.IsNullOrEmpty(version) && Common.IsValidModuleOrBundleVersion(version))
                        {
                            this.core.OnMessage(WixWarnings.VersionTruncated(this.PackagePayload.SourceLineNumbers, this.Version, sourcePath, version));
                            this.Version = version;
                        }
                        else
                        {
                            this.core.OnMessage(WixErrors.InvalidProductVersion(this.PackagePayload.SourceLineNumbers, this.Version, sourcePath));
                        }
                    }

                    if (String.IsNullOrEmpty(this.CacheId))
                    {
                        this.CacheId = String.Format("{0}v{1}", this.ProductCode, this.Version);
                    }

                    if (String.IsNullOrEmpty(this.DisplayName))
                    {
                        this.DisplayName = ChainPackageInfo.GetProperty(db, "ProductName");
                    }

                    this.Manufacturer = ChainPackageInfo.GetProperty(db, "Manufacturer");

                    this.VerifyMsiProperties();

                    if (YesNoType.Yes == forcePerMachine)
                    {
                        if (YesNoDefaultType.No == this.PerMachine)
                        {
                            this.core.OnMessage(WixWarnings.PerUserButForcingPerMachine(this.PackagePayload.SourceLineNumbers, sourcePath));
                            this.PerMachine = YesNoDefaultType.Yes; // ensure that we think the MSI is per-machine.
                        }

                        this.MsiProperties.Add(new MsiPropertyInfo(this.Id, "ALLUSERS", "1")); // force ALLUSERS=1 via the MSI command-line.
                    }
                    else if (ChainPackageInfo.HasProperty(db, "ALLUSERS"))
                    {
                        string allusers = ChainPackageInfo.GetProperty(db, "ALLUSERS");
                        if (allusers.Equals("1", StringComparison.Ordinal))
                        {
                            if (YesNoDefaultType.No == this.PerMachine)
                            {
                                this.core.OnMessage(WixErrors.PerUserButAllUsersEquals1(this.PackagePayload.SourceLineNumbers, sourcePath));
                            }
                        }
                        else if (allusers.Equals("2", StringComparison.Ordinal))
                        {
                            this.core.OnMessage(WixWarnings.DiscouragedAllUsersValue(this.PackagePayload.SourceLineNumbers, sourcePath, (YesNoDefaultType.Yes == this.PerMachine) ? "machine" : "user"));
                        }
                        else
                        {
                            this.core.OnMessage(WixErrors.UnsupportedAllUsersValue(this.PackagePayload.SourceLineNumbers, sourcePath, allusers));
                        }
                    }
                    else if (YesNoDefaultType.Yes == this.PerMachine) // not forced per-machine and no ALLUSERS property, flip back to per-user
                    {
                        this.core.OnMessage(WixWarnings.ImplicitlyPerUser(this.PackagePayload.SourceLineNumbers, sourcePath));
                        this.PerMachine = YesNoDefaultType.No;
                    }

                    if (String.IsNullOrEmpty(this.Description) && ChainPackageInfo.HasProperty(db, "ARPCOMMENTS"))
                    {
                        this.Description = ChainPackageInfo.GetProperty(db, "ARPCOMMENTS");
                    }

                    // Ensure the MSI package is appropriately marked visible or not.
                    bool alreadyVisible = !ChainPackageInfo.HasProperty(db, "ARPSYSTEMCOMPONENT");
                    if (alreadyVisible != this.Visible) // if not already set to the correct visibility.
                    {
                        // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again.
                        bool sysComponentSet = false;
                        foreach (MsiPropertyInfo propertyInfo in this.MsiProperties)
                        {
                            if ("ARPSYSTEMCOMPONENT".Equals(propertyInfo.Name, StringComparison.Ordinal))
                            {
                                sysComponentSet = true;
                                break;
                            }
                        }

                        if (!sysComponentSet)
                        {
                            this.MsiProperties.Add(new MsiPropertyInfo(this.Id, "ARPSYSTEMCOMPONENT", this.Visible ? "" : "1"));
                        }
                    }

                    // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance.
                    if (!ChainPackageInfo.HasProperty(db, "MSIFASTINSTALL"))
                    {
                        bool fastInstallSet = false;
                        foreach (MsiPropertyInfo propertyInfo in this.MsiProperties)
                        {
                            if ("MSIFASTINSTALL".Equals(propertyInfo.Name, StringComparison.Ordinal))
                            {
                                fastInstallSet = true;
                                break;
                            }
                        }

                        if (!fastInstallSet)
                        {
                            this.MsiProperties.Add(new MsiPropertyInfo(this.Id, "MSIFASTINSTALL", "7"));
                        }
                    }

                    this.UpgradeCode = ChainPackageInfo.GetProperty(db, "UpgradeCode");

                        // Represent the Upgrade table as related packages.
                    if (db.Tables.Contains("Upgrade") && !String.IsNullOrEmpty(this.UpgradeCode))
                    {
                        using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView("SELECT `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes` FROM `Upgrade`"))
                        {
                            view.Execute();
                            while (true)
                            {
                                using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch())
                                {
                                    if (null == record)
                                    {
                                        break;
                                    }

                                    RelatedPackage related = new RelatedPackage();
                                    related.Id = record.GetString(1);
                                    related.MinVersion = record.GetString(2);
                                    related.MaxVersion = record.GetString(3);

                                    string languages = record.GetString(4);
                                    if (!String.IsNullOrEmpty(languages))
                                    {
                                        string[] splitLanguages = languages.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                        related.Languages.AddRange(splitLanguages);
                                    }

                                    int attributes = record.GetInteger(5);
                                    // when an Upgrade row has an upgrade code different than this package's upgrade code, don't count it as a possible downgrade to this package
                                    related.OnlyDetect = ((attributes & MsiInterop.MsidbUpgradeAttributesOnlyDetect) == MsiInterop.MsidbUpgradeAttributesOnlyDetect) && this.UpgradeCode.Equals(related.Id, StringComparison.OrdinalIgnoreCase);
                                    related.MinInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesVersionMinInclusive) == MsiInterop.MsidbUpgradeAttributesVersionMinInclusive;
                                    related.MaxInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive) == MsiInterop.MsidbUpgradeAttributesVersionMaxInclusive;
                                    related.LangInclusive = (attributes & MsiInterop.MsidbUpgradeAttributesLanguagesExclusive) == 0;

                                    this.RelatedPackages.Add(related);
                                }
                            }
                        }
                    }

                    // If feature selection is enabled, represent the Feature table in the manifest.
                    if (YesNoType.Yes == enableFeatureSelection && db.Tables.Contains("Feature"))
                    {
                        using (Microsoft.Deployment.WindowsInstaller.View featureView = db.OpenView("SELECT `Component_` FROM `FeatureComponents` WHERE `Feature_` = ?"),
                                    componentView = db.OpenView("SELECT `FileSize` FROM `File` WHERE `Component_` = ?"))
                        {
                            using (Microsoft.Deployment.WindowsInstaller.Record featureRecord = new Microsoft.Deployment.WindowsInstaller.Record(1),
                                          componentRecord = new Microsoft.Deployment.WindowsInstaller.Record(1))
                            {
                                using (Microsoft.Deployment.WindowsInstaller.View allFeaturesView = db.OpenView("SELECT * FROM `Feature`"))
                                {
                                    allFeaturesView.Execute();

                                    while (true)
                                    {
                                        using (Microsoft.Deployment.WindowsInstaller.Record allFeaturesResultRecord = allFeaturesView.Fetch())
                                        {
                                            if (null == allFeaturesResultRecord)
                                            {
                                                break;
                                            }

                                            MsiFeature feature = new MsiFeature();
                                            string featureName = allFeaturesResultRecord.GetString(1);
                                            feature.Name = featureName;
                                            feature.Size = 0;
                                            feature.Parent = allFeaturesResultRecord.GetString(2);
                                            feature.Title = allFeaturesResultRecord.GetString(3);
                                            feature.Description = allFeaturesResultRecord.GetString(4);
                                            feature.Display = allFeaturesResultRecord.GetInteger(5);
                                            feature.Level = allFeaturesResultRecord.GetInteger(6);
                                            feature.Directory = allFeaturesResultRecord.GetString(7);
                                            feature.Attributes = allFeaturesResultRecord.GetInteger(8);
                                            this.MsiFeatures.Add(feature);

                                            // Determine Feature Size
                                            featureRecord.SetString(1, featureName);
                                            featureView.Execute(featureRecord);

                                            // Loop over all the components
                                            while (true)
                                            {
                                                using (Microsoft.Deployment.WindowsInstaller.Record componentResultRecord = featureView.Fetch())
                                                {
                                                    if (null == componentResultRecord)
                                                    {
                                                        break;
                                                    }
                                                    string component = componentResultRecord.GetString(1);
                                                    componentRecord.SetString(1, component);
                                                    componentView.Execute(componentRecord);

                                                    // Loop over all the files

                                                    while (true)
                                                    {
                                                        using (Microsoft.Deployment.WindowsInstaller.Record fileResultRecord = componentView.Fetch())
                                                        {
                                                            if (null == fileResultRecord)
                                                            {
                                                                break;
                                                            }

                                                            string fileSize = fileResultRecord.GetString(1);
                                                            feature.Size += Convert.ToInt32(fileSize, CultureInfo.InvariantCulture.NumberFormat);
                                                        }
                                                    }

                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Add all external cabinets as package payloads.
                    if (db.Tables.Contains("Media"))
                    {
                        foreach (string cabinet in db.ExecuteStringQuery("SELECT `Cabinet` FROM `Media`"))
                        {
                            if (!String.IsNullOrEmpty(cabinet) && !cabinet.StartsWith("#", StringComparison.Ordinal))
                            {
                                // If we didn't find the Payload as an existing child of the package, we need to
                                // add it.  We expect the file to exist on-disk in the same relative location as
                                // the MSI expects to find it...
                                string cabinetName = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), cabinet);
                                if (!this.IsExistingPayload(cabinetName))
                                {
                                    string generatedId = Common.GenerateIdentifier("cab", true, this.PackagePayload.Id, cabinet);
                                    string payloadSourceFile = fileManager.ResolveRelatedFile(this.PackagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.PackagePayload.SourceLineNumbers, BindStage.Normal);

                                    PayloadInfoRow payloadNew = PayloadInfoRow.Create(this.SourceLineNumbers, bundle, generatedId, cabinetName, payloadSourceFile, true, this.PackagePayload.SuppressSignatureValidation, null, this.PackagePayload.Container, this.PackagePayload.Packaging);
                                    payloadNew.ParentPackagePayload = this.PackagePayload.Id;
                                    if (!String.IsNullOrEmpty(payloadNew.Container))
                                    {
                                        containers[payloadNew.Container].Payloads.Add(payloadNew);
                                    }

                                    this.Payloads.Add(payloadNew);
                                    allPayloads.Add(payloadNew.Id, payloadNew);

                                    this.Size += payloadNew.FileSize; // add the newly added payload to the package size.
                                }
                            }
                        }
                    }

                    // Add all external files as package payloads and calculate the total install size as the rollup of
                    // File table's sizes.
                    this.InstallSize = 0;
                    if (db.Tables.Contains("Component") && db.Tables.Contains("Directory") && db.Tables.Contains("File"))
                    {
                        Hashtable directories = new Hashtable();

                        // Load up the directory hash table so we will be able to resolve source paths
                        // for files in the MSI database.
                        using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`"))
                        {
                            view.Execute();
                            while (true)
                            {
                                using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch())
                                {
                                    if (null == record)
                                    {
                                        break;
                                    }
                                    string sourceName = Installer.GetName(record.GetString(3), true, longNamesInImage);
                                    directories.Add(record.GetString(1), new ResolvedDirectory(record.GetString(2), sourceName));
                                }
                            }
                        }

                        // Resolve the source paths to external files and add each file size to the total
                        // install size of the package.
                        using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`"))
                        {
                            view.Execute();
                            while (true)
                            {
                                using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch())
                                {
                                    if (null == record)
                                    {
                                        break;
                                    }

                                    // Skip adding the loose files as payloads if it was suppressed.
                                    if (suppressLooseFilePayloadGeneration != YesNoType.Yes)
                                    {
                                        // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not
                                        // explicitly marked compressed then this is an external file.
                                        if (MsiInterop.MsidbFileAttributesNoncompressed == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesNoncompressed) ||
                                            (!compressed && 0 == (record.GetInteger(4) & MsiInterop.MsidbFileAttributesCompressed)))
                                        {
                                            string generatedId = Common.GenerateIdentifier("f", true, this.PackagePayload.Id, record.GetString(2));
                                            string fileSourcePath = Binder.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage);
                                            string payloadSourceFile = fileManager.ResolveRelatedFile(this.PackagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.PackagePayload.SourceLineNumbers, BindStage.Normal);
                                            string name = Path.Combine(Path.GetDirectoryName(this.PackagePayload.Name), fileSourcePath);

                                            if (!this.IsExistingPayload(name))
                                            {
                                                PayloadInfoRow payloadNew = PayloadInfoRow.Create(this.SourceLineNumbers, bundle, generatedId, name, payloadSourceFile, true, this.PackagePayload.SuppressSignatureValidation, null, this.PackagePayload.Container, this.PackagePayload.Packaging);
                                                payloadNew.ParentPackagePayload = this.PackagePayload.Id;
                                                if (!String.IsNullOrEmpty(payloadNew.Container))
                                                {
                                                    containers[payloadNew.Container].Payloads.Add(payloadNew);
                                                }

                                                this.Payloads.Add(payloadNew);
                                                allPayloads.Add(payloadNew.Id, payloadNew);

                                                this.Size += payloadNew.FileSize; // add the newly added payload to the package size.
                                            }
                                        }
                                    }

                                    this.InstallSize += record.GetInteger(5);
                                }
                            }
                        }
                    }

                    // Import any dependency providers from the MSI.
                    if (db.Tables.Contains("WixDependencyProvider"))
                    {
                        // Use the old schema (v1) if the Version column does not exist.
                        bool hasVersion = db.Tables["WixDependencyProvider"].Columns.Contains("Version");
                        string query = "SELECT `ProviderKey`, `Version`, `DisplayName`, `Attributes` FROM `WixDependencyProvider`";

                        if (!hasVersion)
                        {
                            query = "SELECT `ProviderKey`, `Attributes` FROM `WixDependencyProvider`";
                        }

                        using (Microsoft.Deployment.WindowsInstaller.View view = db.OpenView(query))
                        {
                            view.Execute();
                            while (true)
                            {
                                using (Microsoft.Deployment.WindowsInstaller.Record record = view.Fetch())
                                {
                                    if (null == record)
                                    {
                                        break;
                                    }

                                    // Import the provider key and attributes.
                                    ProvidesDependency dependency = null;
                                    string providerKey = record.GetString(1);

                                    if (hasVersion)
                                    {
                                        string version = record.GetString(2) ?? this.Version;
                                        string displayName = record.GetString(3) ?? this.DisplayName;
                                        int attributes = record.GetInteger(4);

                                        dependency = new ProvidesDependency(providerKey, version, displayName, attributes);
                                    }
                                    else
                                    {
                                        int attributes = record.GetInteger(2);

                                        dependency = new ProvidesDependency(providerKey, this.Version, this.DisplayName, attributes);
                                    }

                                    dependency.Imported = true;
                                    this.Provides.Add(dependency);
                                }
                            }
                        }
                    }
                }
            }
            catch (Microsoft.Deployment.WindowsInstaller.InstallerException e)
            {
                this.core.OnMessage(WixErrors.UnableToReadPackageInformation(this.PackagePayload.SourceLineNumbers, sourcePath, e.Message));
            }
        }
示例#3
0
文件: Binder.cs 项目: zooba/wix3
        /// <summary>
        /// Imports authored dependency providers for each package in the manifest,
        /// and generates dependency providers for certain package types that do not
        /// have a provider defined.
        /// </summary>
        /// <param name="bundle">The <see cref="Output"/> object for the bundle.</param>
        /// <param name="packages">An indexed collection of chained packages.</param>
        private void ProcessDependencyProviders(Output bundle, Dictionary<string, ChainPackageInfo> packages)
        {
            // First import any authored dependencies. These may merge with imported provides from MSI packages.
            Table wixDependencyProviderTable = bundle.Tables["WixDependencyProvider"];
            if (null != wixDependencyProviderTable && 0 < wixDependencyProviderTable.Rows.Count)
            {
                // Add package information for each dependency provider authored into the manifest.
                foreach (Row wixDependencyProviderRow in wixDependencyProviderTable.Rows)
                {
                    string packageId = (string)wixDependencyProviderRow[1];

                    ChainPackageInfo package = null;
                    if (packages.TryGetValue(packageId, out package))
                    {
                        ProvidesDependency dependency = new ProvidesDependency(wixDependencyProviderRow);

                        if (String.IsNullOrEmpty(dependency.Key))
                        {
                            switch (package.ChainPackageType)
                            {
                                // The WixDependencyExtension allows an empty Key for MSIs and MSPs.
                                case Compiler.ChainPackageType.Msi:
                                    dependency.Key = package.ProductCode;
                                    break;
                                case Compiler.ChainPackageType.Msp:
                                    dependency.Key = package.PatchCode;
                                    break;
                            }
                        }

                        if (String.IsNullOrEmpty(dependency.Version))
                        {
                            dependency.Version = package.Version;
                        }

                        // If the version is still missing, a version could not be harvested from the package and was not authored.
                        if (String.IsNullOrEmpty(dependency.Version))
                        {
                            this.core.OnMessage(WixErrors.MissingDependencyVersion(package.Id));
                        }

                        if (String.IsNullOrEmpty(dependency.DisplayName))
                        {
                            dependency.DisplayName = package.DisplayName;
                        }

                        if (!package.Provides.Merge(dependency))
                        {
                            this.core.OnMessage(WixErrors.DuplicateProviderDependencyKey(dependency.Key, package.Id));
                        }
                    }
                }
            }

            // Generate providers for MSI packages that still do not have providers.
            foreach (ChainPackageInfo package in packages.Values)
            {
                if (Compiler.ChainPackageType.Msi == package.ChainPackageType && 0 == package.Provides.Count)
                {
                    ProvidesDependency dependency = new ProvidesDependency(package.ProductCode, package.Version, package.DisplayName, 0);

                    if (!package.Provides.Merge(dependency))
                    {
                        this.core.OnMessage(WixErrors.DuplicateProviderDependencyKey(dependency.Key, package.Id));
                    }
                }
                else if (Compiler.ChainPackageType.Msp == package.ChainPackageType && 0 == package.Provides.Count)
                {
                    ProvidesDependency dependency = new ProvidesDependency(package.PatchCode, package.Version, package.DisplayName, 0);

                    if (!package.Provides.Merge(dependency))
                    {
                        this.core.OnMessage(WixErrors.DuplicateProviderDependencyKey(dependency.Key, package.Id));
                    }
                }
            }
        }
示例#4
0
        /// <summary>
        /// Gets whether certain properties are the same.
        /// </summary>
        /// <param name="other">Another <see cref="ProvidesDependency"/> to compare.</param>
        /// <remarks>This is not the same as object equality, but only checks a subset of properties
        /// to determine if the objects are similar and could be merged into a collection.</remarks>
        /// <returns>True if certain properties are the same.</returns>
        internal bool Equals(ProvidesDependency other)
        {
            if (null != other)
            {
                return this.Key == other.Key &&
                       this.Version == other.Version &&
                       this.DisplayName == other.DisplayName;
            }

            return false;
        }