diff options
author | Rob Mensching <rob@firegiant.com> | 2021-03-25 10:00:35 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-03-25 10:04:58 -0700 |
commit | 3dc92067f57e3803d4e1bac6d055e2a23f797414 (patch) | |
tree | 2127b1a5e2a1d11674c7d4411cc277dd61a43ea9 /src | |
parent | 7c5ccef16a3d6c88c6da2b996fbe7ec5010ea50c (diff) | |
download | wix-3dc92067f57e3803d4e1bac6d055e2a23f797414.tar.gz wix-3dc92067f57e3803d4e1bac6d055e2a23f797414.tar.bz2 wix-3dc92067f57e3803d4e1bac6d055e2a23f797414.zip |
Remove dependency on Dtf.WindowsInstaller from Core
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 | ||