diff options
Diffstat (limited to 'src')
5 files changed, 257 insertions, 358 deletions
diff --git a/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs b/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs index 8584d2a4..f9ff23cb 100644 --- a/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs +++ b/src/WixToolset.Core.Burn/Bind/ProcessBundleSoftwareTagsCommand.cs | |||
| @@ -8,9 +8,9 @@ namespace WixToolset.Core.Burn.Bind | |||
| 8 | using System.Linq; | 8 | using System.Linq; |
| 9 | using System.Text; | 9 | using System.Text; |
| 10 | using System.Xml; | 10 | using System.Xml; |
| 11 | using WixToolset.Core.Native.Msi; | ||
| 11 | using WixToolset.Data; | 12 | using WixToolset.Data; |
| 12 | using WixToolset.Data.Symbols; | 13 | using WixToolset.Data.Symbols; |
| 13 | using WixToolset.Dtf.WindowsInstaller; | ||
| 14 | 14 | ||
| 15 | internal class ProcessBundleSoftwareTagsCommand | 15 | internal class ProcessBundleSoftwareTagsCommand |
| 16 | { | 16 | { |
| @@ -69,22 +69,13 @@ namespace WixToolset.Core.Burn.Bind | |||
| 69 | { | 69 | { |
| 70 | var payload = payloadSymbolsById[msiPackage.PayloadRef]; | 70 | var payload = payloadSymbolsById[msiPackage.PayloadRef]; |
| 71 | 71 | ||
| 72 | using (var db = new Database(payload.SourceFile.Path)) | 72 | using (var db = new Database(payload.SourceFile.Path, OpenDatabase.ReadOnly)) |
| 73 | { | 73 | { |
| 74 | using (var view = db.OpenView("SELECT `Regid`, `TagId` FROM `SoftwareIdentificationTag`")) | 74 | using (var view = db.OpenExecuteView("SELECT `Regid`, `TagId` FROM `SoftwareIdentificationTag`")) |
| 75 | { | 75 | { |
| 76 | view.Execute(); | 76 | foreach (var record in view.Records) |
| 77 | while (true) | ||
| 78 | { | 77 | { |
| 79 | using (var record = view.Fetch()) | 78 | tags.Add(new SoftwareTag { Regid = record.GetString(1), Id = record.GetString(2) }); |
| 80 | { | ||
| 81 | if (null == record) | ||
| 82 | { | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | |||
| 86 | tags.Add(new SoftwareTag { Regid = record.GetString(1), Id = record.GetString(2) }); | ||
| 87 | } | ||
| 88 | } | 79 | } |
| 89 | } | 80 | } |
| 90 | } | 81 | } |
| @@ -98,7 +89,7 @@ namespace WixToolset.Core.Burn.Bind | |||
| 98 | { | 89 | { |
| 99 | var versionScheme = Version.TryParse(version, out _) ? "multipartnumeric" : "alphanumeric"; | 90 | var versionScheme = Version.TryParse(version, out _) ? "multipartnumeric" : "alphanumeric"; |
| 100 | 91 | ||
| 101 | using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true})) | 92 | using (var writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true })) |
| 102 | { | 93 | { |
| 103 | writer.WriteStartDocument(); | 94 | writer.WriteStartDocument(); |
| 104 | writer.WriteStartElement("SoftwareIdentity", "http://standards.iso.org/iso/19770/-2/2015/schema.xsd"); | 95 | writer.WriteStartElement("SoftwareIdentity", "http://standards.iso.org/iso/19770/-2/2015/schema.xsd"); |
diff --git a/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs b/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs index 6d6ae427..99e2eda5 100644 --- a/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/ProcessMsiPackageCommand.cs | |||
| @@ -4,24 +4,23 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Diagnostics; | ||
| 8 | using System.Globalization; | 7 | using System.Globalization; |
| 9 | using System.IO; | 8 | using System.IO; |
| 10 | using System.Linq; | 9 | using System.Linq; |
| 11 | using WixToolset.Data; | 10 | using WixToolset.Data; |
| 12 | using WixToolset.Extensibility; | 11 | using WixToolset.Extensibility; |
| 13 | using Dtf = WixToolset.Dtf.WindowsInstaller; | ||
| 14 | using WixToolset.Extensibility.Services; | 12 | using WixToolset.Extensibility.Services; |
| 15 | using WixToolset.Data.Symbols; | 13 | using WixToolset.Data.Symbols; |
| 16 | using WixToolset.Data.WindowsInstaller; | 14 | using WixToolset.Data.WindowsInstaller; |
| 17 | using WixToolset.Extensibility.Data; | 15 | using WixToolset.Extensibility.Data; |
| 16 | using WixToolset.Core.Native.Msi; | ||
| 18 | 17 | ||
| 19 | /// <summary> | 18 | /// <summary> |
| 20 | /// Initializes package state from the MSI contents. | 19 | /// Initializes package state from the MSI contents. |
| 21 | /// </summary> | 20 | /// </summary> |
| 22 | internal class ProcessMsiPackageCommand | 21 | internal class ProcessMsiPackageCommand |
| 23 | { | 22 | { |
| 24 | private const string PropertySqlFormat = "SELECT `Value` FROM `Property` WHERE `Property` = '{0}'"; | 23 | private const string PropertySqlQuery = "SELECT `Value` FROM `Property` WHERE `Property` = ?"; |
| 25 | 24 | ||
| 26 | public ProcessMsiPackageCommand(IServiceProvider serviceProvider, IEnumerable<IBurnBackendBinderExtension> backendExtensions, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> packagePayloads) | 25 | public ProcessMsiPackageCommand(IServiceProvider serviceProvider, IEnumerable<IBurnBackendBinderExtension> backendExtensions, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> packagePayloads) |
| 27 | { | 26 | { |
| @@ -64,41 +63,60 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 64 | var compressed = false; | 63 | var compressed = false; |
| 65 | try | 64 | try |
| 66 | { | 65 | { |
| 67 | // Read data out of the msi database... | 66 | using (var db = new Database(sourcePath, OpenDatabase.ReadOnly)) |
| 68 | using (var sumInfo = new Dtf.SummaryInfo(sourcePath, false)) | ||
| 69 | { | 67 | { |
| 70 | // 1 is the Word Count summary information stream bit that means | 68 | // Read data out of the msi database... |
| 71 | // the MSI uses short file names when set. We care about long file | 69 | using (var sumInfo = new SummaryInformation(db)) |
| 72 | // names so check when the bit is not set. | 70 | { |
| 73 | longNamesInImage = 0 == (sumInfo.WordCount & 1); | 71 | var fileAndElevateFlags = sumInfo.GetNumericProperty(SummaryInformation.Package.FileAndElevatedFlags); |
| 74 | 72 | var platformsAndLanguages = sumInfo.GetProperty(SummaryInformation.Package.PlatformsAndLanguages); | |
| 75 | // 2 is the Word Count summary information stream bit that means | ||
| 76 | // files are compressed in the MSI by default when the bit is set. | ||
| 77 | compressed = 2 == (sumInfo.WordCount & 2); | ||
| 78 | |||
| 79 | // 8 is the Word Count summary information stream bit that means | ||
| 80 | // "Elevated privileges are not required to install this package." | ||
| 81 | // in MSI 4.5 and below, if this bit is 0, elevation is required. | ||
| 82 | var perMachine = (0 == (sumInfo.WordCount & 8)); | ||
| 83 | var x64 = sumInfo.Template.Contains("x64"); | ||
| 84 | |||
| 85 | this.Facade.PackageSymbol.PerMachine = perMachine ? YesNoDefaultType.Yes : YesNoDefaultType.No; | ||
| 86 | this.Facade.PackageSymbol.Win64 = x64; | ||
| 87 | } | ||
| 88 | 73 | ||
| 89 | using (var db = new Dtf.Database(sourcePath)) | 74 | // 1 is the Word Count summary information stream bit that means |
| 90 | { | 75 | // the MSI uses short file names when set. We care about long file |
| 91 | msiPackage.ProductCode = ProcessMsiPackageCommand.GetProperty(db, "ProductCode"); | 76 | // names so check when the bit is not set. |
| 92 | msiPackage.UpgradeCode = ProcessMsiPackageCommand.GetProperty(db, "UpgradeCode"); | 77 | |
| 93 | msiPackage.Manufacturer = ProcessMsiPackageCommand.GetProperty(db, "Manufacturer"); | 78 | longNamesInImage = 0 == (fileAndElevateFlags & 1); |
| 94 | msiPackage.ProductLanguage = Convert.ToInt32(ProcessMsiPackageCommand.GetProperty(db, "ProductLanguage"), CultureInfo.InvariantCulture); | 79 | |
| 95 | msiPackage.ProductVersion = ProcessMsiPackageCommand.GetProperty(db, "ProductVersion"); | 80 | // 2 is the Word Count summary information stream bit that means |
| 81 | // files are compressed in the MSI by default when the bit is set. | ||
| 82 | compressed = 2 == (fileAndElevateFlags & 2); | ||
| 83 | |||
| 84 | // 8 is the Word Count summary information stream bit that means | ||
| 85 | // "Elevated privileges are not required to install this package." | ||
| 86 | // in MSI 4.5 and below, if this bit is 0, elevation is required. | ||
| 87 | var perMachine = (0 == (fileAndElevateFlags & 8)); | ||
| 88 | var x64 = platformsAndLanguages.Contains("x64"); | ||
| 89 | |||
| 90 | this.Facade.PackageSymbol.PerMachine = perMachine ? YesNoDefaultType.Yes : YesNoDefaultType.No; | ||
| 91 | this.Facade.PackageSymbol.Win64 = x64; | ||
| 92 | } | ||
| 93 | |||
| 94 | string packageName = null; | ||
| 95 | string packageDescription = null; | ||
| 96 | string allusers = null; | ||
| 97 | string fastInstall = null; | ||
| 98 | string systemComponent = null; | ||
| 99 | |||
| 100 | using (var view = db.OpenView(PropertySqlQuery)) | ||
| 101 | { | ||
| 102 | packageName = ProcessMsiPackageCommand.GetProperty(view, "ProductName"); | ||
| 103 | packageDescription = ProcessMsiPackageCommand.GetProperty(view, "ARPCOMMENTS"); | ||
| 104 | allusers = ProcessMsiPackageCommand.GetProperty(view, "ALLUSERS"); | ||
| 105 | fastInstall = ProcessMsiPackageCommand.GetProperty(view, "MSIFASTINSTALL"); | ||
| 106 | systemComponent = ProcessMsiPackageCommand.GetProperty(view, "ARPSYSTEMCOMPONENT"); | ||
| 107 | |||
| 108 | msiPackage.ProductCode = ProcessMsiPackageCommand.GetProperty(view, "ProductCode"); | ||
| 109 | msiPackage.UpgradeCode = ProcessMsiPackageCommand.GetProperty(view, "UpgradeCode"); | ||
| 110 | msiPackage.Manufacturer = ProcessMsiPackageCommand.GetProperty(view, "Manufacturer"); | ||
| 111 | msiPackage.ProductLanguage = Convert.ToInt32(ProcessMsiPackageCommand.GetProperty(view, "ProductLanguage"), CultureInfo.InvariantCulture); | ||
| 112 | msiPackage.ProductVersion = ProcessMsiPackageCommand.GetProperty(view, "ProductVersion"); | ||
| 113 | } | ||
| 96 | 114 | ||
| 97 | if (!this.BackendHelper.IsValidFourPartVersion(msiPackage.ProductVersion)) | 115 | if (!this.BackendHelper.IsValidFourPartVersion(msiPackage.ProductVersion)) |
| 98 | { | 116 | { |
| 99 | // not a proper .NET version (e.g., five fields); can we get a valid four-part version number? | 117 | // not a proper .NET version (e.g., five fields); can we get a valid four-part version number? |
| 100 | string version = null; | 118 | string version = null; |
| 101 | string[] versionParts = msiPackage.ProductVersion.Split('.'); | 119 | var versionParts = msiPackage.ProductVersion.Split('.'); |
| 102 | var count = versionParts.Length; | 120 | var count = versionParts.Length; |
| 103 | if (0 < count) | 121 | if (0 < count) |
| 104 | { | 122 | { |
| @@ -127,12 +145,12 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 127 | 145 | ||
| 128 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) | 146 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) |
| 129 | { | 147 | { |
| 130 | this.Facade.PackageSymbol.DisplayName = ProcessMsiPackageCommand.GetProperty(db, "ProductName"); | 148 | this.Facade.PackageSymbol.DisplayName = packageName; |
| 131 | } | 149 | } |
| 132 | 150 | ||
| 133 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description)) | 151 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description)) |
| 134 | { | 152 | { |
| 135 | this.Facade.PackageSymbol.Description = ProcessMsiPackageCommand.GetProperty(db, "ARPCOMMENTS"); | 153 | this.Facade.PackageSymbol.Description = packageDescription; |
| 136 | } | 154 | } |
| 137 | 155 | ||
| 138 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Version)) | 156 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Version)) |
| @@ -144,13 +162,13 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 144 | 162 | ||
| 145 | var msiPropertyNames = this.GetMsiPropertyNames(packagePayload.Id.Id); | 163 | var msiPropertyNames = this.GetMsiPropertyNames(packagePayload.Id.Id); |
| 146 | 164 | ||
| 147 | this.SetPerMachineAppropriately(db, msiPackage, sourcePath); | 165 | this.SetPerMachineAppropriately(allusers, msiPackage, sourcePath); |
| 148 | 166 | ||
| 149 | // Ensure the MSI package is appropriately marked visible or not. | 167 | // Ensure the MSI package is appropriately marked visible or not. |
| 150 | this.SetPackageVisibility(db, msiPackage, msiPropertyNames); | 168 | this.SetPackageVisibility(systemComponent, msiPackage, msiPropertyNames); |
| 151 | 169 | ||
| 152 | // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance. | 170 | // Unless the MSI or setup code overrides the default, set MSIFASTINSTALL for best performance. |
| 153 | if (!msiPropertyNames.Contains("MSIFASTINSTALL") && !ProcessMsiPackageCommand.HasProperty(db, "MSIFASTINSTALL")) | 171 | if (!String.IsNullOrEmpty(fastInstall)) |
| 154 | { | 172 | { |
| 155 | this.AddMsiProperty(msiPackage, "MSIFASTINSTALL", "7"); | 173 | this.AddMsiProperty(msiPackage, "MSIFASTINSTALL", "7"); |
| 156 | } | 174 | } |
| @@ -171,10 +189,10 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 171 | this.Facade.PackageSymbol.InstallSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, packagePayload, longNamesInImage, compressed, payloadNames); | 189 | this.Facade.PackageSymbol.InstallSize = this.ImportExternalFileAsPayloadsAndReturnInstallSize(db, packagePayload, longNamesInImage, compressed, payloadNames); |
| 172 | 190 | ||
| 173 | // Add all dependency providers from the MSI. | 191 | // Add all dependency providers from the MSI. |
| 174 | this.ImportDependencyProviders(msiPackage, db); | 192 | this.ImportDependencyProviders(db, msiPackage); |
| 175 | } | 193 | } |
| 176 | } | 194 | } |
| 177 | catch (Dtf.InstallerException e) | 195 | catch (MsiException e) |
| 178 | { | 196 | { |
| 179 | this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, e.Message)); | 197 | this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(this.Facade.PackageSymbol.SourceLineNumbers, sourcePath, e.Message)); |
| 180 | } | 198 | } |
| @@ -196,7 +214,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 196 | return new HashSet<string>(properties, StringComparer.Ordinal); | 214 | return new HashSet<string>(properties, StringComparer.Ordinal); |
| 197 | } | 215 | } |
| 198 | 216 | ||
| 199 | private void SetPerMachineAppropriately(Dtf.Database db, WixBundleMsiPackageSymbol msiPackage, string sourcePath) | 217 | private void SetPerMachineAppropriately(string allusers, WixBundleMsiPackageSymbol msiPackage, string sourcePath) |
| 200 | { | 218 | { |
| 201 | if (msiPackage.ForcePerMachine) | 219 | if (msiPackage.ForcePerMachine) |
| 202 | { | 220 | { |
| @@ -211,8 +229,6 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 211 | } | 229 | } |
| 212 | else | 230 | else |
| 213 | { | 231 | { |
| 214 | var allusers = ProcessMsiPackageCommand.GetProperty(db, "ALLUSERS"); | ||
| 215 | |||
| 216 | if (String.IsNullOrEmpty(allusers)) | 232 | if (String.IsNullOrEmpty(allusers)) |
| 217 | { | 233 | { |
| 218 | // Not forced per-machine and no ALLUSERS property, flip back to per-user. | 234 | // Not forced per-machine and no ALLUSERS property, flip back to per-user. |
| @@ -240,269 +256,219 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 240 | } | 256 | } |
| 241 | } | 257 | } |
| 242 | 258 | ||
| 243 | private void SetPackageVisibility(Dtf.Database db, WixBundleMsiPackageSymbol msiPackage, ISet<string> msiPropertyNames) | 259 | private void SetPackageVisibility(string systemComponent, WixBundleMsiPackageSymbol msiPackage, ISet<string> msiPropertyNames) |
| 244 | { | 260 | { |
| 245 | var alreadyVisible = !ProcessMsiPackageCommand.HasProperty(db, "ARPSYSTEMCOMPONENT"); | 261 | // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again. |
| 246 | var visible = (this.Facade.PackageSymbol.Attributes & WixBundlePackageAttributes.Visible) == WixBundlePackageAttributes.Visible; | 262 | if (!msiPropertyNames.Contains("ARPSYSTEMCOMPONENT")) |
| 247 | |||
| 248 | // If not already set to the correct visibility. | ||
| 249 | if (alreadyVisible != visible) | ||
| 250 | { | 263 | { |
| 251 | // If the authoring specifically added "ARPSYSTEMCOMPONENT", don't do it again. | 264 | var alreadyVisible = String.IsNullOrEmpty(systemComponent); |
| 252 | if (!msiPropertyNames.Contains("ARPSYSTEMCOMPONENT")) | 265 | var visible = (this.Facade.PackageSymbol.Attributes & WixBundlePackageAttributes.Visible) == WixBundlePackageAttributes.Visible; |
| 266 | |||
| 267 | // If not already set to the correct visibility. | ||
| 268 | if (alreadyVisible != visible) | ||
| 253 | { | 269 | { |
| 254 | this.AddMsiProperty(msiPackage, "ARPSYSTEMCOMPONENT", visible ? String.Empty : "1"); | 270 | this.AddMsiProperty(msiPackage, "ARPSYSTEMCOMPONENT", visible ? String.Empty : "1"); |
| 255 | } | 271 | } |
| 256 | } | 272 | } |
| 257 | } | 273 | } |
| 258 | 274 | ||
| 259 | private void CreateRelatedPackages(Dtf.Database db) | 275 | private void CreateRelatedPackages(Database db) |
| 260 | { | 276 | { |
| 261 | // Represent the Upgrade table as related packages. | 277 | // Represent the Upgrade table as related packages. |
| 262 | if (db.Tables.Contains("Upgrade")) | 278 | if (db.TableExists("Upgrade")) |
| 263 | { | 279 | { |
| 264 | using (var view = db.OpenView("SELECT `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes` FROM `Upgrade`")) | 280 | using (var view = db.OpenExecuteView("SELECT `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes` FROM `Upgrade`")) |
| 265 | { | 281 | { |
| 266 | view.Execute(); | 282 | foreach (var record in view.Records) |
| 267 | while (true) | ||
| 268 | { | 283 | { |
| 269 | using (var record = view.Fetch()) | 284 | var recordAttributes = record.GetInteger(5); |
| 270 | { | ||
| 271 | if (null == record) | ||
| 272 | { | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | 285 | ||
| 276 | var recordAttributes = record.GetInteger(5); | 286 | var attributes = WixBundleRelatedPackageAttributes.None; |
| 287 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect ? WixBundleRelatedPackageAttributes.OnlyDetect : 0; | ||
| 288 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive ? WixBundleRelatedPackageAttributes.MinInclusive : 0; | ||
| 289 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive ? WixBundleRelatedPackageAttributes.MaxInclusive : 0; | ||
| 290 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive ? WixBundleRelatedPackageAttributes.LangInclusive : 0; | ||
| 277 | 291 | ||
| 278 | var attributes = WixBundleRelatedPackageAttributes.None; | 292 | this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.Facade.PackageSymbol.SourceLineNumbers) |
| 279 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect) == WindowsInstallerConstants.MsidbUpgradeAttributesOnlyDetect ? WixBundleRelatedPackageAttributes.OnlyDetect : 0; | 293 | { |
| 280 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMinInclusive ? WixBundleRelatedPackageAttributes.MinInclusive : 0; | 294 | PackageRef = this.Facade.PackageId, |
| 281 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesVersionMaxInclusive ? WixBundleRelatedPackageAttributes.MaxInclusive : 0; | 295 | RelatedId = record.GetString(1), |
| 282 | attributes |= (recordAttributes & WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive) == WindowsInstallerConstants.MsidbUpgradeAttributesLanguagesExclusive ? WixBundleRelatedPackageAttributes.LangInclusive : 0; | 296 | MinVersion = record.GetString(2), |
| 283 | 297 | MaxVersion = record.GetString(3), | |
| 284 | this.Section.AddSymbol(new WixBundleRelatedPackageSymbol(this.Facade.PackageSymbol.SourceLineNumbers) | 298 | Languages = record.GetString(4), |
| 285 | { | 299 | Attributes = attributes, |
| 286 | PackageRef = this.Facade.PackageId, | 300 | }); |
| 287 | RelatedId = record.GetString(1), | ||
| 288 | MinVersion = record.GetString(2), | ||
| 289 | MaxVersion = record.GetString(3), | ||
| 290 | Languages = record.GetString(4), | ||
| 291 | Attributes = attributes, | ||
| 292 | }); | ||
| 293 | } | ||
| 294 | } | 301 | } |
| 295 | } | 302 | } |
| 296 | } | 303 | } |
| 297 | } | 304 | } |
| 298 | 305 | ||
| 299 | private void CreateMsiFeatures(Dtf.Database db) | 306 | private void CreateMsiFeatures(Database db) |
| 300 | { | 307 | { |
| 301 | if (db.Tables.Contains("Feature")) | 308 | if (db.TableExists("Feature")) |
| 302 | { | 309 | { |
| 310 | using (var allFeaturesView = db.OpenExecuteView("SELECT * FROM `Feature`")) | ||
| 303 | using (var featureView = db.OpenView("SELECT `Component_` FROM `FeatureComponents` WHERE `Feature_` = ?")) | 311 | using (var featureView = db.OpenView("SELECT `Component_` FROM `FeatureComponents` WHERE `Feature_` = ?")) |
| 304 | using (var componentView = db.OpenView("SELECT `FileSize` FROM `File` WHERE `Component_` = ?")) | 312 | using (var componentView = db.OpenView("SELECT `FileSize` FROM `File` WHERE `Component_` = ?")) |
| 305 | { | 313 | { |
| 306 | using (var featureRecord = new Dtf.Record(1)) | 314 | using (var featureRecord = new Record(1)) |
| 307 | using (var componentRecord = new Dtf.Record(1)) | 315 | using (var componentRecord = new Record(1)) |
| 308 | { | 316 | { |
| 309 | using (var allFeaturesView = db.OpenView("SELECT * FROM `Feature`")) | 317 | foreach (var allFeaturesResultRecord in allFeaturesView.Records) |
| 310 | { | 318 | { |
| 311 | allFeaturesView.Execute(); | 319 | var featureName = allFeaturesResultRecord.GetString(1); |
| 320 | |||
| 321 | // Calculate the Feature size. | ||
| 322 | featureRecord.SetString(1, featureName); | ||
| 323 | featureView.Execute(featureRecord); | ||
| 312 | 324 | ||
| 313 | while (true) | 325 | // Loop over all the components for the feature to calculate the size of the feature. |
| 326 | long size = 0; | ||
| 327 | foreach (var componentResultRecord in featureView.Records) | ||
| 314 | { | 328 | { |
| 315 | using (var allFeaturesResultRecord = allFeaturesView.Fetch()) | 329 | var component = componentResultRecord.GetString(1); |
| 330 | componentRecord.SetString(1, component); | ||
| 331 | componentView.Execute(componentRecord); | ||
| 332 | |||
| 333 | foreach (var fileResultRecord in componentView.Records) | ||
| 316 | { | 334 | { |
| 317 | if (null == allFeaturesResultRecord) | 335 | var fileSize = fileResultRecord.GetString(1); |
| 318 | { | 336 | size += Convert.ToInt32(fileSize, CultureInfo.InvariantCulture.NumberFormat); |
| 319 | break; | ||
| 320 | } | ||
| 321 | |||
| 322 | var featureName = allFeaturesResultRecord.GetString(1); | ||
| 323 | |||
| 324 | // Calculate the Feature size. | ||
| 325 | featureRecord.SetString(1, featureName); | ||
| 326 | featureView.Execute(featureRecord); | ||
| 327 | |||
| 328 | // Loop over all the components for the feature to calculate the size of the feature. | ||
| 329 | long size = 0; | ||
| 330 | while (true) | ||
| 331 | { | ||
| 332 | using (var componentResultRecord = featureView.Fetch()) | ||
| 333 | { | ||
| 334 | if (null == componentResultRecord) | ||
| 335 | { | ||
| 336 | break; | ||
| 337 | } | ||
| 338 | |||
| 339 | var component = componentResultRecord.GetString(1); | ||
| 340 | componentRecord.SetString(1, component); | ||
| 341 | componentView.Execute(componentRecord); | ||
| 342 | |||
| 343 | while (true) | ||
| 344 | { | ||
| 345 | using (var fileResultRecord = componentView.Fetch()) | ||
| 346 | { | ||
| 347 | if (null == fileResultRecord) | ||
| 348 | { | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | |||
| 352 | var fileSize = fileResultRecord.GetString(1); | ||
| 353 | size += Convert.ToInt32(fileSize, CultureInfo.InvariantCulture.NumberFormat); | ||
| 354 | } | ||
| 355 | } | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, this.Facade.PackageId, featureName)) | ||
| 360 | { | ||
| 361 | PackageRef = this.Facade.PackageId, | ||
| 362 | Name = featureName, | ||
| 363 | Parent = allFeaturesResultRecord.GetString(2), | ||
| 364 | Title = allFeaturesResultRecord.GetString(3), | ||
| 365 | Description = allFeaturesResultRecord.GetString(4), | ||
| 366 | Display = allFeaturesResultRecord.GetInteger(5), | ||
| 367 | Level = allFeaturesResultRecord.GetInteger(6), | ||
| 368 | Directory = allFeaturesResultRecord.GetString(7), | ||
| 369 | Attributes = allFeaturesResultRecord.GetInteger(8), | ||
| 370 | Size = size | ||
| 371 | }); | ||
| 372 | } | 337 | } |
| 373 | } | 338 | } |
| 339 | |||
| 340 | this.Section.AddSymbol(new WixBundleMsiFeatureSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, this.Facade.PackageId, featureName)) | ||
| 341 | { | ||
| 342 | PackageRef = this.Facade.PackageId, | ||
| 343 | Name = featureName, | ||
| 344 | Parent = allFeaturesResultRecord.GetString(2), | ||
| 345 | Title = allFeaturesResultRecord.GetString(3), | ||
| 346 | Description = allFeaturesResultRecord.GetString(4), | ||
| 347 | Display = allFeaturesResultRecord.GetInteger(5), | ||
| 348 | Level = allFeaturesResultRecord.GetInteger(6), | ||
| 349 | Directory = allFeaturesResultRecord.GetString(7), | ||
| 350 | Attributes = allFeaturesResultRecord.GetInteger(8), | ||
| 351 | Size = size | ||
| 352 | }); | ||
| 374 | } | 353 | } |
| 375 | } | 354 | } |
| 376 | } | 355 | } |
| 377 | } | 356 | } |
| 378 | } | 357 | } |
| 379 | 358 | ||
| 380 | private void ImportExternalCabinetAsPayloads(Dtf.Database db, WixBundlePayloadSymbol packagePayload, ISet<string> payloadNames) | 359 | private void ImportExternalCabinetAsPayloads(Database db, WixBundlePayloadSymbol packagePayload, ISet<string> payloadNames) |
| 381 | { | 360 | { |
| 382 | if (db.Tables.Contains("Media")) | 361 | if (db.TableExists("Media")) |
| 383 | { | 362 | { |
| 384 | foreach (var cabinet in db.ExecuteStringQuery("SELECT `Cabinet` FROM `Media`")) | 363 | using (var view = db.OpenExecuteView("SELECT `Cabinet` FROM `Media`")) |
| 385 | { | 364 | { |
| 386 | if (!String.IsNullOrEmpty(cabinet) && !cabinet.StartsWith("#", StringComparison.Ordinal)) | 365 | foreach (var cabinetRecord in view.Records) |
| 387 | { | 366 | { |
| 388 | // If we didn't find the Payload as an existing child of the package, we need to | 367 | var cabinet = cabinetRecord.GetString(1); |
| 389 | // add it. We expect the file to exist on-disk in the same relative location as | ||
| 390 | // the MSI expects to find it... | ||
| 391 | var cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet); | ||
| 392 | 368 | ||
| 393 | if (!payloadNames.Contains(cabinetName)) | 369 | if (!String.IsNullOrEmpty(cabinet) && !cabinet.StartsWith("#", StringComparison.Ordinal)) |
| 394 | { | 370 | { |
| 395 | var generatedId = this.BackendHelper.GenerateIdentifier("cab", packagePayload.Id.Id, cabinet); | 371 | // If we didn't find the Payload as an existing child of the package, we need to |
| 396 | var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.PackageSymbol.SourceLineNumbers); | 372 | // add it. We expect the file to exist on-disk in the same relative location as |
| 373 | // the MSI expects to find it... | ||
| 374 | var cabinetName = Path.Combine(Path.GetDirectoryName(packagePayload.Name), cabinet); | ||
| 397 | 375 | ||
| 398 | this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) | 376 | if (!payloadNames.Contains(cabinetName)) |
| 399 | { | 377 | { |
| 400 | ParentType = ComplexReferenceParentType.Package, | 378 | var generatedId = this.BackendHelper.GenerateIdentifier("cab", packagePayload.Id.Id, cabinet); |
| 401 | ParentId = this.Facade.PackageId, | 379 | var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, cabinet, "Cabinet", this.Facade.PackageSymbol.SourceLineNumbers); |
| 402 | ChildType = ComplexReferenceChildType.Payload, | ||
| 403 | ChildId = generatedId | ||
| 404 | }); | ||
| 405 | 380 | ||
| 406 | this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) | 381 | this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) |
| 407 | { | 382 | { |
| 408 | Name = cabinetName, | 383 | ParentType = ComplexReferenceParentType.Package, |
| 409 | SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, | 384 | ParentId = this.Facade.PackageId, |
| 410 | Compressed = packagePayload.Compressed, | 385 | ChildType = ComplexReferenceChildType.Payload, |
| 411 | UnresolvedSourceFile = cabinetName, | 386 | ChildId = generatedId |
| 412 | ContainerRef = packagePayload.ContainerRef, | 387 | }); |
| 413 | ContentFile = true, | 388 | |
| 414 | Packaging = packagePayload.Packaging, | 389 | this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) |
| 415 | ParentPackagePayloadRef = packagePayload.Id.Id, | 390 | { |
| 416 | }); | 391 | Name = cabinetName, |
| 392 | SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, | ||
| 393 | Compressed = packagePayload.Compressed, | ||
| 394 | UnresolvedSourceFile = cabinetName, | ||
| 395 | ContainerRef = packagePayload.ContainerRef, | ||
| 396 | ContentFile = true, | ||
| 397 | Packaging = packagePayload.Packaging, | ||
| 398 | ParentPackagePayloadRef = packagePayload.Id.Id, | ||
| 399 | }); | ||
| 400 | } | ||
| 417 | } | 401 | } |
| 418 | } | 402 | } |
| 419 | } | 403 | } |
| 420 | } | 404 | } |
| 421 | } | 405 | } |
| 422 | 406 | ||
| 423 | private long ImportExternalFileAsPayloadsAndReturnInstallSize(Dtf.Database db, WixBundlePayloadSymbol packagePayload, bool longNamesInImage, bool compressed, ISet<string> payloadNames) | 407 | private long ImportExternalFileAsPayloadsAndReturnInstallSize(Database db, WixBundlePayloadSymbol packagePayload, bool longNamesInImage, bool compressed, ISet<string> payloadNames) |
| 424 | { | 408 | { |
| 425 | long size = 0; | 409 | long size = 0; |
| 426 | 410 | ||
| 427 | if (db.Tables.Contains("Component") && db.Tables.Contains("Directory") && db.Tables.Contains("File")) | 411 | if (db.TableExists("Component") && db.TableExists("Directory") && db.TableExists("File")) |
| 428 | { | 412 | { |
| 429 | var directories = new Dictionary<string, IResolvedDirectory>(); | 413 | var directories = new Dictionary<string, IResolvedDirectory>(); |
| 430 | 414 | ||
| 431 | // Load up the directory hash table so we will be able to resolve source paths | 415 | // Load up the directory hash table so we will be able to resolve source paths |
| 432 | // for files in the MSI database. | 416 | // for files in the MSI database. |
| 433 | using (var view = db.OpenView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) | 417 | using (var view = db.OpenExecuteView("SELECT `Directory`, `Directory_Parent`, `DefaultDir` FROM `Directory`")) |
| 434 | { | 418 | { |
| 435 | view.Execute(); | 419 | foreach (var record in view.Records) |
| 436 | while (true) | ||
| 437 | { | 420 | { |
| 438 | using (var record = view.Fetch()) | 421 | var sourceName = this.BackendHelper.GetMsiFileName(record.GetString(3), true, longNamesInImage); |
| 439 | { | ||
| 440 | if (null == record) | ||
| 441 | { | ||
| 442 | break; | ||
| 443 | } | ||
| 444 | 422 | ||
| 445 | var sourceName = this.BackendHelper.GetMsiFileName(record.GetString(3), true, longNamesInImage); | 423 | var resolvedDirectory = this.BackendHelper.CreateResolvedDirectory(record.GetString(2), sourceName); |
| 446 | 424 | ||
| 447 | var resolvedDirectory = this.BackendHelper.CreateResolvedDirectory(record.GetString(2), sourceName); | 425 | directories.Add(record.GetString(1), resolvedDirectory); |
| 448 | |||
| 449 | directories.Add(record.GetString(1), resolvedDirectory); | ||
| 450 | } | ||
| 451 | } | 426 | } |
| 452 | } | 427 | } |
| 453 | 428 | ||
| 454 | // Resolve the source paths to external files and add each file size to the total | 429 | // Resolve the source paths to external files and add each file size to the total |
| 455 | // install size of the package. | 430 | // install size of the package. |
| 456 | using (var view = db.OpenView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`")) | 431 | using (var view = db.OpenExecuteView("SELECT `Directory_`, `File`, `FileName`, `File`.`Attributes`, `FileSize` FROM `Component`, `File` WHERE `Component`.`Component`=`File`.`Component_`")) |
| 457 | { | 432 | { |
| 458 | view.Execute(); | 433 | foreach (var record in view.Records) |
| 459 | while (true) | ||
| 460 | { | 434 | { |
| 461 | using (var record = view.Fetch()) | 435 | // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not |
| 436 | // explicitly marked compressed then this is an external file. | ||
| 437 | var compressionBit = record.GetInteger(4); | ||
| 438 | if (WindowsInstallerConstants.MsidbFileAttributesNoncompressed == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) || | ||
| 439 | (!compressed && 0 == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesCompressed))) | ||
| 462 | { | 440 | { |
| 463 | if (null == record) | 441 | var fileSourcePath = this.PathResolver.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage); |
| 464 | { | 442 | var name = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath); |
| 465 | break; | ||
| 466 | } | ||
| 467 | 443 | ||
| 468 | // If the file is explicitly uncompressed or the MSI is uncompressed and the file is not | 444 | if (!payloadNames.Contains(name)) |
| 469 | // explicitly marked compressed then this is an external file. | ||
| 470 | var compressionBit = record.GetInteger(4); | ||
| 471 | if (WindowsInstallerConstants.MsidbFileAttributesNoncompressed == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesNoncompressed) || | ||
| 472 | (!compressed && 0 == (compressionBit & WindowsInstallerConstants.MsidbFileAttributesCompressed))) | ||
| 473 | { | 445 | { |
| 474 | var fileSourcePath = this.PathResolver.GetFileSourcePath(directories, record.GetString(1), record.GetString(3), compressed, longNamesInImage); | 446 | var generatedId = this.BackendHelper.GenerateIdentifier("f", packagePayload.Id.Id, record.GetString(2)); |
| 475 | var name = Path.Combine(Path.GetDirectoryName(packagePayload.Name), fileSourcePath); | 447 | var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.PackageSymbol.SourceLineNumbers); |
| 476 | 448 | ||
| 477 | if (!payloadNames.Contains(name)) | 449 | this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) |
| 478 | { | 450 | { |
| 479 | var generatedId = this.BackendHelper.GenerateIdentifier("f", packagePayload.Id.Id, record.GetString(2)); | 451 | ParentType = ComplexReferenceParentType.Package, |
| 480 | var payloadSourceFile = this.ResolveRelatedFile(packagePayload.SourceFile.Path, packagePayload.UnresolvedSourceFile, fileSourcePath, "File", this.Facade.PackageSymbol.SourceLineNumbers); | 452 | ParentId = this.Facade.PackageId, |
| 481 | 453 | ChildType = ComplexReferenceChildType.Payload, | |
| 482 | this.Section.AddSymbol(new WixGroupSymbol(this.Facade.PackageSymbol.SourceLineNumbers) | 454 | ChildId = generatedId |
| 483 | { | 455 | }); |
| 484 | ParentType = ComplexReferenceParentType.Package, | ||
| 485 | ParentId = this.Facade.PackageId, | ||
| 486 | ChildType = ComplexReferenceChildType.Payload, | ||
| 487 | ChildId = generatedId | ||
| 488 | }); | ||
| 489 | |||
| 490 | this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) | ||
| 491 | { | ||
| 492 | Name = name, | ||
| 493 | SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, | ||
| 494 | Compressed = packagePayload.Compressed, | ||
| 495 | UnresolvedSourceFile = name, | ||
| 496 | ContainerRef = packagePayload.ContainerRef, | ||
| 497 | ContentFile = true, | ||
| 498 | Packaging = packagePayload.Packaging, | ||
| 499 | ParentPackagePayloadRef = packagePayload.Id.Id, | ||
| 500 | }); | ||
| 501 | } | ||
| 502 | } | ||
| 503 | 456 | ||
| 504 | size += record.GetInteger(5); | 457 | this.Section.AddSymbol(new WixBundlePayloadSymbol(this.Facade.PackageSymbol.SourceLineNumbers, new Identifier(AccessModifier.Section, generatedId)) |
| 458 | { | ||
| 459 | Name = name, | ||
| 460 | SourceFile = new IntermediateFieldPathValue { Path = payloadSourceFile }, | ||
| 461 | Compressed = packagePayload.Compressed, | ||
| 462 | UnresolvedSourceFile = name, | ||
| 463 | ContainerRef = packagePayload.ContainerRef, | ||
| 464 | ContentFile = true, | ||
| 465 | Packaging = packagePayload.Packaging, | ||
| 466 | ParentPackagePayloadRef = packagePayload.Id.Id, | ||
| 467 | }); | ||
| 468 | } | ||
| 505 | } | 469 | } |
| 470 | |||
| 471 | size += record.GetInteger(5); | ||
| 506 | } | 472 | } |
| 507 | } | 473 | } |
| 508 | } | 474 | } |
| @@ -520,36 +486,25 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 520 | }); | 486 | }); |
| 521 | } | 487 | } |
| 522 | 488 | ||
| 523 | private void ImportDependencyProviders(WixBundleMsiPackageSymbol msiPackage, Dtf.Database db) | 489 | private void ImportDependencyProviders(Database db, WixBundleMsiPackageSymbol msiPackage) |
| 524 | { | 490 | { |
| 525 | if (db.Tables.Contains("WixDependencyProvider")) | 491 | if (db.TableExists("WixDependencyProvider")) |
| 526 | { | 492 | { |
| 527 | var query = "SELECT `WixDependencyProvider`, `ProviderKey`, `Version`, `DisplayName`, `Attributes` FROM `WixDependencyProvider`"; | 493 | using (var view = db.OpenExecuteView("SELECT `WixDependencyProvider`, `ProviderKey`, `Version`, `DisplayName`, `Attributes` FROM `WixDependencyProvider`")) |
| 528 | |||
| 529 | using (var view = db.OpenView(query)) | ||
| 530 | { | 494 | { |
| 531 | view.Execute(); | 495 | foreach (var record in view.Records) |
| 532 | while (true) | ||
| 533 | { | 496 | { |
| 534 | using (var record = view.Fetch()) | 497 | var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", msiPackage.Id.Id, record.GetString(1))); |
| 535 | { | ||
| 536 | if (null == record) | ||
| 537 | { | ||
| 538 | break; | ||
| 539 | } | ||
| 540 | 498 | ||
| 541 | var id = new Identifier(AccessModifier.Section, this.BackendHelper.GenerateIdentifier("dep", msiPackage.Id.Id, record.GetString(1))); | 499 | // Import the provider key and attributes. |
| 542 | 500 | this.Section.AddSymbol(new WixDependencyProviderSymbol(msiPackage.SourceLineNumbers, id) | |
| 543 | // Import the provider key and attributes. | 501 | { |
| 544 | this.Section.AddSymbol(new WixDependencyProviderSymbol(msiPackage.SourceLineNumbers, id) | 502 | ParentRef = msiPackage.Id.Id, |
| 545 | { | 503 | ProviderKey = record.GetString(2), |
| 546 | ParentRef = msiPackage.Id.Id, | 504 | Version = record.GetString(3) ?? msiPackage.ProductVersion, |
| 547 | ProviderKey = record.GetString(2), | 505 | DisplayName = record.GetString(4) ?? this.Facade.PackageSymbol.DisplayName, |
| 548 | Version = record.GetString(3) ?? msiPackage.ProductVersion, | 506 | Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)record.GetInteger(5), |
| 549 | DisplayName = record.GetString(4) ?? this.Facade.PackageSymbol.DisplayName, | 507 | }); |
| 550 | Attributes = WixDependencyProviderAttributes.ProvidesAttributesImported | (WixDependencyProviderAttributes)record.GetInteger(5), | ||
| 551 | }); | ||
| 552 | } | ||
| 553 | } | 508 | } |
| 554 | } | 509 | } |
| 555 | } | 510 | } |
| @@ -585,51 +540,19 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 585 | return resolvedPath; | 540 | return resolvedPath; |
| 586 | } | 541 | } |
| 587 | 542 | ||
| 588 | /// <summary> | 543 | private static string GetProperty(View view, string property) |
| 589 | /// Queries a Windows Installer database for a Property value. | ||
| 590 | /// </summary> | ||
| 591 | /// <param name="db">Database to query.</param> | ||
| 592 | /// <param name="property">Property to examine.</param> | ||
| 593 | /// <returns>String value for result or null if query doesn't match a single result.</returns> | ||
| 594 | private static string GetProperty(Dtf.Database db, string property) | ||
| 595 | { | 544 | { |
| 596 | try | 545 | using (var queryRecord = new Record(1)) |
| 597 | { | ||
| 598 | return db.ExecuteScalar(PropertyQuery(property)).ToString(); | ||
| 599 | } | ||
| 600 | catch (Dtf.InstallerException) | ||
| 601 | { | 546 | { |
| 602 | } | 547 | queryRecord[1] = property; |
| 603 | 548 | ||
| 604 | return null; | 549 | view.Execute(queryRecord); |
| 605 | } | ||
| 606 | 550 | ||
| 607 | /// <summary> | 551 | using (var record = view.Fetch()) |
| 608 | /// Queries a Windows Installer database to determine if one or more rows exist in the Property table. | 552 | { |
| 609 | /// </summary> | 553 | return record?.GetString(1); |
| 610 | /// <param name="db">Database to query.</param> | 554 | } |
| 611 | /// <param name="property">Property to examine.</param> | ||
| 612 | /// <returns>True if query matches at least one result.</returns> | ||
| 613 | private static bool HasProperty(Dtf.Database db, string property) | ||
| 614 | { | ||
| 615 | try | ||
| 616 | { | ||
| 617 | return 0 < db.ExecuteQuery(PropertyQuery(property)).Count; | ||
| 618 | } | ||
| 619 | catch (Dtf.InstallerException) | ||
| 620 | { | ||
| 621 | } | 555 | } |
| 622 | |||
| 623 | return false; | ||
| 624 | } | ||
| 625 | |||
| 626 | private static string PropertyQuery(string property) | ||
| 627 | { | ||
| 628 | // quick sanity check that we'll be creating a valid query... | ||
| 629 | // TODO: Are there any other special characters we should be looking for? | ||
| 630 | Debug.Assert(!property.Contains("'")); | ||
| 631 | |||
| 632 | return String.Format(CultureInfo.InvariantCulture, ProcessMsiPackageCommand.PropertySqlFormat, property); | ||
| 633 | } | 556 | } |
| 634 | } | 557 | } |
| 635 | } | 558 | } |
diff --git a/src/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs b/src/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs index f528ce20..5f431b38 100644 --- a/src/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/ProcessMspPackageCommand.cs | |||
| @@ -4,23 +4,27 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Diagnostics; | ||
| 8 | using System.Globalization; | ||
| 9 | using System.IO; | 7 | using System.IO; |
| 10 | using System.Text; | 8 | using System.Text; |
| 11 | using System.Xml; | 9 | using System.Xml; |
| 10 | using WixToolset.Core.Native.Msi; | ||
| 12 | using WixToolset.Data; | 11 | using WixToolset.Data; |
| 13 | using WixToolset.Data.Symbols; | 12 | using WixToolset.Data.Symbols; |
| 14 | using WixToolset.Extensibility.Services; | 13 | using WixToolset.Extensibility.Services; |
| 15 | using Dtf = WixToolset.Dtf.WindowsInstaller; | ||
| 16 | 14 | ||
| 17 | /// <summary> | 15 | /// <summary> |
| 18 | /// Initializes package state from the Msp contents. | 16 | /// Initializes package state from the Msp contents. |
| 19 | /// </summary> | 17 | /// </summary> |
| 20 | internal class ProcessMspPackageCommand | 18 | internal class ProcessMspPackageCommand |
| 21 | { | 19 | { |
| 22 | private const string PatchMetadataFormat = "SELECT `Value` FROM `MsiPatchMetadata` WHERE `Property` = '{0}'"; | 20 | private const string PatchMetadataQuery = "SELECT `Value` FROM `MsiPatchMetadata` WHERE `Property` = ?"; |
| 23 | private static readonly Encoding XmlOutputEncoding = new UTF8Encoding(false); | 21 | private static readonly XmlWriterSettings XmlSettings = new XmlWriterSettings() |
| 22 | { | ||
| 23 | Encoding = new UTF8Encoding(false), | ||
| 24 | Indent = false, | ||
| 25 | NewLineChars = String.Empty, | ||
| 26 | NewLineHandling = NewLineHandling.Replace, | ||
| 27 | }; | ||
| 24 | 28 | ||
| 25 | public ProcessMspPackageCommand(IMessaging messaging, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols) | 29 | public ProcessMspPackageCommand(IMessaging messaging, IntermediateSection section, PackageFacade facade, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols) |
| 26 | { | 30 | { |
| @@ -52,30 +56,34 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 52 | 56 | ||
| 53 | try | 57 | try |
| 54 | { | 58 | { |
| 55 | // Read data out of the msp database... | 59 | using (var db = new Database(sourcePath, OpenDatabase.ReadOnly | OpenDatabase.OpenPatchFile)) |
| 56 | using (var sumInfo = new Dtf.SummaryInfo(sourcePath, false)) | ||
| 57 | { | ||
| 58 | mspPackage.PatchCode = sumInfo.RevisionNumber.Substring(0, 38); | ||
| 59 | } | ||
| 60 | |||
| 61 | using (var db = new Dtf.Database(sourcePath)) | ||
| 62 | { | 60 | { |
| 63 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) | 61 | // Read data out of the msp database... |
| 62 | using (var sumInfo = new SummaryInformation(db)) | ||
| 64 | { | 63 | { |
| 65 | this.Facade.PackageSymbol.DisplayName = ProcessMspPackageCommand.GetPatchMetadataProperty(db, "DisplayName"); | 64 | var patchCode = sumInfo.GetProperty(SummaryInformation.Patch.PatchCode); |
| 65 | mspPackage.PatchCode = patchCode.Substring(0, 38); | ||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description)) | 68 | using (var view = db.OpenView(PatchMetadataQuery)) |
| 69 | { | 69 | { |
| 70 | this.Facade.PackageSymbol.Description = ProcessMspPackageCommand.GetPatchMetadataProperty(db, "Description"); | 70 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.DisplayName)) |
| 71 | } | 71 | { |
| 72 | this.Facade.PackageSymbol.DisplayName = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "DisplayName"); | ||
| 73 | } | ||
| 74 | |||
| 75 | if (String.IsNullOrEmpty(this.Facade.PackageSymbol.Description)) | ||
| 76 | { | ||
| 77 | this.Facade.PackageSymbol.Description = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "Description"); | ||
| 78 | } | ||
| 72 | 79 | ||
| 73 | mspPackage.Manufacturer = ProcessMspPackageCommand.GetPatchMetadataProperty(db, "ManufacturerName"); | 80 | mspPackage.Manufacturer = ProcessMspPackageCommand.GetPatchMetadataProperty(view, "ManufacturerName"); |
| 81 | } | ||
| 74 | } | 82 | } |
| 75 | 83 | ||
| 76 | this.ProcessPatchXml(packagePayload, mspPackage, sourcePath); | 84 | this.ProcessPatchXml(packagePayload, mspPackage, sourcePath); |
| 77 | } | 85 | } |
| 78 | catch (Dtf.InstallerException e) | 86 | catch (MsiException e) |
| 79 | { | 87 | { |
| 80 | this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(packagePayload.SourceLineNumbers, sourcePath, e.Message)); | 88 | this.Messaging.Write(ErrorMessages.UnableToReadPackageInformation(packagePayload.SourceLineNumbers, sourcePath, e.Message)); |
| 81 | return; | 89 | return; |
| @@ -91,7 +99,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 91 | { | 99 | { |
| 92 | var uniqueTargetCodes = new HashSet<string>(); | 100 | var uniqueTargetCodes = new HashSet<string>(); |
| 93 | 101 | ||
| 94 | var patchXml = Dtf.Installer.ExtractPatchXmlData(sourcePath); | 102 | var patchXml = Installer.ExtractPatchXml(sourcePath); |
| 95 | 103 | ||
| 96 | var doc = new XmlDocument(); | 104 | var doc = new XmlDocument(); |
| 97 | doc.LoadXml(patchXml); | 105 | doc.LoadXml(patchXml); |
| @@ -146,15 +154,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 146 | // Save the XML as compact as possible. | 154 | // Save the XML as compact as possible. |
| 147 | using (var writer = new StringWriter()) | 155 | using (var writer = new StringWriter()) |
| 148 | { | 156 | { |
| 149 | var settings = new XmlWriterSettings() | 157 | using (var xmlWriter = XmlWriter.Create(writer, XmlSettings)) |
| 150 | { | ||
| 151 | Encoding = ProcessMspPackageCommand.XmlOutputEncoding, | ||
| 152 | Indent = false, | ||
| 153 | NewLineChars = String.Empty, | ||
| 154 | NewLineHandling = NewLineHandling.Replace, | ||
| 155 | }; | ||
| 156 | |||
| 157 | using (var xmlWriter = XmlWriter.Create(writer, settings)) | ||
| 158 | { | 158 | { |
| 159 | doc.WriteTo(xmlWriter); | 159 | doc.WriteTo(xmlWriter); |
| 160 | } | 160 | } |
| @@ -163,32 +163,19 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 163 | } | 163 | } |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | /// <summary> | 166 | private static string GetPatchMetadataProperty(View view, string property) |
| 167 | /// Queries a Windows Installer patch database for a Property value from the MsiPatchMetadata table. | ||
| 168 | /// </summary> | ||
| 169 | /// <param name="db">Database to query.</param> | ||
| 170 | /// <param name="property">Property to examine.</param> | ||
| 171 | /// <returns>String value for result or null if query doesn't match a single result.</returns> | ||
| 172 | private static string GetPatchMetadataProperty(Dtf.Database db, string property) | ||
| 173 | { | 167 | { |
| 174 | try | 168 | using (var queryRecord = new Record(1)) |
| 175 | { | ||
| 176 | return db.ExecuteScalar(PatchMetadataPropertyQuery(property)).ToString(); | ||
| 177 | } | ||
| 178 | catch (Dtf.InstallerException) | ||
| 179 | { | 169 | { |
| 180 | } | 170 | queryRecord[1] = property; |
| 181 | |||
| 182 | return null; | ||
| 183 | } | ||
| 184 | 171 | ||
| 185 | private static string PatchMetadataPropertyQuery(string property) | 172 | view.Execute(queryRecord); |
| 186 | { | ||
| 187 | // quick sanity check that we'll be creating a valid query... | ||
| 188 | // TODO: Are there any other special characters we should be looking for? | ||
| 189 | Debug.Assert(!property.Contains("'")); | ||
| 190 | 173 | ||
| 191 | return String.Format(CultureInfo.InvariantCulture, ProcessMspPackageCommand.PatchMetadataFormat, property); | 174 | using (var record = view.Fetch()) |
| 175 | { | ||
| 176 | return record?.GetString(1); | ||
| 177 | } | ||
| 178 | } | ||
| 192 | } | 179 | } |
| 193 | 180 | ||
| 194 | private static bool TargetsCode(XmlNode node) => "true" == node?.Attributes["Validate"]?.Value; | 181 | private static bool TargetsCode(XmlNode node) => "true" == node?.Attributes["Validate"]?.Value; |
diff --git a/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj b/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj index 4c57f567..2e828eae 100644 --- a/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj +++ b/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | <PackageReference Include="WixToolset.Core.Native" Version="4.0.*" /> | 27 | <PackageReference Include="WixToolset.Core.Native" Version="4.0.*" /> |
| 28 | <PackageReference Include="WixToolset.Data" Version="4.0.*" /> | 28 | <PackageReference Include="WixToolset.Data" Version="4.0.*" /> |
| 29 | <PackageReference Include="WixToolset.Dtf.Resources" Version="4.0.*" /> | 29 | <PackageReference Include="WixToolset.Dtf.Resources" Version="4.0.*" /> |
| 30 | <PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="4.0.*" /> | ||
| 31 | <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" /> | 30 | <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" /> |
| 32 | </ItemGroup> | 31 | </ItemGroup> |
| 33 | 32 | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj b/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj index cd2c917c..56262373 100644 --- a/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj +++ b/src/WixToolset.Core.WindowsInstaller/WixToolset.Core.WindowsInstaller.csproj | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | <ItemGroup> | 15 | <ItemGroup> |
| 16 | <PackageReference Include="WixToolset.Core.Native" Version="4.0.*" /> | 16 | <PackageReference Include="WixToolset.Core.Native" Version="4.0.*" /> |
| 17 | <PackageReference Include="WixToolset.Data" Version="4.0.*" /> | 17 | <PackageReference Include="WixToolset.Data" Version="4.0.*" /> |
| 18 | <PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="4.0.*" /> | ||
| 19 | <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" /> | 18 | <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" /> |
| 20 | </ItemGroup> | 19 | </ItemGroup> |
| 21 | 20 | ||
