diff options
Diffstat (limited to 'src')
45 files changed, 2001 insertions, 2442 deletions
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs index 74e2cdb5..f426b96d 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/AssignMediaCommand.cs | |||
@@ -1,43 +1,44 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.Globalization; | 7 | using System.Globalization; |
8 | using System.Linq; | ||
8 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
9 | using WixToolset.Data; | 10 | using WixToolset.Data; |
10 | using WixToolset.Data.Rows; | 11 | using WixToolset.Data.Rows; |
12 | using WixToolset.Data.Tuples; | ||
11 | 13 | ||
12 | /// <summary> | 14 | /// <summary> |
13 | /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows. | 15 | /// AssignMediaCommand assigns files to cabs based on Media or MediaTemplate rows. |
14 | /// </summary> | 16 | /// </summary> |
15 | public class AssignMediaCommand | 17 | internal class AssignMediaCommand |
16 | { | 18 | { |
17 | public AssignMediaCommand() | 19 | public AssignMediaCommand(IntermediateSection section) |
18 | { | 20 | { |
19 | this.CabinetNameTemplate = "Cab{0}.cab"; | 21 | this.CabinetNameTemplate = "Cab{0}.cab"; |
22 | this.Section = section; | ||
20 | } | 23 | } |
21 | 24 | ||
22 | public Output Output { private get; set; } | 25 | private IntermediateSection Section { get; } |
26 | |||
27 | public IEnumerable<FileFacade> FileFacades { private get; set; } | ||
23 | 28 | ||
24 | public bool FilesCompressed { private get; set; } | 29 | public bool FilesCompressed { private get; set; } |
25 | 30 | ||
26 | public string CabinetNameTemplate { private get; set; } | 31 | public string CabinetNameTemplate { private get; set; } |
27 | 32 | ||
28 | public IEnumerable<FileFacade> FileFacades { private get; set; } | ||
29 | |||
30 | public TableDefinitionCollection TableDefinitions { private get; set; } | ||
31 | |||
32 | /// <summary> | 33 | /// <summary> |
33 | /// Gets cabinets with their file rows. | 34 | /// Gets cabinets with their file rows. |
34 | /// </summary> | 35 | /// </summary> |
35 | public Dictionary<MediaRow, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; } | 36 | public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileFacadesByCabinetMedia { get; private set; } |
36 | 37 | ||
37 | /// <summary> | 38 | /// <summary> |
38 | /// Get media rows. | 39 | /// Get media rows. |
39 | /// </summary> | 40 | /// </summary> |
40 | public RowDictionary<MediaRow> MediaRows { get; private set; } | 41 | public Dictionary<int, MediaTuple> MediaRows { get; private set; } |
41 | 42 | ||
42 | /// <summary> | 43 | /// <summary> |
43 | /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. | 44 | /// Get uncompressed file rows. This will contain file rows of File elements that are marked with compression=no. |
@@ -47,42 +48,41 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
47 | 48 | ||
48 | public void Execute() | 49 | public void Execute() |
49 | { | 50 | { |
50 | Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia = new Dictionary<MediaRow, List<FileFacade>>(); | 51 | var filesByCabinetMedia = new Dictionary<MediaTuple, List<FileFacade>>(); |
51 | 52 | ||
52 | RowDictionary<MediaRow> mediaRows = new RowDictionary<MediaRow>(); | 53 | var mediaRows = new Dictionary<int, MediaTuple>(); |
53 | 54 | ||
54 | List<FileFacade> uncompressedFiles = new List<FileFacade>(); | 55 | List<FileFacade> uncompressedFiles = new List<FileFacade>(); |
55 | 56 | ||
56 | MediaRow mergeModuleMediaRow = null; | 57 | var mediaTable = this.Section.Tuples.OfType<MediaTuple>().ToList(); |
57 | Table mediaTable = this.Output.Tables["Media"]; | 58 | var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>().ToList(); |
58 | Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; | ||
59 | 59 | ||
60 | // If both tables are authored, it is an error. | 60 | // If both tables are authored, it is an error. |
61 | if ((mediaTemplateTable != null && mediaTemplateTable.Rows.Count > 0) && (mediaTable != null && mediaTable.Rows.Count > 1)) | 61 | if ((mediaTemplateTable != null && mediaTemplateTable.Count > 0) && (mediaTable != null && mediaTable.Count > 1)) |
62 | { | 62 | { |
63 | throw new WixException(WixErrors.MediaTableCollision(null)); | 63 | throw new WixException(WixErrors.MediaTableCollision(null)); |
64 | } | 64 | } |
65 | 65 | ||
66 | // When building merge module, all the files go to "#MergeModule.CABinet". | 66 | // When building merge module, all the files go to "#MergeModule.CABinet". |
67 | if (OutputType.Module == this.Output.Type) | 67 | if (SectionType.Module == this.Section.Type) |
68 | { | 68 | { |
69 | Table mergeModuleMediaTable = new Table(this.TableDefinitions["Media"]); | 69 | var mergeModuleMediaRow = new MediaTuple(); |
70 | mergeModuleMediaRow = (MediaRow)mergeModuleMediaTable.CreateRow(null); | ||
71 | mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet"; | 70 | mergeModuleMediaRow.Cabinet = "#MergeModule.CABinet"; |
72 | 71 | ||
73 | filesByCabinetMedia.Add(mergeModuleMediaRow, new List<FileFacade>()); | 72 | this.Section.Tuples.Add(mergeModuleMediaRow); |
74 | } | ||
75 | 73 | ||
76 | if (OutputType.Module == this.Output.Type || null == mediaTemplateTable) | 74 | filesByCabinetMedia.Add(mergeModuleMediaRow, new List<FileFacade>(this.FileFacades)); |
75 | } | ||
76 | else if (null == mediaTemplateTable) | ||
77 | { | 77 | { |
78 | this.ManuallyAssignFiles(mediaTable, mergeModuleMediaRow, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); | 78 | this.ManuallyAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); |
79 | } | 79 | } |
80 | else | 80 | else |
81 | { | 81 | { |
82 | this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); | 82 | this.AutoAssignFiles(mediaTable, this.FileFacades, filesByCabinetMedia, mediaRows, uncompressedFiles); |
83 | } | 83 | } |
84 | 84 | ||
85 | this.FileFacadesByCabinetMedia = new Dictionary<MediaRow, IEnumerable<FileFacade>>(); | 85 | this.FileFacadesByCabinetMedia = new Dictionary<MediaTuple, IEnumerable<FileFacade>>(); |
86 | 86 | ||
87 | foreach (var mediaRowWithFiles in filesByCabinetMedia) | 87 | foreach (var mediaRowWithFiles in filesByCabinetMedia) |
88 | { | 88 | { |
@@ -98,7 +98,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
98 | /// Assign files to cabinets based on MediaTemplate authoring. | 98 | /// Assign files to cabinets based on MediaTemplate authoring. |
99 | /// </summary> | 99 | /// </summary> |
100 | /// <param name="fileFacades">FileRowCollection</param> | 100 | /// <param name="fileFacades">FileRowCollection</param> |
101 | private void AutoAssignFiles(Table mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia, RowDictionary<MediaRow> mediaRows, List<FileFacade> uncompressedFiles) | 101 | private void AutoAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) |
102 | { | 102 | { |
103 | const int MaxCabIndex = 999; | 103 | const int MaxCabIndex = 999; |
104 | 104 | ||
@@ -107,13 +107,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
107 | int maxPreCabSizeInMB = 0; | 107 | int maxPreCabSizeInMB = 0; |
108 | int currentCabIndex = 0; | 108 | int currentCabIndex = 0; |
109 | 109 | ||
110 | MediaRow currentMediaRow = null; | 110 | MediaTuple currentMediaRow = null; |
111 | 111 | ||
112 | Table mediaTemplateTable = this.Output.Tables["WixMediaTemplate"]; | 112 | var mediaTemplateTable = this.Section.Tuples.OfType<WixMediaTemplateTuple>(); |
113 | |||
114 | // Remove all previous media tuples since they will be replaced with | ||
115 | // media template. | ||
116 | foreach (var mediaTuple in mediaTable) | ||
117 | { | ||
118 | this.Section.Tuples.Remove(mediaTuple); | ||
119 | } | ||
113 | 120 | ||
114 | // Auto assign files to cabinets based on maximum uncompressed media size | 121 | // Auto assign files to cabinets based on maximum uncompressed media size |
115 | mediaTable.Rows.Clear(); | 122 | var mediaTemplateRow = mediaTemplateTable.Single(); |
116 | WixMediaTemplateRow mediaTemplateRow = (WixMediaTemplateRow)mediaTemplateTable.Rows[0]; | ||
117 | 123 | ||
118 | if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) | 124 | if (!String.IsNullOrEmpty(mediaTemplateRow.CabinetTemplate)) |
119 | { | 125 | { |
@@ -149,9 +155,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
149 | { | 155 | { |
150 | // When building a product, if the current file is not to be compressed or if | 156 | // When building a product, if the current file is not to be compressed or if |
151 | // the package set not to be compressed, don't cab it. | 157 | // the package set not to be compressed, don't cab it. |
152 | if (OutputType.Product == this.Output.Type && | 158 | if (SectionType.Product == this.Section.Type && |
153 | (!facade.File.Compressed.Value || | 159 | ((facade.File.Compressed.HasValue && !facade.File.Compressed.Value) || |
154 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) | 160 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) |
155 | { | 161 | { |
156 | uncompressedFiles.Add(facade); | 162 | uncompressedFiles.Add(facade); |
157 | continue; | 163 | continue; |
@@ -172,8 +178,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
172 | if (currentPreCabSize > maxPreCabSizeInBytes) | 178 | if (currentPreCabSize > maxPreCabSizeInBytes) |
173 | { | 179 | { |
174 | // Overflow due to current file | 180 | // Overflow due to current file |
175 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex); | 181 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); |
176 | mediaRows.Add(currentMediaRow); | 182 | mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); |
177 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | 183 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); |
178 | 184 | ||
179 | List<FileFacade> cabinetFileRows = filesByCabinetMedia[currentMediaRow]; | 185 | List<FileFacade> cabinetFileRows = filesByCabinetMedia[currentMediaRow]; |
@@ -188,8 +194,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
188 | if (currentMediaRow == null) | 194 | if (currentMediaRow == null) |
189 | { | 195 | { |
190 | // Create new cab and MediaRow | 196 | // Create new cab and MediaRow |
191 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, mediaTable, ++currentCabIndex); | 197 | currentMediaRow = this.AddMediaRow(mediaTemplateRow, ++currentCabIndex); |
192 | mediaRows.Add(currentMediaRow); | 198 | mediaRows.Add(currentMediaRow.DiskId, currentMediaRow); |
193 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); | 199 | filesByCabinetMedia.Add(currentMediaRow, new List<FileFacade>()); |
194 | } | 200 | } |
195 | 201 | ||
@@ -201,11 +207,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
201 | } | 207 | } |
202 | 208 | ||
203 | // If there are uncompressed files and no MediaRow, create a default one. | 209 | // If there are uncompressed files and no MediaRow, create a default one. |
204 | if (uncompressedFiles.Count > 0 && mediaTable.Rows.Count == 0) | 210 | if (uncompressedFiles.Count > 0 && !this.Section.Tuples.OfType<MediaTuple>().Any()) |
205 | { | 211 | { |
206 | MediaRow defaultMediaRow = (MediaRow)mediaTable.CreateRow(null); | 212 | var defaultMediaRow = new MediaTuple(null, new Identifier(1, AccessModifier.Private)); |
207 | defaultMediaRow.DiskId = 1; | 213 | defaultMediaRow.DiskId = 1; |
208 | mediaRows.Add(defaultMediaRow); | 214 | |
215 | mediaRows.Add(1, defaultMediaRow); | ||
216 | this.Section.Tuples.Add(defaultMediaRow); | ||
209 | } | 217 | } |
210 | } | 218 | } |
211 | 219 | ||
@@ -213,79 +221,65 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
213 | /// Assign files to cabinets based on Media authoring. | 221 | /// Assign files to cabinets based on Media authoring. |
214 | /// </summary> | 222 | /// </summary> |
215 | /// <param name="mediaTable"></param> | 223 | /// <param name="mediaTable"></param> |
216 | /// <param name="mergeModuleMediaRow"></param> | ||
217 | /// <param name="fileFacades"></param> | 224 | /// <param name="fileFacades"></param> |
218 | private void ManuallyAssignFiles(Table mediaTable, MediaRow mergeModuleMediaRow, IEnumerable<FileFacade> fileFacades, Dictionary<MediaRow, List<FileFacade>> filesByCabinetMedia, RowDictionary<MediaRow> mediaRows, List<FileFacade> uncompressedFiles) | 225 | private void ManuallyAssignFiles(List<MediaTuple> mediaTable, IEnumerable<FileFacade> fileFacades, Dictionary<MediaTuple, List<FileFacade>> filesByCabinetMedia, Dictionary<int, MediaTuple> mediaRows, List<FileFacade> uncompressedFiles) |
219 | { | 226 | { |
220 | if (OutputType.Module != this.Output.Type) | 227 | if (mediaTable.Any()) |
221 | { | 228 | { |
222 | if (null != mediaTable) | 229 | var cabinetMediaRows = new Dictionary<string, MediaTuple>(StringComparer.OrdinalIgnoreCase); |
230 | foreach (var mediaRow in mediaTable) | ||
223 | { | 231 | { |
224 | Dictionary<string, MediaRow> cabinetMediaRows = new Dictionary<string, MediaRow>(StringComparer.InvariantCultureIgnoreCase); | 232 | // If the Media row has a cabinet, make sure it is unique across all Media rows. |
225 | foreach (MediaRow mediaRow in mediaTable.Rows) | 233 | if (!String.IsNullOrEmpty(mediaRow.Cabinet)) |
226 | { | 234 | { |
227 | // If the Media row has a cabinet, make sure it is unique across all Media rows. | 235 | if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out var existingRow)) |
228 | if (!String.IsNullOrEmpty(mediaRow.Cabinet)) | ||
229 | { | 236 | { |
230 | MediaRow existingRow; | 237 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); |
231 | if (cabinetMediaRows.TryGetValue(mediaRow.Cabinet, out existingRow)) | 238 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); |
232 | { | 239 | } |
233 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName(mediaRow.SourceLineNumbers, mediaRow.Cabinet)); | 240 | else |
234 | Messaging.Instance.OnMessage(WixErrors.DuplicateCabinetName2(existingRow.SourceLineNumbers, existingRow.Cabinet)); | 241 | { |
235 | } | 242 | cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); |
236 | else | ||
237 | { | ||
238 | cabinetMediaRows.Add(mediaRow.Cabinet, mediaRow); | ||
239 | } | ||
240 | } | 243 | } |
241 | |||
242 | mediaRows.Add(mediaRow); | ||
243 | } | 244 | } |
245 | |||
246 | mediaRows.Add(mediaRow.DiskId, mediaRow); | ||
244 | } | 247 | } |
248 | } | ||
245 | 249 | ||
246 | foreach (MediaRow mediaRow in mediaRows.Values) | 250 | foreach (var mediaRow in mediaRows.Values) |
251 | { | ||
252 | if (null != mediaRow.Cabinet) | ||
247 | { | 253 | { |
248 | if (null != mediaRow.Cabinet) | 254 | filesByCabinetMedia.Add(mediaRow, new List<FileFacade>()); |
249 | { | ||
250 | filesByCabinetMedia.Add(mediaRow, new List<FileFacade>()); | ||
251 | } | ||
252 | } | 255 | } |
253 | } | 256 | } |
254 | 257 | ||
255 | foreach (FileFacade facade in fileFacades) | 258 | foreach (FileFacade facade in fileFacades) |
256 | { | 259 | { |
257 | if (OutputType.Module == this.Output.Type) | 260 | if (!mediaRows.TryGetValue(facade.WixFile.DiskId, out var mediaRow)) |
258 | { | 261 | { |
259 | filesByCabinetMedia[mergeModuleMediaRow].Add(facade); | 262 | Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); |
263 | continue; | ||
260 | } | 264 | } |
261 | else | ||
262 | { | ||
263 | MediaRow mediaRow; | ||
264 | if (!mediaRows.TryGetValue(facade.WixFile.DiskId.ToString(CultureInfo.InvariantCulture), out mediaRow)) | ||
265 | { | ||
266 | Messaging.Instance.OnMessage(WixErrors.MissingMedia(facade.File.SourceLineNumbers, facade.WixFile.DiskId)); | ||
267 | continue; | ||
268 | } | ||
269 | 265 | ||
270 | // When building a product, if the current file is not to be compressed or if | 266 | // When building a product, if the current file is not to be compressed or if |
271 | // the package set not to be compressed, don't cab it. | 267 | // the package set not to be compressed, don't cab it. |
272 | if (OutputType.Product == this.Output.Type && | 268 | if (SectionType.Product == this.Section.Type && |
273 | (!facade.File.Compressed.Value || | 269 | (!facade.File.Compressed.Value || |
274 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) | 270 | (!facade.File.Compressed.HasValue && !this.FilesCompressed))) |
271 | { | ||
272 | uncompressedFiles.Add(facade); | ||
273 | } | ||
274 | else // file is marked compressed. | ||
275 | { | ||
276 | if (filesByCabinetMedia.TryGetValue(mediaRow, out var cabinetFiles)) | ||
275 | { | 277 | { |
276 | uncompressedFiles.Add(facade); | 278 | cabinetFiles.Add(facade); |
277 | } | 279 | } |
278 | else // file is marked compressed. | 280 | else |
279 | { | 281 | { |
280 | List<FileFacade> cabinetFiles; | 282 | Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); |
281 | if (filesByCabinetMedia.TryGetValue(mediaRow, out cabinetFiles)) | ||
282 | { | ||
283 | cabinetFiles.Add(facade); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | Messaging.Instance.OnMessage(WixErrors.ExpectedMediaCabinet(facade.File.SourceLineNumbers, facade.File.File, facade.WixFile.DiskId)); | ||
288 | } | ||
289 | } | 283 | } |
290 | } | 284 | } |
291 | } | 285 | } |
@@ -297,17 +291,20 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
297 | /// <param name="mediaTable"></param> | 291 | /// <param name="mediaTable"></param> |
298 | /// <param name="cabIndex"></param> | 292 | /// <param name="cabIndex"></param> |
299 | /// <returns></returns> | 293 | /// <returns></returns> |
300 | private MediaRow AddMediaRow(WixMediaTemplateRow mediaTemplateRow, Table mediaTable, int cabIndex) | 294 | private MediaTuple AddMediaRow(WixMediaTemplateTuple mediaTemplateRow, int cabIndex) |
301 | { | 295 | { |
302 | MediaRow currentMediaRow = (MediaRow)mediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers); | 296 | var currentMediaRow = new MediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); |
303 | currentMediaRow.DiskId = cabIndex; | 297 | currentMediaRow.DiskId = cabIndex; |
304 | currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); | 298 | currentMediaRow.Cabinet = String.Format(CultureInfo.InvariantCulture, this.CabinetNameTemplate, cabIndex); |
305 | 299 | ||
306 | Table wixMediaTable = this.Output.EnsureTable(this.TableDefinitions["WixMedia"]); | 300 | this.Section.Tuples.Add(currentMediaRow); |
307 | WixMediaRow row = (WixMediaRow)wixMediaTable.CreateRow(mediaTemplateRow.SourceLineNumbers); | 301 | |
308 | row.DiskId = cabIndex; | 302 | var row = new WixMediaTuple(mediaTemplateRow.SourceLineNumbers, new Identifier(cabIndex, AccessModifier.Private)); |
303 | row.DiskId_ = cabIndex; | ||
309 | row.CompressionLevel = mediaTemplateRow.CompressionLevel; | 304 | row.CompressionLevel = mediaTemplateRow.CompressionLevel; |
310 | 305 | ||
306 | this.Section.Tuples.Add(row); | ||
307 | |||
311 | return currentMediaRow; | 308 | return currentMediaRow; |
312 | } | 309 | } |
313 | } | 310 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs index 5a61b63c..30a19a4b 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindDatabaseCommand.cs | |||
@@ -3,21 +3,15 @@ | |||
3 | namespace WixToolset.Core.WindowsInstaller.Bind | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | ||
7 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
8 | using System.Diagnostics; | ||
9 | using System.Globalization; | ||
10 | using System.IO; | 7 | using System.IO; |
11 | using System.Linq; | 8 | using System.Linq; |
12 | using WixToolset.Bind; | ||
13 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
14 | using WixToolset.Core.WindowsInstaller.Databases; | ||
15 | using WixToolset.Data; | 10 | using WixToolset.Data; |
16 | using WixToolset.Data.Bind; | 11 | using WixToolset.Data.Bind; |
17 | using WixToolset.Data.Rows; | 12 | using WixToolset.Data.Tuples; |
18 | using WixToolset.Extensibility; | 13 | using WixToolset.Extensibility; |
19 | using WixToolset.Extensibility.Services; | 14 | using WixToolset.Extensibility.Services; |
20 | using WixToolset.Msi; | ||
21 | 15 | ||
22 | /// <summary> | 16 | /// <summary> |
23 | /// Binds a databse. | 17 | /// Binds a databse. |
@@ -25,11 +19,11 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
25 | internal class BindDatabaseCommand | 19 | internal class BindDatabaseCommand |
26 | { | 20 | { |
27 | // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. | 21 | // As outlined in RFC 4122, this is our namespace for generating name-based (version 3) UUIDs. |
28 | private static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); | 22 | internal static readonly Guid WixComponentGuidNamespace = new Guid("{3064E5C6-FB63-4FE9-AC49-E446A792EFA5}"); |
29 | 23 | ||
30 | public BindDatabaseCommand(IBindContext context, Validator validator) | 24 | public BindDatabaseCommand(IBindContext context, Validator validator) |
31 | { | 25 | { |
32 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 26 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
33 | 27 | ||
34 | this.BindPaths = context.BindPaths; | 28 | this.BindPaths = context.BindPaths; |
35 | this.CabbingThreadCount = context.CabbingThreadCount; | 29 | this.CabbingThreadCount = context.CabbingThreadCount; |
@@ -73,8 +67,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
73 | 67 | ||
74 | private Intermediate Intermediate { get; } | 68 | private Intermediate Intermediate { get; } |
75 | 69 | ||
76 | private Output Output { get; } | ||
77 | |||
78 | private string OutputPath { get; } | 70 | private string OutputPath { get; } |
79 | 71 | ||
80 | private bool SuppressAddingValidationRows { get; } | 72 | private bool SuppressAddingValidationRows { get; } |
@@ -95,22 +87,16 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
95 | 87 | ||
96 | public void Execute() | 88 | public void Execute() |
97 | { | 89 | { |
98 | this.Intermediate.Save(this.OutputPath); | 90 | var section = this.Intermediate.Sections.Single(); |
99 | #if FINISH | ||
100 | List<FileTransfer> fileTransfers = new List<FileTransfer>(); | ||
101 | 91 | ||
102 | HashSet<string> suppressedTableNames = new HashSet<string>(); | 92 | var fileTransfers = new List<FileTransfer>(); |
103 | 93 | ||
104 | // If there are any fields to resolve later, create the cache to populate during bind. | 94 | var suppressedTableNames = new HashSet<string>(); |
105 | IDictionary<string, string> variableCache = null; | ||
106 | if (this.DelayedFields.Any()) | ||
107 | { | ||
108 | variableCache = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); | ||
109 | } | ||
110 | 95 | ||
111 | this.LocalizeUI(this.Output.Tables); | 96 | // If there are any fields to resolve later, create the cache to populate during bind. |
97 | var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; | ||
112 | 98 | ||
113 | this.Output = CreateOutputFromIR(this.Intermediate); | 99 | this.LocalizeUI(section); |
114 | 100 | ||
115 | // Process the summary information table before the other tables. | 101 | // Process the summary information table before the other tables. |
116 | bool compressed; | 102 | bool compressed; |
@@ -118,8 +104,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
118 | int installerVersion; | 104 | int installerVersion; |
119 | string modularizationGuid; | 105 | string modularizationGuid; |
120 | { | 106 | { |
121 | BindSummaryInfoCommand command = new BindSummaryInfoCommand(); | 107 | var command = new BindSummaryInfoCommand(section); |
122 | command.Output = this.Output; | ||
123 | command.Execute(); | 108 | command.Execute(); |
124 | 109 | ||
125 | compressed = command.Compressed; | 110 | compressed = command.Compressed; |
@@ -128,42 +113,61 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
128 | modularizationGuid = command.ModularizationGuid; | 113 | modularizationGuid = command.ModularizationGuid; |
129 | } | 114 | } |
130 | 115 | ||
131 | // Stop processing if an error previously occurred. | 116 | // Add binder variables for all properties. |
132 | if (Messaging.Instance.EncounteredError) | 117 | if (SectionType.Product == section.Type || variableCache != null) |
133 | { | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | // Modularize identifiers and add tables with real streams to the import tables. | ||
138 | if (OutputType.Module == this.Output.Type) | ||
139 | { | 118 | { |
140 | // Gather all the suppress modularization identifiers | 119 | foreach (var propertyRow in section.Tuples.OfType<PropertyTuple>()) |
141 | HashSet<string> suppressModularizationIdentifiers = null; | ||
142 | Table wixSuppressModularizationTable = this.Output.Tables["WixSuppressModularization"]; | ||
143 | if (null != wixSuppressModularizationTable) | ||
144 | { | 120 | { |
145 | suppressModularizationIdentifiers = new HashSet<string>(wixSuppressModularizationTable.Rows.Select(row => (string)row[0])); | 121 | // Set the ProductCode if it is to be generated. |
146 | } | 122 | if ("ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) |
123 | { | ||
124 | propertyRow.Value = Common.GenerateGuid(); | ||
147 | 125 | ||
148 | foreach (Table table in this.Output.Tables) | 126 | #if TODO_FIX_INSTANCE_TRANSFORM |
149 | { | 127 | // Update the target ProductCode in any instance transforms. |
150 | table.Modularize(modularizationGuid, suppressModularizationIdentifiers); | 128 | foreach (SubStorage subStorage in this.Output.SubStorages) |
129 | { | ||
130 | Output subStorageOutput = subStorage.Data; | ||
131 | if (OutputType.Transform != subStorageOutput.Type) | ||
132 | { | ||
133 | continue; | ||
134 | } | ||
135 | |||
136 | Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; | ||
137 | foreach (Row row in instanceSummaryInformationTable.Rows) | ||
138 | { | ||
139 | if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) | ||
140 | { | ||
141 | row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | #endif | ||
147 | } | ||
148 | |||
149 | // Add the property name and value to the variableCache. | ||
150 | if (variableCache != null) | ||
151 | { | ||
152 | var key = String.Concat("property.", propertyRow.Property); | ||
153 | variableCache[key] = propertyRow.Value; | ||
154 | } | ||
151 | } | 155 | } |
152 | } | 156 | } |
153 | 157 | ||
154 | // This must occur after all variables and source paths have been resolved and after modularization. | 158 | // Sequence all the actions. |
155 | List<FileFacade> fileFacades; | ||
156 | { | 159 | { |
157 | GetFileFacadesCommand command = new GetFileFacadesCommand(); | 160 | var command = new SequenceActionsCommand(section); |
158 | command.FileTable = this.Output.Tables["File"]; | 161 | command.Messaging = Messaging.Instance; |
159 | command.WixFileTable = this.Output.Tables["WixFile"]; | ||
160 | command.WixDeltaPatchFileTable = this.Output.Tables["WixDeltaPatchFile"]; | ||
161 | command.WixDeltaPatchSymbolPathsTable = this.Output.Tables["WixDeltaPatchSymbolPaths"]; | ||
162 | command.Execute(); | 162 | command.Execute(); |
163 | } | ||
163 | 164 | ||
164 | fileFacades = command.FileFacades; | 165 | { |
166 | var command = new CreateSpecialPropertiesCommand(section); | ||
167 | command.Execute(); | ||
165 | } | 168 | } |
166 | 169 | ||
170 | #if TODO_FINISH_PATCH | ||
167 | ////if (OutputType.Patch == this.Output.Type) | 171 | ////if (OutputType.Patch == this.Output.Type) |
168 | ////{ | 172 | ////{ |
169 | //// foreach (SubStorage substorage in this.Output.SubStorages) | 173 | //// foreach (SubStorage substorage in this.Output.SubStorages) |
@@ -183,87 +187,72 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
183 | //// this.MergeUnrealTables(transform.Tables); | 187 | //// this.MergeUnrealTables(transform.Tables); |
184 | //// } | 188 | //// } |
185 | ////} | 189 | ////} |
186 | 190 | #endif | |
187 | { | ||
188 | CreateSpecialPropertiesCommand command = new CreateSpecialPropertiesCommand(); | ||
189 | command.PropertyTable = this.Output.Tables["Property"]; | ||
190 | command.WixPropertyTable = this.Output.Tables["WixProperty"]; | ||
191 | command.Execute(); | ||
192 | } | ||
193 | 191 | ||
194 | if (Messaging.Instance.EncounteredError) | 192 | if (Messaging.Instance.EncounteredError) |
195 | { | 193 | { |
196 | return; | 194 | return; |
197 | } | 195 | } |
198 | 196 | ||
199 | // Add binder variables for all properties. | 197 | Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); |
200 | Table propertyTable = this.Output.Tables["Property"]; | 198 | |
201 | if (null != propertyTable) | 199 | // This must occur after all variables and source paths have been resolved. |
200 | List<FileFacade> fileFacades; | ||
202 | { | 201 | { |
203 | foreach (PropertyRow propertyRow in propertyTable.Rows) | 202 | var command = new GetFileFacadesCommand(section); |
204 | { | 203 | command.Execute(); |
205 | // Set the ProductCode if it is to be generated. | ||
206 | if (OutputType.Product == this.Output.Type && "ProductCode".Equals(propertyRow.Property, StringComparison.Ordinal) && "*".Equals(propertyRow.Value, StringComparison.Ordinal)) | ||
207 | { | ||
208 | propertyRow.Value = Common.GenerateGuid(); | ||
209 | 204 | ||
210 | // Update the target ProductCode in any instance transforms. | 205 | fileFacades = command.FileFacades; |
211 | foreach (SubStorage subStorage in this.Output.SubStorages) | 206 | } |
212 | { | ||
213 | Output subStorageOutput = subStorage.Data; | ||
214 | if (OutputType.Transform != subStorageOutput.Type) | ||
215 | { | ||
216 | continue; | ||
217 | } | ||
218 | 207 | ||
219 | Table instanceSummaryInformationTable = subStorageOutput.Tables["_SummaryInformation"]; | 208 | // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules). |
220 | foreach (Row row in instanceSummaryInformationTable.Rows) | 209 | { |
221 | { | 210 | var command = new ExtractEmbeddedFilesCommand(this.ExpectedEmbeddedFiles); |
222 | if ((int)SummaryInformation.Transform.ProductCodes == row.FieldAsInteger(0)) | 211 | command.Execute(); |
223 | { | 212 | } |
224 | row[1] = row.FieldAsString(1).Replace("*", propertyRow.Value); | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | 213 | ||
231 | // Add the property name and value to the variableCache. | 214 | // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). |
232 | if (null != variableCache) | 215 | { |
233 | { | 216 | var command = new UpdateFileFacadesCommand(section); |
234 | string key = String.Concat("property.", Common.Demodularize(this.Output.Type, modularizationGuid, propertyRow.Property)); | 217 | command.FileFacades = fileFacades; |
235 | variableCache[key] = propertyRow.Value; | 218 | command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); |
236 | } | 219 | command.OverwriteHash = true; |
237 | } | 220 | command.TableDefinitions = this.TableDefinitions; |
221 | command.VariableCache = variableCache; | ||
222 | command.Execute(); | ||
238 | } | 223 | } |
239 | 224 | ||
240 | // Extract files that come from cabinet files (this does not extract files from merge modules). | 225 | // Now that the variable cache is populated, resolve any delayed fields. |
226 | if (this.DelayedFields.Any()) | ||
241 | { | 227 | { |
242 | ExtractEmbeddedFilesCommand command = new ExtractEmbeddedFilesCommand(); | 228 | var command = new ResolveDelayedFieldsCommand(this.DelayedFields, variableCache); |
243 | command.FilesWithEmbeddedFiles = this.ExpectedEmbeddedFiles; | ||
244 | command.Execute(); | 229 | command.Execute(); |
245 | } | 230 | } |
246 | 231 | ||
247 | if (OutputType.Product == this.Output.Type) | 232 | // Set generated component guids. |
233 | { | ||
234 | var command = new CalculateComponentGuids(section); | ||
235 | command.Execute(); | ||
236 | } | ||
237 | |||
238 | if (SectionType.Product == section.Type) | ||
248 | { | 239 | { |
249 | // Retrieve files and their information from merge modules. | 240 | // Retrieve files and their information from merge modules. |
250 | Table wixMergeTable = this.Output.Tables["WixMerge"]; | 241 | var wixMergeTuples = section.Tuples.OfType<WixMergeTuple>().ToList(); |
251 | 242 | ||
252 | if (null != wixMergeTable) | 243 | if (wixMergeTuples.Any()) |
253 | { | 244 | { |
254 | ExtractMergeModuleFilesCommand command = new ExtractMergeModuleFilesCommand(); | 245 | var command = new ExtractMergeModuleFilesCommand(section, wixMergeTuples); |
255 | command.FileFacades = fileFacades; | 246 | command.FileFacades = fileFacades; |
256 | command.FileTable = this.Output.Tables["File"]; | ||
257 | command.WixFileTable = this.Output.Tables["WixFile"]; | ||
258 | command.WixMergeTable = wixMergeTable; | ||
259 | command.OutputInstallerVersion = installerVersion; | 247 | command.OutputInstallerVersion = installerVersion; |
260 | command.SuppressLayout = this.SuppressLayout; | 248 | command.SuppressLayout = this.SuppressLayout; |
261 | command.TempFilesLocation = this.IntermediateFolder; | 249 | command.IntermediateFolder = this.IntermediateFolder; |
262 | command.Execute(); | 250 | command.Execute(); |
263 | 251 | ||
264 | fileFacades.AddRange(command.MergeModulesFileFacades); | 252 | fileFacades.AddRange(command.MergeModulesFileFacades); |
265 | } | 253 | } |
266 | } | 254 | } |
255 | #if TODO_FINISH_PATCH | ||
267 | else if (OutputType.Patch == this.Output.Type) | 256 | else if (OutputType.Patch == this.Output.Type) |
268 | { | 257 | { |
269 | // Merge transform data into the output object. | 258 | // Merge transform data into the output object. |
@@ -271,6 +260,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
271 | 260 | ||
272 | fileFacades.AddRange(filesFromTransform); | 261 | fileFacades.AddRange(filesFromTransform); |
273 | } | 262 | } |
263 | #endif | ||
274 | 264 | ||
275 | // stop processing if an error previously occurred | 265 | // stop processing if an error previously occurred |
276 | if (Messaging.Instance.EncounteredError) | 266 | if (Messaging.Instance.EncounteredError) |
@@ -278,51 +268,19 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
278 | return; | 268 | return; |
279 | } | 269 | } |
280 | 270 | ||
281 | Messaging.Instance.OnMessage(WixVerboses.UpdatingFileInformation()); | 271 | #if TODO_FIX_INSTANCE_TRANSFORM |
282 | |||
283 | // Gather information about files that did not come from merge modules (i.e. rows with a reference to the File table). | ||
284 | { | ||
285 | UpdateFileFacadesCommand command = new UpdateFileFacadesCommand(); | ||
286 | command.FileFacades = fileFacades; | ||
287 | command.UpdateFileFacades = fileFacades.Where(f => !f.FromModule); | ||
288 | command.ModularizationGuid = modularizationGuid; | ||
289 | command.Output = this.Output; | ||
290 | command.OverwriteHash = true; | ||
291 | command.TableDefinitions = this.TableDefinitions; | ||
292 | command.VariableCache = variableCache; | ||
293 | command.Execute(); | ||
294 | } | ||
295 | |||
296 | // Set generated component guids. | ||
297 | this.SetComponentGuids(this.Output); | ||
298 | |||
299 | // With the Component Guids set now we can create instance transforms. | 272 | // With the Component Guids set now we can create instance transforms. |
300 | this.CreateInstanceTransforms(this.Output); | 273 | this.CreateInstanceTransforms(this.Output); |
301 | 274 | #endif | |
302 | this.ValidateComponentGuids(this.Output); | ||
303 | |||
304 | this.UpdateControlText(this.Output); | ||
305 | |||
306 | if (this.DelayedFields.Any()) | ||
307 | { | ||
308 | ResolveDelayedFieldsCommand command = new ResolveDelayedFieldsCommand(); | ||
309 | command.OutputType = this.Output.Type; | ||
310 | command.DelayedFields = this.DelayedFields; | ||
311 | command.ModularizationGuid = null; | ||
312 | command.VariableCache = variableCache; | ||
313 | command.Execute(); | ||
314 | } | ||
315 | 275 | ||
316 | // Assign files to media. | 276 | // Assign files to media. |
317 | RowDictionary<MediaRow> assignedMediaRows; | 277 | Dictionary<int, MediaTuple> assignedMediaRows; |
318 | Dictionary<MediaRow, IEnumerable<FileFacade>> filesByCabinetMedia; | 278 | Dictionary<MediaTuple, IEnumerable<FileFacade>> filesByCabinetMedia; |
319 | IEnumerable<FileFacade> uncompressedFiles; | 279 | IEnumerable<FileFacade> uncompressedFiles; |
320 | { | 280 | { |
321 | AssignMediaCommand command = new AssignMediaCommand(); | 281 | var command = new AssignMediaCommand(section); |
322 | command.FilesCompressed = compressed; | ||
323 | command.FileFacades = fileFacades; | 282 | command.FileFacades = fileFacades; |
324 | command.Output = this.Output; | 283 | command.FilesCompressed = compressed; |
325 | command.TableDefinitions = this.TableDefinitions; | ||
326 | command.Execute(); | 284 | command.Execute(); |
327 | 285 | ||
328 | assignedMediaRows = command.MediaRows; | 286 | assignedMediaRows = command.MediaRows; |
@@ -330,15 +288,40 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
330 | uncompressedFiles = command.UncompressedFileFacades; | 288 | uncompressedFiles = command.UncompressedFileFacades; |
331 | } | 289 | } |
332 | 290 | ||
333 | // Update file sequence. | ||
334 | this.UpdateMediaSequences(this.Output.Type, fileFacades, assignedMediaRows); | ||
335 | |||
336 | // stop processing if an error previously occurred | 291 | // stop processing if an error previously occurred |
337 | if (Messaging.Instance.EncounteredError) | 292 | if (Messaging.Instance.EncounteredError) |
338 | { | 293 | { |
339 | return; | 294 | return; |
340 | } | 295 | } |
341 | 296 | ||
297 | // Try to put as much above here as possible, updating the IR is better. | ||
298 | Output output; | ||
299 | { | ||
300 | var command = new CreateOutputFromIRCommand(section, this.TableDefinitions); | ||
301 | command.Execute(); | ||
302 | |||
303 | output = command.Output; | ||
304 | } | ||
305 | |||
306 | // Update file sequence. | ||
307 | { | ||
308 | var command = new UpdateMediaSequencesCommand(output, fileFacades, assignedMediaRows); | ||
309 | command.Execute(); | ||
310 | } | ||
311 | |||
312 | // Modularize identifiers and add tables with real streams to the import tables. | ||
313 | if (OutputType.Module == output.Type) | ||
314 | { | ||
315 | // Gather all the suppress modularization identifiers | ||
316 | var suppressModularizationIdentifiers = new HashSet<string>(section.Tuples.OfType<WixSuppressModularizationTuple>().Select(s => s.WixSuppressModularization)); | ||
317 | |||
318 | foreach (var table in output.Tables) | ||
319 | { | ||
320 | table.Modularize(modularizationGuid, suppressModularizationIdentifiers); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | #if TODO_FINISH_UPDATE | ||
342 | // Extended binder extensions can be called now that fields are resolved. | 325 | // Extended binder extensions can be called now that fields are resolved. |
343 | { | 326 | { |
344 | Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); | 327 | Table updatedFiles = this.Output.EnsureTable(this.TableDefinitions["WixBindUpdatedFiles"]); |
@@ -372,27 +355,27 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
372 | command.Execute(); | 355 | command.Execute(); |
373 | } | 356 | } |
374 | } | 357 | } |
358 | #endif | ||
375 | 359 | ||
376 | // stop processing if an error previously occurred | 360 | // Stop processing if an error previously occurred. |
377 | if (Messaging.Instance.EncounteredError) | 361 | if (Messaging.Instance.EncounteredError) |
378 | { | 362 | { |
379 | return; | 363 | return; |
380 | } | 364 | } |
381 | 365 | ||
366 | // Ensure the intermediate folder is created since delta patches will be | ||
367 | // created there. | ||
382 | Directory.CreateDirectory(this.IntermediateFolder); | 368 | Directory.CreateDirectory(this.IntermediateFolder); |
383 | 369 | ||
384 | if (OutputType.Patch == this.Output.Type && this.DeltaBinaryPatch) | 370 | if (SectionType.Patch == section.Type && this.DeltaBinaryPatch) |
385 | { | 371 | { |
386 | CreateDeltaPatchesCommand command = new CreateDeltaPatchesCommand(); | 372 | var command = new CreateDeltaPatchesCommand(fileFacades, this.IntermediateFolder, section.Tuples.OfType<WixPatchIdTuple>().FirstOrDefault()); |
387 | command.FileFacades = fileFacades; | ||
388 | command.WixPatchIdTable = this.Output.Tables["WixPatchId"]; | ||
389 | command.TempFilesLocation = this.IntermediateFolder; | ||
390 | command.Execute(); | 373 | command.Execute(); |
391 | } | 374 | } |
392 | 375 | ||
393 | // create cabinet files and process uncompressed files | 376 | // create cabinet files and process uncompressed files |
394 | string layoutDirectory = Path.GetDirectoryName(this.OutputPath); | 377 | string layoutDirectory = Path.GetDirectoryName(this.OutputPath); |
395 | if (!this.SuppressLayout || OutputType.Module == this.Output.Type) | 378 | if (!this.SuppressLayout || OutputType.Module == output.Type) |
396 | { | 379 | { |
397 | Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); | 380 | Messaging.Instance.OnMessage(WixVerboses.CreatingCabinetFiles()); |
398 | 381 | ||
@@ -400,7 +383,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
400 | command.CabbingThreadCount = this.CabbingThreadCount; | 383 | command.CabbingThreadCount = this.CabbingThreadCount; |
401 | command.CabCachePath = this.CabCachePath; | 384 | command.CabCachePath = this.CabCachePath; |
402 | command.DefaultCompressionLevel = this.DefaultCompressionLevel; | 385 | command.DefaultCompressionLevel = this.DefaultCompressionLevel; |
403 | command.Output = this.Output; | 386 | command.Output = output; |
404 | command.BackendExtensions = this.BackendExtensions; | 387 | command.BackendExtensions = this.BackendExtensions; |
405 | command.LayoutDirectory = layoutDirectory; | 388 | command.LayoutDirectory = layoutDirectory; |
406 | command.Compressed = compressed; | 389 | command.Compressed = compressed; |
@@ -408,39 +391,35 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
408 | command.ResolveMedia = this.ResolveMedia; | 391 | command.ResolveMedia = this.ResolveMedia; |
409 | command.TableDefinitions = this.TableDefinitions; | 392 | command.TableDefinitions = this.TableDefinitions; |
410 | command.TempFilesLocation = this.IntermediateFolder; | 393 | command.TempFilesLocation = this.IntermediateFolder; |
411 | command.WixMediaTable = this.Output.Tables["WixMedia"]; | 394 | command.WixMediaTable = output.Tables["WixMedia"]; |
412 | command.Execute(); | 395 | command.Execute(); |
413 | 396 | ||
414 | fileTransfers.AddRange(command.FileTransfers); | 397 | fileTransfers.AddRange(command.FileTransfers); |
415 | } | 398 | } |
416 | 399 | ||
400 | #if TODO_FINISH_PATCH | ||
417 | if (OutputType.Patch == this.Output.Type) | 401 | if (OutputType.Patch == this.Output.Type) |
418 | { | 402 | { |
419 | // copy output data back into the transforms | 403 | // copy output data back into the transforms |
420 | this.CopyToTransformData(this.Output); | 404 | this.CopyToTransformData(this.Output); |
421 | } | 405 | } |
406 | #endif | ||
422 | 407 | ||
423 | // stop processing if an error previously occurred | 408 | // Add back suppressed tables which must be present prior to merging in modules. |
424 | if (Messaging.Instance.EncounteredError) | 409 | if (OutputType.Product == output.Type) |
425 | { | ||
426 | return; | ||
427 | } | ||
428 | |||
429 | // add back suppressed tables which must be present prior to merging in modules | ||
430 | if (OutputType.Product == this.Output.Type) | ||
431 | { | 410 | { |
432 | Table wixMergeTable = this.Output.Tables["WixMerge"]; | 411 | Table wixMergeTable = output.Tables["WixMerge"]; |
433 | 412 | ||
434 | if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count) | 413 | if (null != wixMergeTable && 0 < wixMergeTable.Rows.Count) |
435 | { | 414 | { |
436 | foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) | 415 | foreach (SequenceTable sequence in Enum.GetValues(typeof(SequenceTable))) |
437 | { | 416 | { |
438 | string sequenceTableName = sequence.ToString(); | 417 | string sequenceTableName = sequence.ToString(); |
439 | Table sequenceTable = this.Output.Tables[sequenceTableName]; | 418 | Table sequenceTable = output.Tables[sequenceTableName]; |
440 | 419 | ||
441 | if (null == sequenceTable) | 420 | if (null == sequenceTable) |
442 | { | 421 | { |
443 | sequenceTable = this.Output.EnsureTable(this.TableDefinitions[sequenceTableName]); | 422 | sequenceTable = output.EnsureTable(this.TableDefinitions[sequenceTableName]); |
444 | } | 423 | } |
445 | 424 | ||
446 | if (0 == sequenceTable.Rows.Count) | 425 | if (0 == sequenceTable.Rows.Count) |
@@ -456,67 +435,59 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
456 | // extension.PostBind(this.Context); | 435 | // extension.PostBind(this.Context); |
457 | //} | 436 | //} |
458 | 437 | ||
459 | // generate database file | 438 | this.ValidateComponentGuids(output); |
439 | |||
440 | // stop processing if an error previously occurred | ||
441 | if (Messaging.Instance.EncounteredError) | ||
442 | { | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | // Generate database file. | ||
460 | Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); | 447 | Messaging.Instance.OnMessage(WixVerboses.GeneratingDatabase()); |
461 | string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); | 448 | string tempDatabaseFile = Path.Combine(this.IntermediateFolder, Path.GetFileName(this.OutputPath)); |
462 | this.GenerateDatabase(this.Output, tempDatabaseFile, false, false); | 449 | this.GenerateDatabase(output, tempDatabaseFile, false, false); |
463 | 450 | ||
464 | FileTransfer transfer; | 451 | if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, output.Type.ToString(), null, out var transfer)) // note where this database needs to move in the future |
465 | if (FileTransfer.TryCreate(tempDatabaseFile, this.OutputPath, true, this.Output.Type.ToString(), null, out transfer)) // note where this database needs to move in the future | ||
466 | { | 452 | { |
467 | transfer.Built = true; | 453 | transfer.Built = true; |
468 | fileTransfers.Add(transfer); | 454 | fileTransfers.Add(transfer); |
469 | } | 455 | } |
470 | 456 | ||
471 | // stop processing if an error previously occurred | 457 | // Stop processing if an error previously occurred. |
472 | if (Messaging.Instance.EncounteredError) | 458 | if (Messaging.Instance.EncounteredError) |
473 | { | 459 | { |
474 | return; | 460 | return; |
475 | } | 461 | } |
476 | 462 | ||
477 | // Output the output to a file | 463 | // Output the output to a file. |
478 | Pdb pdb = new Pdb(); | 464 | Pdb pdb = new Pdb(); |
479 | pdb.Output = this.Output; | 465 | pdb.Output = output; |
480 | if (!String.IsNullOrEmpty(this.PdbFile)) | 466 | if (!String.IsNullOrEmpty(this.PdbFile)) |
481 | { | 467 | { |
482 | pdb.Save(this.PdbFile); | 468 | pdb.Save(this.PdbFile); |
483 | } | 469 | } |
484 | 470 | ||
485 | // Merge modules. | 471 | // Merge modules. |
486 | if (OutputType.Product == this.Output.Type) | 472 | if (OutputType.Product == output.Type) |
487 | { | 473 | { |
488 | Messaging.Instance.OnMessage(WixVerboses.MergingModules()); | 474 | Messaging.Instance.OnMessage(WixVerboses.MergingModules()); |
489 | 475 | ||
490 | MergeModulesCommand command = new MergeModulesCommand(); | 476 | var command = new MergeModulesCommand(); |
491 | command.FileFacades = fileFacades; | 477 | command.FileFacades = fileFacades; |
492 | command.Output = this.Output; | 478 | command.Output = output; |
493 | command.OutputPath = tempDatabaseFile; | 479 | command.OutputPath = tempDatabaseFile; |
494 | command.SuppressedTableNames = suppressedTableNames; | 480 | command.SuppressedTableNames = suppressedTableNames; |
495 | command.Execute(); | 481 | command.Execute(); |
496 | |||
497 | // stop processing if an error previously occurred | ||
498 | if (Messaging.Instance.EncounteredError) | ||
499 | { | ||
500 | return; | ||
501 | } | ||
502 | } | 482 | } |
503 | 483 | ||
504 | // inspect the MSI prior to running ICEs | ||
505 | //InspectorCore inspectorCore = new InspectorCore(); | ||
506 | //foreach (InspectorExtension inspectorExtension in this.InspectorExtensions) | ||
507 | //{ | ||
508 | // inspectorExtension.Core = inspectorCore; | ||
509 | // inspectorExtension.InspectDatabase(tempDatabaseFile, pdb); | ||
510 | |||
511 | // inspectorExtension.Core = null; // reset. | ||
512 | //} | ||
513 | |||
514 | if (Messaging.Instance.EncounteredError) | 484 | if (Messaging.Instance.EncounteredError) |
515 | { | 485 | { |
516 | return; | 486 | return; |
517 | } | 487 | } |
518 | 488 | ||
519 | // validate the output if there is an MSI validator | 489 | #if TODO_FINISH_VALIDATION |
490 | // Validate the output if there is an MSI validator. | ||
520 | if (null != this.Validator) | 491 | if (null != this.Validator) |
521 | { | 492 | { |
522 | Stopwatch stopwatch = Stopwatch.StartNew(); | 493 | Stopwatch stopwatch = Stopwatch.StartNew(); |
@@ -537,19 +508,18 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
537 | return; | 508 | return; |
538 | } | 509 | } |
539 | } | 510 | } |
511 | #endif | ||
540 | 512 | ||
541 | // Process uncompressed files. | 513 | // Process uncompressed files. |
542 | if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) | 514 | if (!Messaging.Instance.EncounteredError && !this.SuppressLayout && uncompressedFiles.Any()) |
543 | { | 515 | { |
544 | var command = new ProcessUncompressedFilesCommand(); | 516 | var command = new ProcessUncompressedFilesCommand(section); |
545 | command.Compressed = compressed; | 517 | command.Compressed = compressed; |
546 | command.FileFacades = uncompressedFiles; | 518 | command.FileFacades = uncompressedFiles; |
547 | command.LayoutDirectory = layoutDirectory; | 519 | command.LayoutDirectory = layoutDirectory; |
548 | command.LongNamesInImage = longNames; | 520 | command.LongNamesInImage = longNames; |
549 | command.MediaRows = assignedMediaRows; | ||
550 | command.ResolveMedia = this.ResolveMedia; | 521 | command.ResolveMedia = this.ResolveMedia; |
551 | command.DatabasePath = tempDatabaseFile; | 522 | command.DatabasePath = tempDatabaseFile; |
552 | command.WixMediaTable = this.Output.Tables["WixMedia"]; | ||
553 | command.Execute(); | 523 | command.Execute(); |
554 | 524 | ||
555 | fileTransfers.AddRange(command.FileTransfers); | 525 | fileTransfers.AddRange(command.FileTransfers); |
@@ -557,94 +527,92 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
557 | 527 | ||
558 | this.FileTransfers = fileTransfers; | 528 | this.FileTransfers = fileTransfers; |
559 | this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList(); | 529 | this.ContentFilePaths = fileFacades.Select(r => r.WixFile.Source).ToList(); |
530 | |||
531 | // TODO: Eventually this gets removed | ||
532 | var intermediate = new Intermediate(this.Intermediate.Id, new[] { section }, this.Intermediate.Localizations.ToDictionary(l => l.Culture, StringComparer.OrdinalIgnoreCase), this.Intermediate.EmbedFilePaths); | ||
533 | intermediate.Save(Path.ChangeExtension(this.OutputPath, "wir")); | ||
560 | } | 534 | } |
561 | 535 | ||
562 | /// <summary> | 536 | /// <summary> |
563 | /// Localize dialogs and controls. | 537 | /// Localize dialogs and controls. |
564 | /// </summary> | 538 | /// </summary> |
565 | /// <param name="tables">The tables to localize.</param> | 539 | /// <param name="tables">The tables to localize.</param> |
566 | private void LocalizeUI(TableIndexedCollection tables) | 540 | private void LocalizeUI(IntermediateSection section) |
567 | { | 541 | { |
568 | Table dialogTable = tables["Dialog"]; | 542 | foreach (var row in section.Tuples.OfType<DialogTuple>()) |
569 | if (null != dialogTable) | ||
570 | { | 543 | { |
571 | foreach (Row row in dialogTable.Rows) | 544 | string dialog = row.Dialog; |
572 | { | ||
573 | string dialog = (string)row[0]; | ||
574 | 545 | ||
575 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) | 546 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, null, out LocalizedControl localizedControl)) |
547 | { | ||
548 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
576 | { | 549 | { |
577 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | 550 | row.HCentering = localizedControl.X; |
578 | { | 551 | } |
579 | row[1] = localizedControl.X; | ||
580 | } | ||
581 | 552 | ||
582 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | 553 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) |
583 | { | 554 | { |
584 | row[2] = localizedControl.Y; | 555 | row.VCentering = localizedControl.Y; |
585 | } | 556 | } |
586 | 557 | ||
587 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | 558 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) |
588 | { | 559 | { |
589 | row[3] = localizedControl.Width; | 560 | row.Width = localizedControl.Width; |
590 | } | 561 | } |
591 | 562 | ||
592 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | 563 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) |
593 | { | 564 | { |
594 | row[4] = localizedControl.Height; | 565 | row.Height = localizedControl.Height; |
595 | } | 566 | } |
596 | 567 | ||
597 | row[5] = (int)row[5] | localizedControl.Attributes; | 568 | row.Attributes = row.Attributes | localizedControl.Attributes; |
598 | 569 | ||
599 | if (!String.IsNullOrEmpty(localizedControl.Text)) | 570 | if (!String.IsNullOrEmpty(localizedControl.Text)) |
600 | { | 571 | { |
601 | row[6] = localizedControl.Text; | 572 | row.Title = localizedControl.Text; |
602 | } | ||
603 | } | 573 | } |
604 | } | 574 | } |
605 | } | 575 | } |
606 | 576 | ||
607 | Table controlTable = tables["Control"]; | 577 | |
608 | if (null != controlTable) | 578 | foreach (var row in section.Tuples.OfType<ControlTuple>()) |
609 | { | 579 | { |
610 | foreach (Row row in controlTable.Rows) | 580 | string dialog = row.Dialog_; |
611 | { | 581 | string control = row.Control; |
612 | string dialog = (string)row[0]; | ||
613 | string control = (string)row[1]; | ||
614 | 582 | ||
615 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) | 583 | if (this.WixVariableResolver.TryGetLocalizedControl(dialog, control, out LocalizedControl localizedControl)) |
584 | { | ||
585 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | ||
616 | { | 586 | { |
617 | if (CompilerConstants.IntegerNotSet != localizedControl.X) | 587 | row.X = localizedControl.X; |
618 | { | 588 | } |
619 | row[3] = localizedControl.X.ToString(); | ||
620 | } | ||
621 | 589 | ||
622 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) | 590 | if (CompilerConstants.IntegerNotSet != localizedControl.Y) |
623 | { | 591 | { |
624 | row[4] = localizedControl.Y.ToString(); | 592 | row.Y = localizedControl.Y; |
625 | } | 593 | } |
626 | 594 | ||
627 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) | 595 | if (CompilerConstants.IntegerNotSet != localizedControl.Width) |
628 | { | 596 | { |
629 | row[5] = localizedControl.Width.ToString(); | 597 | row.Width = localizedControl.Width; |
630 | } | 598 | } |
631 | 599 | ||
632 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) | 600 | if (CompilerConstants.IntegerNotSet != localizedControl.Height) |
633 | { | 601 | { |
634 | row[6] = localizedControl.Height.ToString(); | 602 | row.Height = localizedControl.Height; |
635 | } | 603 | } |
636 | 604 | ||
637 | row[7] = (int)row[7] | localizedControl.Attributes; | 605 | row.Attributes = row.Attributes | localizedControl.Attributes; |
638 | 606 | ||
639 | if (!String.IsNullOrEmpty(localizedControl.Text)) | 607 | if (!String.IsNullOrEmpty(localizedControl.Text)) |
640 | { | 608 | { |
641 | row[9] = localizedControl.Text; | 609 | row.Text = localizedControl.Text; |
642 | } | ||
643 | } | 610 | } |
644 | } | 611 | } |
645 | } | 612 | } |
646 | } | 613 | } |
647 | 614 | ||
615 | #if TODO_FINISH_PATCH | ||
648 | /// <summary> | 616 | /// <summary> |
649 | /// Copy file data between transform substorages and the patch output object | 617 | /// Copy file data between transform substorages and the patch output object |
650 | /// </summary> | 618 | /// </summary> |
@@ -674,269 +642,10 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
674 | command.TableDefinitions = this.TableDefinitions; | 642 | command.TableDefinitions = this.TableDefinitions; |
675 | command.Execute(); | 643 | command.Execute(); |
676 | } | 644 | } |
645 | #endif | ||
677 | 646 | ||
678 | private void UpdateMediaSequences(OutputType outputType, IEnumerable<FileFacade> fileFacades, RowDictionary<MediaRow> mediaRows) | ||
679 | { | ||
680 | // Calculate sequence numbers and media disk id layout for all file media information objects. | ||
681 | if (OutputType.Module == outputType) | ||
682 | { | ||
683 | int lastSequence = 0; | ||
684 | foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI. | ||
685 | { | ||
686 | facade.File.Sequence = ++lastSequence; | ||
687 | } | ||
688 | } | ||
689 | else | ||
690 | { | ||
691 | int lastSequence = 0; | ||
692 | MediaRow mediaRow = null; | ||
693 | Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>(); | ||
694 | |||
695 | // sequence the non-patch-added files | ||
696 | foreach (FileFacade facade in fileFacades) // TODO: Sort these rows directory path and component id and maybe file size or file extension and other creative ideas to get optimal install speed out of MSI. | ||
697 | { | ||
698 | if (null == mediaRow) | ||
699 | { | ||
700 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
701 | if (OutputType.Patch == outputType) | ||
702 | { | ||
703 | // patch Media cannot start at zero | ||
704 | lastSequence = mediaRow.LastSequence; | ||
705 | } | ||
706 | } | ||
707 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
708 | { | ||
709 | mediaRow.LastSequence = lastSequence; | ||
710 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
711 | } | ||
712 | |||
713 | if (0 < facade.WixFile.PatchGroup) | ||
714 | { | ||
715 | List<FileFacade> patchGroup = patchGroups[facade.WixFile.PatchGroup]; | ||
716 | |||
717 | if (null == patchGroup) | ||
718 | { | ||
719 | patchGroup = new List<FileFacade>(); | ||
720 | patchGroups.Add(facade.WixFile.PatchGroup, patchGroup); | ||
721 | } | ||
722 | |||
723 | patchGroup.Add(facade); | ||
724 | } | ||
725 | else | ||
726 | { | ||
727 | facade.File.Sequence = ++lastSequence; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | if (null != mediaRow) | ||
732 | { | ||
733 | mediaRow.LastSequence = lastSequence; | ||
734 | mediaRow = null; | ||
735 | } | ||
736 | |||
737 | // sequence the patch-added files | ||
738 | foreach (List<FileFacade> patchGroup in patchGroups.Values) | ||
739 | { | ||
740 | foreach (FileFacade facade in patchGroup) | ||
741 | { | ||
742 | if (null == mediaRow) | ||
743 | { | ||
744 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
745 | } | ||
746 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
747 | { | ||
748 | mediaRow.LastSequence = lastSequence; | ||
749 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
750 | } | ||
751 | |||
752 | facade.File.Sequence = ++lastSequence; | ||
753 | } | ||
754 | } | ||
755 | |||
756 | if (null != mediaRow) | ||
757 | { | ||
758 | mediaRow.LastSequence = lastSequence; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | |||
763 | /// <summary> | ||
764 | /// Set the guids for components with generatable guids. | ||
765 | /// </summary> | ||
766 | /// <param name="output">Internal representation of the database to operate on.</param> | ||
767 | private void SetComponentGuids(Output output) | ||
768 | { | ||
769 | Table componentTable = output.Tables["Component"]; | ||
770 | if (null != componentTable) | ||
771 | { | ||
772 | Hashtable registryKeyRows = null; | ||
773 | Hashtable directories = null; | ||
774 | Hashtable componentIdGenSeeds = null; | ||
775 | Dictionary<string, List<FileRow>> fileRows = null; | ||
776 | |||
777 | // find components with generatable guids | ||
778 | foreach (ComponentRow componentRow in componentTable.Rows) | ||
779 | { | ||
780 | // component guid will be generated | ||
781 | if ("*" == componentRow.Guid) | ||
782 | { | ||
783 | if (null == componentRow.KeyPath || componentRow.IsOdbcDataSourceKeyPath) | ||
784 | { | ||
785 | Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); | ||
786 | } | ||
787 | else if (componentRow.IsRegistryKeyPath) | ||
788 | { | ||
789 | if (null == registryKeyRows) | ||
790 | { | ||
791 | Table registryTable = output.Tables["Registry"]; | ||
792 | |||
793 | registryKeyRows = new Hashtable(registryTable.Rows.Count); | ||
794 | |||
795 | foreach (Row registryRow in registryTable.Rows) | ||
796 | { | ||
797 | registryKeyRows.Add((string)registryRow[0], registryRow); | ||
798 | } | ||
799 | } | ||
800 | |||
801 | Row foundRow = registryKeyRows[componentRow.KeyPath] as Row; | ||
802 | |||
803 | string bitness = componentRow.Is64Bit ? "64" : String.Empty; | ||
804 | if (null != foundRow) | ||
805 | { | ||
806 | string regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]); | ||
807 | componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant(); | ||
808 | } | ||
809 | } | ||
810 | else // must be a File KeyPath | ||
811 | { | ||
812 | // if the directory table hasn't been loaded into an indexed hash | ||
813 | // of directory ids to target names do that now. | ||
814 | if (null == directories) | ||
815 | { | ||
816 | Table directoryTable = output.Tables["Directory"]; | ||
817 | |||
818 | int numDirectoryTableRows = (null != directoryTable) ? directoryTable.Rows.Count : 0; | ||
819 | |||
820 | directories = new Hashtable(numDirectoryTableRows); | ||
821 | |||
822 | // get the target paths for all directories | ||
823 | if (null != directoryTable) | ||
824 | { | ||
825 | foreach (Row row in directoryTable.Rows) | ||
826 | { | ||
827 | // if the directory Id already exists, we will skip it here since | ||
828 | // checking for duplicate primary keys is done later when importing tables | ||
829 | // into database | ||
830 | if (directories.ContainsKey(row[0])) | ||
831 | { | ||
832 | continue; | ||
833 | } | ||
834 | |||
835 | string targetName = Common.GetName((string)row[2], false, true); | ||
836 | directories.Add(row[0], new ResolvedDirectory((string)row[1], targetName)); | ||
837 | } | ||
838 | } | ||
839 | } | ||
840 | |||
841 | // if the component id generation seeds have not been indexed | ||
842 | // from the WixDirectory table do that now. | ||
843 | if (null == componentIdGenSeeds) | ||
844 | { | ||
845 | Table wixDirectoryTable = output.Tables["WixDirectory"]; | ||
846 | |||
847 | int numWixDirectoryRows = (null != wixDirectoryTable) ? wixDirectoryTable.Rows.Count : 0; | ||
848 | |||
849 | componentIdGenSeeds = new Hashtable(numWixDirectoryRows); | ||
850 | |||
851 | // if there are any WixDirectory rows, build up the Component Guid | ||
852 | // generation seeds indexed by Directory/@Id. | ||
853 | if (null != wixDirectoryTable) | ||
854 | { | ||
855 | foreach (Row row in wixDirectoryTable.Rows) | ||
856 | { | ||
857 | componentIdGenSeeds.Add(row[0], (string)row[1]); | ||
858 | } | ||
859 | } | ||
860 | } | ||
861 | |||
862 | // if the file rows have not been indexed by File.Component yet | ||
863 | // then do that now | ||
864 | if (null == fileRows) | ||
865 | { | ||
866 | Table fileTable = output.Tables["File"]; | ||
867 | |||
868 | int numFileRows = (null != fileTable) ? fileTable.Rows.Count : 0; | ||
869 | |||
870 | fileRows = new Dictionary<string, List<FileRow>>(numFileRows); | ||
871 | |||
872 | if (null != fileTable) | ||
873 | { | ||
874 | foreach (FileRow file in fileTable.Rows) | ||
875 | { | ||
876 | List<FileRow> files; | ||
877 | if (!fileRows.TryGetValue(file.Component, out files)) | ||
878 | { | ||
879 | files = new List<FileRow>(); | ||
880 | fileRows.Add(file.Component, files); | ||
881 | } | ||
882 | |||
883 | files.Add(file); | ||
884 | } | ||
885 | } | ||
886 | } | ||
887 | |||
888 | // validate component meets all the conditions to have a generated guid | ||
889 | List<FileRow> currentComponentFiles = fileRows[componentRow.Component]; | ||
890 | int numFilesInComponent = currentComponentFiles.Count; | ||
891 | string path = null; | ||
892 | |||
893 | foreach (FileRow fileRow in currentComponentFiles) | ||
894 | { | ||
895 | if (fileRow.File == componentRow.KeyPath) | ||
896 | { | ||
897 | // calculate the key file's canonical target path | ||
898 | string directoryPath = Binder.GetDirectoryPath(directories, componentIdGenSeeds, componentRow.Directory, true); | ||
899 | string fileName = Common.GetName(fileRow.FileName, false, true).ToLower(CultureInfo.InvariantCulture); | ||
900 | path = Path.Combine(directoryPath, fileName); | ||
901 | |||
902 | // find paths that are not canonicalized | ||
903 | if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) || | ||
904 | path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) || | ||
905 | path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) || | ||
906 | path.StartsWith("TARGETDIR", StringComparison.Ordinal) || | ||
907 | path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || | ||
908 | path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) | ||
909 | { | ||
910 | Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component, path)); | ||
911 | } | ||
912 | |||
913 | // if component has more than one file, the key path must be versioned | ||
914 | if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) | ||
915 | { | ||
916 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); | ||
917 | } | ||
918 | } | ||
919 | else | ||
920 | { | ||
921 | // not a key path, so it must be an unversioned file if component has more than one file | ||
922 | if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) | ||
923 | { | ||
924 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); | ||
925 | } | ||
926 | } | ||
927 | } | ||
928 | |||
929 | // if the rules were followed, reward with a generated guid | ||
930 | if (!Messaging.Instance.EncounteredError) | ||
931 | { | ||
932 | componentRow.Guid = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); | ||
933 | } | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | } | ||
938 | } | ||
939 | 647 | ||
648 | #if TODO_FIX_INSTANCE_TRANSFORM | ||
940 | /// <summary> | 649 | /// <summary> |
941 | /// Creates instance transform substorages in the output. | 650 | /// Creates instance transform substorages in the output. |
942 | /// </summary> | 651 | /// </summary> |
@@ -1171,6 +880,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1171 | } | 880 | } |
1172 | } | 881 | } |
1173 | } | 882 | } |
883 | #endif | ||
1174 | 884 | ||
1175 | /// <summary> | 885 | /// <summary> |
1176 | /// Validate that there are no duplicate GUIDs in the output. | 886 | /// Validate that there are no duplicate GUIDs in the output. |
@@ -1186,7 +896,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1186 | { | 896 | { |
1187 | Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count); | 897 | Dictionary<string, bool> componentGuidConditions = new Dictionary<string, bool>(componentTable.Rows.Count); |
1188 | 898 | ||
1189 | foreach (ComponentRow row in componentTable.Rows) | 899 | foreach (Data.Rows.ComponentRow row in componentTable.Rows) |
1190 | { | 900 | { |
1191 | // we don't care about unmanaged components and if there's a * GUID remaining, | 901 | // we don't care about unmanaged components and if there's a * GUID remaining, |
1192 | // there's already an error that prevented it from being replaced with a real GUID. | 902 | // there's already an error that prevented it from being replaced with a real GUID. |
@@ -1221,7 +931,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1221 | /// <param name="output">Internal representation of the msi database to operate upon.</param> | 931 | /// <param name="output">Internal representation of the msi database to operate upon.</param> |
1222 | private void UpdateControlText(Output output) | 932 | private void UpdateControlText(Output output) |
1223 | { | 933 | { |
1224 | UpdateControlTextCommand command = new UpdateControlTextCommand(); | 934 | var command = new UpdateControlTextCommand(); |
1225 | command.BBControlTable = output.Tables["BBControl"]; | 935 | command.BBControlTable = output.Tables["BBControl"]; |
1226 | command.WixBBControlTable = output.Tables["WixBBControl"]; | 936 | command.WixBBControlTable = output.Tables["WixBBControl"]; |
1227 | command.ControlTable = output.Tables["Control"]; | 937 | command.ControlTable = output.Tables["Control"]; |
@@ -1229,7 +939,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1229 | command.Execute(); | 939 | command.Execute(); |
1230 | } | 940 | } |
1231 | 941 | ||
1232 | private string ResolveMedia(MediaRow mediaRow, string mediaLayoutDirectory, string layoutDirectory) | 942 | private string ResolveMedia(MediaTuple mediaRow, string mediaLayoutDirectory, string layoutDirectory) |
1233 | { | 943 | { |
1234 | string layout = null; | 944 | string layout = null; |
1235 | 945 | ||
@@ -1282,7 +992,6 @@ namespace WixToolset.Core.WindowsInstaller.Bind | |||
1282 | command.TempFilesLocation = this.IntermediateFolder; | 992 | command.TempFilesLocation = this.IntermediateFolder; |
1283 | command.Codepage = this.Codepage; | 993 | command.Codepage = this.Codepage; |
1284 | command.Execute(); | 994 | command.Execute(); |
1285 | #endif | ||
1286 | } | 995 | } |
1287 | } | 996 | } |
1288 | } | 997 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs index 5471792d..c9286a38 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindSummaryInfoCommand.cs | |||
@@ -1,20 +1,24 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Globalization; | 6 | using System.Globalization; |
7 | using System.Linq; | ||
7 | using WixToolset.Data; | 8 | using WixToolset.Data; |
9 | using WixToolset.Data.Tuples; | ||
8 | 10 | ||
9 | /// <summary> | 11 | /// <summary> |
10 | /// Binds the summary information table of a database. | 12 | /// Binds the summary information table of a database. |
11 | /// </summary> | 13 | /// </summary> |
12 | internal class BindSummaryInfoCommand | 14 | internal class BindSummaryInfoCommand |
13 | { | 15 | { |
14 | /// <summary> | 16 | public BindSummaryInfoCommand(IntermediateSection section) |
15 | /// The output to bind. | 17 | { |
16 | /// </summary> | 18 | this.Section = section; |
17 | public Output Output { private get; set; } | 19 | } |
20 | |||
21 | private IntermediateSection Section { get; } | ||
18 | 22 | ||
19 | /// <summary> | 23 | /// <summary> |
20 | /// Returns a flag indicating if files are compressed by default. | 24 | /// Returns a flag indicating if files are compressed by default. |
@@ -40,95 +44,97 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
40 | this.InstallerVersion = 0; | 44 | this.InstallerVersion = 0; |
41 | this.ModularizationGuid = null; | 45 | this.ModularizationGuid = null; |
42 | 46 | ||
43 | Table summaryInformationTable = this.Output.Tables["_SummaryInformation"]; | 47 | bool foundCreateDataTime = false; |
48 | bool foundLastSaveDataTime = false; | ||
49 | bool foundCreatingApplication = false; | ||
50 | string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); | ||
44 | 51 | ||
45 | if (null != summaryInformationTable) | 52 | foreach (var summaryInformationRow in this.Section.Tuples.OfType<_SummaryInformationTuple>()) |
46 | { | 53 | { |
47 | bool foundCreateDataTime = false; | 54 | switch (summaryInformationRow.PropertyId) |
48 | bool foundLastSaveDataTime = false; | ||
49 | bool foundCreatingApplication = false; | ||
50 | string now = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture); | ||
51 | |||
52 | foreach (Row summaryInformationRow in summaryInformationTable.Rows) | ||
53 | { | 55 | { |
54 | switch (summaryInformationRow.FieldAsInteger(0)) | 56 | case 1: // PID_CODEPAGE |
55 | { | ||
56 | case 1: // PID_CODEPAGE | ||
57 | // make sure the code page is an int and not a web name or null | 57 | // make sure the code page is an int and not a web name or null |
58 | string codepage = summaryInformationRow.FieldAsString(1); | 58 | var codepage = summaryInformationRow.Value; |
59 | |||
60 | if (null == codepage) | ||
61 | { | ||
62 | codepage = "0"; | ||
63 | } | ||
64 | else | ||
65 | { | ||
66 | summaryInformationRow[1] = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); | ||
67 | } | ||
68 | break; | ||
69 | case 9: // PID_REVNUMBER | ||
70 | string packageCode = (string)summaryInformationRow[1]; | ||
71 | |||
72 | if (OutputType.Module == this.Output.Type) | ||
73 | { | ||
74 | this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_'); | ||
75 | } | ||
76 | else if ("*" == packageCode) | ||
77 | { | ||
78 | // set the revision number (package/patch code) if it should be automatically generated | ||
79 | summaryInformationRow[1] = Common.GenerateGuid(); | ||
80 | } | ||
81 | break; | ||
82 | case 12: // PID_CREATE_DTM | ||
83 | foundCreateDataTime = true; | ||
84 | break; | ||
85 | case 13: // PID_LASTSAVE_DTM | ||
86 | foundLastSaveDataTime = true; | ||
87 | break; | ||
88 | case 14: | ||
89 | this.InstallerVersion = summaryInformationRow.FieldAsInteger(1); | ||
90 | break; | ||
91 | case 15: // PID_WORDCOUNT | ||
92 | if (OutputType.Patch == this.Output.Type) | ||
93 | { | ||
94 | this.LongNames = true; | ||
95 | this.Compressed = true; | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | this.LongNames = (0 == (summaryInformationRow.FieldAsInteger(1) & 1)); | ||
100 | this.Compressed = (2 == (summaryInformationRow.FieldAsInteger(1) & 2)); | ||
101 | } | ||
102 | break; | ||
103 | case 18: // PID_APPNAME | ||
104 | foundCreatingApplication = true; | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | 59 | ||
109 | // add a summary information row for the create time/date property if its not already set | 60 | if (String.IsNullOrEmpty(codepage)) |
110 | if (!foundCreateDataTime) | 61 | { |
111 | { | 62 | codepage = "0"; |
112 | Row createTimeDateRow = summaryInformationTable.CreateRow(null); | 63 | } |
113 | createTimeDateRow[0] = 12; | 64 | else |
114 | createTimeDateRow[1] = now; | 65 | { |
115 | } | 66 | summaryInformationRow.Value = Common.GetValidCodePage(codepage, false, false, summaryInformationRow.SourceLineNumbers).ToString(CultureInfo.InvariantCulture); |
67 | } | ||
68 | break; | ||
69 | case 9: // PID_REVNUMBER | ||
70 | var packageCode = summaryInformationRow.Value; | ||
116 | 71 | ||
117 | // add a summary information row for the last save time/date property if its not already set | 72 | if (SectionType.Module == this.Section.Type) |
118 | if (!foundLastSaveDataTime) | 73 | { |
119 | { | 74 | this.ModularizationGuid = packageCode.Substring(1, 36).Replace('-', '_'); |
120 | Row lastSaveTimeDateRow = summaryInformationTable.CreateRow(null); | 75 | } |
121 | lastSaveTimeDateRow[0] = 13; | 76 | else if ("*" == packageCode) |
122 | lastSaveTimeDateRow[1] = now; | 77 | { |
78 | // set the revision number (package/patch code) if it should be automatically generated | ||
79 | summaryInformationRow.Value = Common.GenerateGuid(); | ||
80 | } | ||
81 | break; | ||
82 | case 12: // PID_CREATE_DTM | ||
83 | foundCreateDataTime = true; | ||
84 | break; | ||
85 | case 13: // PID_LASTSAVE_DTM | ||
86 | foundLastSaveDataTime = true; | ||
87 | break; | ||
88 | case 14: | ||
89 | this.InstallerVersion = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); | ||
90 | break; | ||
91 | case 15: // PID_WORDCOUNT | ||
92 | if (SectionType.Patch == this.Section.Type) | ||
93 | { | ||
94 | this.LongNames = true; | ||
95 | this.Compressed = true; | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | var attributes = summaryInformationRow[_SummaryInformationTupleFields.Value].AsNumber(); | ||
100 | this.LongNames = (0 == (attributes & 1)); | ||
101 | this.Compressed = (2 == (attributes & 2)); | ||
102 | } | ||
103 | break; | ||
104 | case 18: // PID_APPNAME | ||
105 | foundCreatingApplication = true; | ||
106 | break; | ||
123 | } | 107 | } |
108 | } | ||
124 | 109 | ||
125 | // add a summary information row for the creating application property if its not already set | 110 | // add a summary information row for the create time/date property if its not already set |
126 | if (!foundCreatingApplication) | 111 | if (!foundCreateDataTime) |
127 | { | 112 | { |
128 | Row creatingApplicationRow = summaryInformationTable.CreateRow(null); | 113 | var createTimeDateRow = new _SummaryInformationTuple(null, new Identifier(12, AccessModifier.Private)); |
129 | creatingApplicationRow[0] = 18; | 114 | createTimeDateRow.PropertyId = 12; |
130 | creatingApplicationRow[1] = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); | 115 | createTimeDateRow.Value = now; |
131 | } | 116 | |
117 | this.Section.Tuples.Add(createTimeDateRow); | ||
118 | } | ||
119 | |||
120 | // add a summary information row for the last save time/date property if its not already set | ||
121 | if (!foundLastSaveDataTime) | ||
122 | { | ||
123 | var lastSaveTimeDateRow = new _SummaryInformationTuple(null, new Identifier(13, AccessModifier.Private)); | ||
124 | lastSaveTimeDateRow.PropertyId = 13; | ||
125 | lastSaveTimeDateRow.Value = now; | ||
126 | |||
127 | this.Section.Tuples.Add(lastSaveTimeDateRow); | ||
128 | } | ||
129 | |||
130 | // add a summary information row for the creating application property if its not already set | ||
131 | if (!foundCreatingApplication) | ||
132 | { | ||
133 | var creatingApplicationRow = new _SummaryInformationTuple(null, new Identifier(18, AccessModifier.Private)); | ||
134 | creatingApplicationRow.PropertyId = 18; | ||
135 | creatingApplicationRow.Value = String.Format(CultureInfo.InvariantCulture, AppCommon.GetCreatingApplicationString()); | ||
136 | |||
137 | this.Section.Tuples.Add(creatingApplicationRow); | ||
132 | } | 138 | } |
133 | } | 139 | } |
134 | } | 140 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs index 425d1f9c..b4027834 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/BindTransformCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs index b2cc76fc..c25a497e 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetBuilder.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | 6 | using System.Collections; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs index dcafcd36..405b840b 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CabinetWorkItem.cs | |||
@@ -1,11 +1,10 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System.Collections.Generic; | 5 | using System.Collections.Generic; |
6 | using WixToolset.Core.Bind; | 6 | using WixToolset.Core.Bind; |
7 | using WixToolset.Data; | 7 | using WixToolset.Data; |
8 | using WixToolset.Data.Rows; | ||
9 | 8 | ||
10 | /// <summary> | 9 | /// <summary> |
11 | /// A cabinet builder work item. | 10 | /// A cabinet builder work item. |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs new file mode 100644 index 00000000..0c0aea1f --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CalculateComponentGuids.cs | |||
@@ -0,0 +1,174 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.IO; | ||
8 | using System.Linq; | ||
9 | using WixToolset.Bind; | ||
10 | using WixToolset.Core.Native; | ||
11 | using WixToolset.Data; | ||
12 | using WixToolset.Data.Tuples; | ||
13 | |||
14 | /// <summary> | ||
15 | /// Set the guids for components with generatable guids. | ||
16 | /// </summary> | ||
17 | internal class CalculateComponentGuids | ||
18 | { | ||
19 | public CalculateComponentGuids(IntermediateSection section) | ||
20 | { | ||
21 | this.Section = section; | ||
22 | } | ||
23 | |||
24 | private IntermediateSection Section { get; } | ||
25 | |||
26 | public void Execute() | ||
27 | { | ||
28 | Dictionary<string, RegistryTuple> registryKeyRows = null; | ||
29 | Dictionary<string, ResolvedDirectory> targetPathsByDirectoryId = null; | ||
30 | Dictionary<string, string> componentIdGenSeeds = null; | ||
31 | Dictionary<string, List<FileTuple>> filesByComponentId = null; | ||
32 | |||
33 | // Find components with generatable guids. | ||
34 | foreach (var componentRow in this.Section.Tuples.OfType<ComponentTuple>()) | ||
35 | { | ||
36 | // Skip components that do not specify generate guid. | ||
37 | if (componentRow.ComponentId != "*") | ||
38 | { | ||
39 | continue; | ||
40 | } | ||
41 | |||
42 | var odbcDataSourceKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesODBCDataSource) != 0; | ||
43 | |||
44 | if (String.IsNullOrEmpty(componentRow.KeyPath) || odbcDataSourceKeyPath) | ||
45 | { | ||
46 | Messaging.Instance.OnMessage(WixErrors.IllegalComponentWithAutoGeneratedGuid(componentRow.SourceLineNumbers)); | ||
47 | continue; | ||
48 | } | ||
49 | |||
50 | var registryKeyPath = (componentRow.Attributes & MsiInterop.MsidbComponentAttributesRegistryKeyPath) != 0; | ||
51 | |||
52 | if (registryKeyPath) | ||
53 | { | ||
54 | if (registryKeyRows is null) | ||
55 | { | ||
56 | registryKeyRows = this.Section.Tuples.OfType<RegistryTuple>().ToDictionary(t => t.Registry); | ||
57 | } | ||
58 | |||
59 | if (registryKeyRows.TryGetValue(componentRow.KeyPath, out var foundRow)) | ||
60 | { | ||
61 | var is64Bit = (componentRow.Attributes & MsiInterop.MsidbComponentAttributes64bit) != 0; | ||
62 | var bitness = is64Bit ? "64" : String.Empty; | ||
63 | var regkey = String.Concat(bitness, foundRow[1], "\\", foundRow[2], "\\", foundRow[3]); | ||
64 | componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, regkey.ToLowerInvariant()).ToString("B").ToUpperInvariant(); | ||
65 | } | ||
66 | } | ||
67 | else // must be a File KeyPath. | ||
68 | { | ||
69 | // If the directory table hasn't been loaded into an indexed hash | ||
70 | // of directory ids to target names do that now. | ||
71 | if (targetPathsByDirectoryId is null) | ||
72 | { | ||
73 | var directories = this.Section.Tuples.OfType<DirectoryTuple>().ToList(); | ||
74 | |||
75 | targetPathsByDirectoryId = new Dictionary<string, ResolvedDirectory>(directories.Count); | ||
76 | |||
77 | // Get the target paths for all directories. | ||
78 | foreach (var row in directories) | ||
79 | { | ||
80 | // If the directory Id already exists, we will skip it here since | ||
81 | // checking for duplicate primary keys is done later when importing tables | ||
82 | // into database | ||
83 | if (targetPathsByDirectoryId.ContainsKey(row.Directory)) | ||
84 | { | ||
85 | continue; | ||
86 | } | ||
87 | |||
88 | var targetName = Common.GetName(row.DefaultDir, false, true); | ||
89 | targetPathsByDirectoryId.Add(row.Directory, new ResolvedDirectory(row.Directory_Parent, targetName)); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | // If the component id generation seeds have not been indexed | ||
94 | // from the WixDirectory table do that now. | ||
95 | if (componentIdGenSeeds is null) | ||
96 | { | ||
97 | // If there are any WixDirectory rows, build up the Component Guid | ||
98 | // generation seeds indexed by Directory/@Id. | ||
99 | componentIdGenSeeds = this.Section.Tuples.OfType<WixDirectoryTuple>() | ||
100 | .Where(t => !String.IsNullOrEmpty(t.ComponentGuidGenerationSeed)) | ||
101 | .ToDictionary(t => t.Directory_, t => t.ComponentGuidGenerationSeed); | ||
102 | } | ||
103 | |||
104 | // if the file rows have not been indexed by File.Component yet | ||
105 | // then do that now | ||
106 | if (filesByComponentId is null) | ||
107 | { | ||
108 | var files = this.Section.Tuples.OfType<FileTuple>().ToList(); | ||
109 | |||
110 | filesByComponentId = new Dictionary<string, List<FileTuple>>(files.Count); | ||
111 | |||
112 | foreach (var file in files) | ||
113 | { | ||
114 | if (!filesByComponentId.TryGetValue(file.Component_, out var componentFiles)) | ||
115 | { | ||
116 | componentFiles = new List<FileTuple>(); | ||
117 | filesByComponentId.Add(file.Component_, componentFiles); | ||
118 | } | ||
119 | |||
120 | componentFiles.Add(file); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | // validate component meets all the conditions to have a generated guid | ||
125 | var currentComponentFiles = filesByComponentId[componentRow.Component]; | ||
126 | var numFilesInComponent = currentComponentFiles.Count; | ||
127 | string path = null; | ||
128 | |||
129 | foreach (var fileRow in currentComponentFiles) | ||
130 | { | ||
131 | if (fileRow.File == componentRow.KeyPath) | ||
132 | { | ||
133 | // calculate the key file's canonical target path | ||
134 | string directoryPath = Binder.GetDirectoryPath(targetPathsByDirectoryId, componentIdGenSeeds, componentRow.Directory_, true); | ||
135 | string fileName = Common.GetName(fileRow.LongFileName, false, true).ToLowerInvariant(); | ||
136 | path = Path.Combine(directoryPath, fileName); | ||
137 | |||
138 | // find paths that are not canonicalized | ||
139 | if (path.StartsWith(@"PersonalFolder\my pictures", StringComparison.Ordinal) || | ||
140 | path.StartsWith(@"ProgramFilesFolder\common files", StringComparison.Ordinal) || | ||
141 | path.StartsWith(@"ProgramMenuFolder\startup", StringComparison.Ordinal) || | ||
142 | path.StartsWith("TARGETDIR", StringComparison.Ordinal) || | ||
143 | path.StartsWith(@"StartMenuFolder\programs", StringComparison.Ordinal) || | ||
144 | path.StartsWith(@"WindowsFolder\fonts", StringComparison.Ordinal)) | ||
145 | { | ||
146 | Messaging.Instance.OnMessage(WixErrors.IllegalPathForGeneratedComponentGuid(componentRow.SourceLineNumbers, fileRow.Component_, path)); | ||
147 | } | ||
148 | |||
149 | // if component has more than one file, the key path must be versioned | ||
150 | if (1 < numFilesInComponent && String.IsNullOrEmpty(fileRow.Version)) | ||
151 | { | ||
152 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentUnversionedKeypath(componentRow.SourceLineNumbers)); | ||
153 | } | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | // not a key path, so it must be an unversioned file if component has more than one file | ||
158 | if (1 < numFilesInComponent && !String.IsNullOrEmpty(fileRow.Version)) | ||
159 | { | ||
160 | Messaging.Instance.OnMessage(WixErrors.IllegalGeneratedGuidComponentVersionedNonkeypath(componentRow.SourceLineNumbers)); | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | |||
165 | // if the rules were followed, reward with a generated guid | ||
166 | if (!Messaging.Instance.EncounteredError) | ||
167 | { | ||
168 | componentRow.ComponentId = Uuid.NewUuid(BindDatabaseCommand.WixComponentGuidNamespace, path).ToString("B").ToUpperInvariant(); | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs index d4d3799f..9a8e2bba 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ConfigurationCallback.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | 6 | using System.Collections; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs index 6388a352..0dcddb99 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CopyTransformDataCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
@@ -10,6 +10,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
10 | using WixToolset.Extensibility; | 10 | using WixToolset.Extensibility; |
11 | using WixToolset.Core.Native; | 11 | using WixToolset.Core.Native; |
12 | using WixToolset.Core.Bind; | 12 | using WixToolset.Core.Bind; |
13 | using WixToolset.Data.Tuples; | ||
13 | 14 | ||
14 | internal class CopyTransformDataCommand | 15 | internal class CopyTransformDataCommand |
15 | { | 16 | { |
@@ -29,7 +30,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
29 | 30 | ||
30 | List<FileFacade> allFileRows = this.CopyOutFileRows ? new List<FileFacade>() : null; | 31 | List<FileFacade> allFileRows = this.CopyOutFileRows ? new List<FileFacade>() : null; |
31 | 32 | ||
32 | #if false // TODO: Fix this patching related code to work correctly with FileFacades. | 33 | #if REVISIT_FOR_PATCHING // TODO: Fix this patching related code to work correctly with FileFacades. |
33 | bool copyToPatch = (allFileRows != null); | 34 | bool copyToPatch = (allFileRows != null); |
34 | bool copyFromPatch = !copyToPatch; | 35 | bool copyFromPatch = !copyToPatch; |
35 | 36 | ||
@@ -454,7 +455,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
454 | } | 455 | } |
455 | 456 | ||
456 | Row patchAction = iesTable.CreateRow(null); | 457 | Row patchAction = iesTable.CreateRow(null); |
457 | WixActionRow wixPatchAction = WindowsInstallerStandard.GetStandardActions()[table, "PatchFiles"]; | 458 | WixActionRow wixPatchAction = WindowsInstallerStandardInternal.GetStandardActionRows()[table, "PatchFiles"]; |
458 | int sequence = wixPatchAction.Sequence; | 459 | int sequence = wixPatchAction.Sequence; |
459 | // Test for default sequence value's appropriateness | 460 | // Test for default sequence value's appropriateness |
460 | if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence)) | 461 | if (seqInstallFiles >= sequence || (0 != seqDuplicateFiles && seqDuplicateFiles <= sequence)) |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs index 02015744..b5a436c5 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateCabinetsCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
@@ -10,10 +10,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
10 | using System.Runtime.InteropServices; | 10 | using System.Runtime.InteropServices; |
11 | using System.Threading; | 11 | using System.Threading; |
12 | using WixToolset.Core.Bind; | 12 | using WixToolset.Core.Bind; |
13 | using WixToolset.Core.WindowsInstaller.Bind; | ||
14 | using WixToolset.Data; | 13 | using WixToolset.Data; |
15 | using WixToolset.Data.Bind; | 14 | using WixToolset.Data.Bind; |
16 | using WixToolset.Data.Rows; | 15 | using WixToolset.Data.Rows; |
16 | using WixToolset.Data.Tuples; | ||
17 | using WixToolset.Extensibility; | 17 | using WixToolset.Extensibility; |
18 | 18 | ||
19 | /// <summary> | 19 | /// <summary> |
@@ -60,9 +60,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
60 | 60 | ||
61 | public bool Compressed { private get; set; } | 61 | public bool Compressed { private get; set; } |
62 | 62 | ||
63 | public Dictionary<MediaRow, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; } | 63 | public Dictionary<MediaTuple, IEnumerable<FileFacade>> FileRowsByCabinet { private get; set; } |
64 | 64 | ||
65 | public Func<MediaRow, string, string, string> ResolveMedia { private get; set; } | 65 | public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; } |
66 | 66 | ||
67 | public TableDefinitionCollection TableDefinitions { private get; set; } | 67 | public TableDefinitionCollection TableDefinitions { private get; set; } |
68 | 68 | ||
@@ -77,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
77 | /// <returns>The uncompressed file rows.</returns> | 77 | /// <returns>The uncompressed file rows.</returns> |
78 | public void Execute() | 78 | public void Execute() |
79 | { | 79 | { |
80 | RowDictionary<WixMediaRow> wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable); | 80 | var wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable); |
81 | 81 | ||
82 | this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); | 82 | this.lastCabinetAddedToMediaTable = new Dictionary<string, string>(); |
83 | 83 | ||
@@ -87,22 +87,19 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
87 | CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); | 87 | CabinetBuilder cabinetBuilder = new CabinetBuilder(this.CabbingThreadCount, Marshal.GetFunctionPointerForDelegate(this.newCabNamesCallBack)); |
88 | 88 | ||
89 | // Supply Compile MediaTemplate Attributes to Cabinet Builder | 89 | // Supply Compile MediaTemplate Attributes to Cabinet Builder |
90 | int MaximumCabinetSizeForLargeFileSplitting; | 90 | this.GetMediaTemplateAttributes(out var MaximumCabinetSizeForLargeFileSplitting, out var MaximumUncompressedMediaSize); |
91 | int MaximumUncompressedMediaSize; | ||
92 | this.GetMediaTemplateAttributes(out MaximumCabinetSizeForLargeFileSplitting, out MaximumUncompressedMediaSize); | ||
93 | cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting; | 91 | cabinetBuilder.MaximumCabinetSizeForLargeFileSplitting = MaximumCabinetSizeForLargeFileSplitting; |
94 | cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize; | 92 | cabinetBuilder.MaximumUncompressedMediaSize = MaximumUncompressedMediaSize; |
95 | 93 | ||
96 | foreach (var entry in this.FileRowsByCabinet) | 94 | foreach (var entry in this.FileRowsByCabinet) |
97 | { | 95 | { |
98 | MediaRow mediaRow = entry.Key; | 96 | var mediaRow = entry.Key; |
99 | IEnumerable<FileFacade> files = entry.Value; | 97 | IEnumerable<FileFacade> files = entry.Value; |
100 | CompressionLevel compressionLevel = this.DefaultCompressionLevel; | 98 | CompressionLevel compressionLevel = this.DefaultCompressionLevel; |
101 | 99 | ||
102 | WixMediaRow wixMediaRow = null; | ||
103 | string mediaLayoutFolder = null; | 100 | string mediaLayoutFolder = null; |
104 | 101 | ||
105 | if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) | 102 | if (wixMediaRows.TryGetValue(mediaRow.Id.Id, out var wixMediaRow)) |
106 | { | 103 | { |
107 | mediaLayoutFolder = wixMediaRow.Layout; | 104 | mediaLayoutFolder = wixMediaRow.Layout; |
108 | 105 | ||
@@ -185,7 +182,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
185 | /// <param name="fileFacades">Collection of files in this cabinet.</param> | 182 | /// <param name="fileFacades">Collection of files in this cabinet.</param> |
186 | /// <param name="fileTransfers">Array of files to be transfered.</param> | 183 | /// <param name="fileTransfers">Array of files to be transfered.</param> |
187 | /// <returns>created CabinetWorkItem object</returns> | 184 | /// <returns>created CabinetWorkItem object</returns> |
188 | private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaRow mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<FileTransfer> fileTransfers) | 185 | private CabinetWorkItem CreateCabinetWorkItem(Output output, string cabinetDir, MediaTuple mediaRow, CompressionLevel compressionLevel, IEnumerable<FileFacade> fileFacades, List<FileTransfer> fileTransfers) |
189 | { | 186 | { |
190 | CabinetWorkItem cabinetWorkItem = null; | 187 | CabinetWorkItem cabinetWorkItem = null; |
191 | string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); | 188 | string tempCabinetFileX = Path.Combine(this.TempFilesLocation, mediaRow.Cabinet); |
@@ -254,8 +251,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
254 | else | 251 | else |
255 | { | 252 | { |
256 | string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); | 253 | string destinationPath = Path.Combine(cabinetDir, mediaRow.Cabinet); |
257 | FileTransfer transfer; | 254 | if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out var transfer)) |
258 | if (FileTransfer.TryCreate(resolvedCabinet.Path, destinationPath, CabinetBuildOption.BuildAndMove == resolvedCabinet.BuildOption, "Cabinet", mediaRow.SourceLineNumbers, out transfer)) | ||
259 | { | 255 | { |
260 | transfer.Built = true; | 256 | transfer.Built = true; |
261 | fileTransfers.Add(transfer); | 257 | fileTransfers.Add(transfer); |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs index 42a69310..7c7b07cc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateDeltaPatchesCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
@@ -9,49 +9,40 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
9 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
10 | using WixToolset.Data; | 10 | using WixToolset.Data; |
11 | using WixToolset.Data.Rows; | 11 | using WixToolset.Data.Rows; |
12 | using WixToolset.Data.Tuples; | ||
12 | 13 | ||
13 | /// <summary> | 14 | /// <summary> |
14 | /// Creates delta patches and updates the appropriate rows to point to the newly generated patches. | 15 | /// Creates delta patches and updates the appropriate rows to point to the newly generated patches. |
15 | /// </summary> | 16 | /// </summary> |
16 | internal class CreateDeltaPatchesCommand | 17 | internal class CreateDeltaPatchesCommand |
17 | { | 18 | { |
18 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 19 | public CreateDeltaPatchesCommand(List<FileFacade> fileFacades, string intermediateFolder, WixPatchIdTuple wixPatchId) |
20 | { | ||
21 | this.FileFacades = fileFacades; | ||
22 | this.IntermediateFolder = intermediateFolder; | ||
23 | this.WixPatchId = wixPatchId; | ||
24 | } | ||
19 | 25 | ||
20 | public Table WixPatchIdTable { private get; set; } | 26 | private IEnumerable<FileFacade> FileFacades { get; } |
21 | 27 | ||
22 | public string TempFilesLocation { private get; set; } | 28 | private WixPatchIdTuple WixPatchId { get; } |
29 | |||
30 | private string IntermediateFolder { get; } | ||
23 | 31 | ||
24 | public void Execute() | 32 | public void Execute() |
25 | { | 33 | { |
26 | #if REVISIT_FOR_PATCHING | 34 | var optimizePatchSizeForLargeFiles = this.WixPatchId?.OptimizePatchSizeForLargeFiles ?? false; |
27 | bool optimizePatchSizeForLargeFiles = false; | 35 | var apiPatchingSymbolFlags = (PatchSymbolFlagsType)(this.WixPatchId?.ApiPatchingSymbolFlags ?? 0); |
28 | PatchSymbolFlagsType apiPatchingSymbolFlags = 0; | ||
29 | |||
30 | if (null != this.WixPatchIdTable) | ||
31 | { | ||
32 | Row row = this.WixPatchIdTable.Rows[0]; | ||
33 | if (null != row) | ||
34 | { | ||
35 | if (null != row[2]) | ||
36 | { | ||
37 | optimizePatchSizeForLargeFiles = (1 == Convert.ToUInt32(row[2], CultureInfo.InvariantCulture)); | ||
38 | } | ||
39 | |||
40 | if (null != row[3]) | ||
41 | { | ||
42 | apiPatchingSymbolFlags = (PatchSymbolFlagsType)Convert.ToUInt32(row[3], CultureInfo.InvariantCulture); | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | 36 | ||
37 | #if REVISIT_FOR_PATCHING | ||
47 | foreach (FileFacade facade in this.FileFacades) | 38 | foreach (FileFacade facade in this.FileFacades) |
48 | { | 39 | { |
49 | if (RowOperation.Modify == facade.File.Operation && | 40 | if (RowOperation.Modify == facade.File.Operation && |
50 | 0 != (facade.WixFile.PatchAttributes & PatchAttributeType.IncludeWholeFile)) | 41 | 0 != (facade.WixFile.PatchAttributes & PatchAttributeType.IncludeWholeFile)) |
51 | { | 42 | { |
52 | string deltaBase = String.Concat("delta_", facade.File.File); | 43 | string deltaBase = String.Concat("delta_", facade.File.File); |
53 | string deltaFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".dpf")); | 44 | string deltaFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".dpf")); |
54 | string headerFile = Path.Combine(this.TempFilesLocation, String.Concat(deltaBase, ".phd")); | 45 | string headerFile = Path.Combine(this.IntermediateFolder, String.Concat(deltaBase, ".phd")); |
55 | 46 | ||
56 | bool retainRangeWarning = false; | 47 | bool retainRangeWarning = false; |
57 | 48 | ||
@@ -84,6 +75,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
84 | } | 75 | } |
85 | } | 76 | } |
86 | #endif | 77 | #endif |
78 | |||
87 | throw new NotImplementedException(); | 79 | throw new NotImplementedException(); |
88 | } | 80 | } |
89 | } | 81 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs new file mode 100644 index 00000000..85b3b25a --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs | |||
@@ -0,0 +1,230 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Linq; | ||
7 | using WixToolset.Core.Native; | ||
8 | using WixToolset.Data; | ||
9 | using WixToolset.Data.Rows; | ||
10 | using WixToolset.Data.Tuples; | ||
11 | |||
12 | internal class CreateOutputFromIRCommand | ||
13 | { | ||
14 | public CreateOutputFromIRCommand(IntermediateSection section, TableDefinitionCollection tableDefinitions) | ||
15 | { | ||
16 | this.Section = section; | ||
17 | this.TableDefinitions = tableDefinitions; | ||
18 | } | ||
19 | |||
20 | private TableDefinitionCollection TableDefinitions { get; } | ||
21 | |||
22 | private IntermediateSection Section { get; } | ||
23 | |||
24 | public Output Output { get; private set; } | ||
25 | |||
26 | public void Execute() | ||
27 | { | ||
28 | var output = new Output(this.Section.Tuples.First().SourceLineNumbers); | ||
29 | output.Codepage = this.Section.Codepage; | ||
30 | output.Type = SectionTypeToOutputType(this.Section.Type); | ||
31 | |||
32 | this.AddSectionToOutput(this.Section, output); | ||
33 | |||
34 | this.Output = output; | ||
35 | } | ||
36 | |||
37 | private void AddSectionToOutput(IntermediateSection section, Output output) | ||
38 | { | ||
39 | foreach (var tuple in section.Tuples) | ||
40 | { | ||
41 | switch (tuple.Definition.Type) | ||
42 | { | ||
43 | case TupleDefinitionType.File: | ||
44 | this.AddFileTuple((FileTuple)tuple, output); | ||
45 | break; | ||
46 | |||
47 | case TupleDefinitionType.WixAction: | ||
48 | this.AddWixActionTuple((WixActionTuple)tuple, output); | ||
49 | break; | ||
50 | |||
51 | default: | ||
52 | this.AddTupleDefaultly(tuple, output); | ||
53 | break; | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | |||
58 | private void AddFileTuple(FileTuple tuple, Output output) | ||
59 | { | ||
60 | var table = output.EnsureTable(this.TableDefinitions["File"]); | ||
61 | var row = (FileRow)table.CreateRow(tuple.SourceLineNumbers); | ||
62 | row.File = tuple.File; | ||
63 | row.Component = tuple.Component_; | ||
64 | row.FileName = GetMsiFilenameValue(tuple.ShortFileName, tuple.LongFileName); | ||
65 | row.FileSize = tuple.FileSize; | ||
66 | row.Version = tuple.Version; | ||
67 | row.Language = tuple.Language; | ||
68 | |||
69 | var attributes = tuple.Checksum ? MsiInterop.MsidbFileAttributesChecksum : 0; | ||
70 | attributes |= (tuple.Compressed.HasValue && tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesCompressed : 0; | ||
71 | attributes |= (tuple.Compressed.HasValue && !tuple.Compressed.Value) ? MsiInterop.MsidbFileAttributesNoncompressed : 0; | ||
72 | attributes |= tuple.Hidden ? MsiInterop.MsidbFileAttributesHidden : 0; | ||
73 | attributes |= tuple.ReadOnly ? MsiInterop.MsidbFileAttributesReadOnly : 0; | ||
74 | attributes |= tuple.System ? MsiInterop.MsidbFileAttributesSystem : 0; | ||
75 | attributes |= tuple.Vital ? MsiInterop.MsidbFileAttributesVital : 0; | ||
76 | row.Attributes = attributes; | ||
77 | } | ||
78 | |||
79 | private void AddWixActionTuple(WixActionTuple actionRow, Output output) | ||
80 | { | ||
81 | // Get the table definition for the action (and ensure the proper table exists for a module). | ||
82 | TableDefinition sequenceTableDefinition = null; | ||
83 | switch (actionRow.SequenceTable) | ||
84 | { | ||
85 | case SequenceTable.AdminExecuteSequence: | ||
86 | if (OutputType.Module == output.Type) | ||
87 | { | ||
88 | output.EnsureTable(this.TableDefinitions["AdminExecuteSequence"]); | ||
89 | sequenceTableDefinition = this.TableDefinitions["ModuleAdminExecuteSequence"]; | ||
90 | } | ||
91 | else | ||
92 | { | ||
93 | sequenceTableDefinition = this.TableDefinitions["AdminExecuteSequence"]; | ||
94 | } | ||
95 | break; | ||
96 | case SequenceTable.AdminUISequence: | ||
97 | if (OutputType.Module == output.Type) | ||
98 | { | ||
99 | output.EnsureTable(this.TableDefinitions["AdminUISequence"]); | ||
100 | sequenceTableDefinition = this.TableDefinitions["ModuleAdminUISequence"]; | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | sequenceTableDefinition = this.TableDefinitions["AdminUISequence"]; | ||
105 | } | ||
106 | break; | ||
107 | case SequenceTable.AdvtExecuteSequence: | ||
108 | if (OutputType.Module == output.Type) | ||
109 | { | ||
110 | output.EnsureTable(this.TableDefinitions["AdvtExecuteSequence"]); | ||
111 | sequenceTableDefinition = this.TableDefinitions["ModuleAdvtExecuteSequence"]; | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | sequenceTableDefinition = this.TableDefinitions["AdvtExecuteSequence"]; | ||
116 | } | ||
117 | break; | ||
118 | case SequenceTable.InstallExecuteSequence: | ||
119 | if (OutputType.Module == output.Type) | ||
120 | { | ||
121 | output.EnsureTable(this.TableDefinitions["InstallExecuteSequence"]); | ||
122 | sequenceTableDefinition = this.TableDefinitions["ModuleInstallExecuteSequence"]; | ||
123 | } | ||
124 | else | ||
125 | { | ||
126 | sequenceTableDefinition = this.TableDefinitions["InstallExecuteSequence"]; | ||
127 | } | ||
128 | break; | ||
129 | case SequenceTable.InstallUISequence: | ||
130 | if (OutputType.Module == output.Type) | ||
131 | { | ||
132 | output.EnsureTable(this.TableDefinitions["InstallUISequence"]); | ||
133 | sequenceTableDefinition = this.TableDefinitions["ModuleInstallUISequence"]; | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | sequenceTableDefinition = this.TableDefinitions["InstallUISequence"]; | ||
138 | } | ||
139 | break; | ||
140 | } | ||
141 | |||
142 | // create the action sequence row in the output | ||
143 | var sequenceTable = output.EnsureTable(sequenceTableDefinition); | ||
144 | var row = sequenceTable.CreateRow(actionRow.SourceLineNumbers); | ||
145 | |||
146 | if (SectionType.Module == this.Section.Type) | ||
147 | { | ||
148 | row[0] = actionRow.Action; | ||
149 | if (0 != actionRow.Sequence) | ||
150 | { | ||
151 | row[1] = actionRow.Sequence; | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | bool after = (null == actionRow.Before); | ||
156 | row[2] = after ? actionRow.After : actionRow.Before; | ||
157 | row[3] = after ? 1 : 0; | ||
158 | } | ||
159 | row[4] = actionRow.Condition; | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | row[0] = actionRow.Action; | ||
164 | row[1] = actionRow.Condition; | ||
165 | row[2] = actionRow.Sequence; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | private void AddTupleDefaultly(IntermediateTuple tuple, Output output) | ||
170 | { | ||
171 | if (!this.TableDefinitions.TryGet(tuple.Definition.Name, out var tableDefinition)) | ||
172 | { | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | var table = output.EnsureTable(tableDefinition); | ||
177 | var row = table.CreateRow(tuple.SourceLineNumbers); | ||
178 | for (var i = 0; i < tuple.Fields.Length; ++i) | ||
179 | { | ||
180 | if (i < tableDefinition.Columns.Count) | ||
181 | { | ||
182 | var column = tableDefinition.Columns[i]; | ||
183 | |||
184 | switch (column.Type) | ||
185 | { | ||
186 | case ColumnType.Number: | ||
187 | row[i] = tuple.AsNumber(i); | ||
188 | break; | ||
189 | |||
190 | default: | ||
191 | row[i] = tuple.AsString(i); | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | } | ||
197 | |||
198 | private static OutputType SectionTypeToOutputType(SectionType type) | ||
199 | { | ||
200 | switch (type) | ||
201 | { | ||
202 | case SectionType.Bundle: | ||
203 | return OutputType.Bundle; | ||
204 | case SectionType.Module: | ||
205 | return OutputType.Module; | ||
206 | case SectionType.Product: | ||
207 | return OutputType.Product; | ||
208 | case SectionType.PatchCreation: | ||
209 | return OutputType.PatchCreation; | ||
210 | case SectionType.Patch: | ||
211 | return OutputType.Patch; | ||
212 | |||
213 | default: | ||
214 | throw new ArgumentOutOfRangeException(nameof(type)); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | private static string GetMsiFilenameValue(string shortName, string longName) | ||
219 | { | ||
220 | if (String.IsNullOrEmpty(shortName)) | ||
221 | { | ||
222 | return longName; | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | return shortName + "|" + longName; | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs index aef130b0..ab2e8201 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateSpecialPropertiesCommand.cs | |||
@@ -1,67 +1,72 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.Linq; | ||
7 | using WixToolset.Data; | 8 | using WixToolset.Data; |
8 | using WixToolset.Data.Rows; | 9 | using WixToolset.Data.Tuples; |
9 | 10 | ||
10 | internal class CreateSpecialPropertiesCommand | 11 | internal class CreateSpecialPropertiesCommand |
11 | { | 12 | { |
12 | public Table PropertyTable { private get; set; } | 13 | public CreateSpecialPropertiesCommand(IntermediateSection section) |
14 | { | ||
15 | this.Section = section; | ||
16 | } | ||
13 | 17 | ||
14 | public Table WixPropertyTable { private get; set; } | 18 | private IntermediateSection Section { get; } |
15 | 19 | ||
16 | public void Execute() | 20 | public void Execute() |
17 | { | 21 | { |
18 | // Create the special properties. | 22 | // Create lists of the properties that contribute to the special lists of properties. |
19 | if (null != this.WixPropertyTable) | 23 | SortedSet<string> adminProperties = new SortedSet<string>(); |
20 | { | 24 | SortedSet<string> secureProperties = new SortedSet<string>(); |
21 | // Create lists of the properties that contribute to the special lists of properties. | 25 | SortedSet<string> hiddenProperties = new SortedSet<string>(); |
22 | SortedSet<string> adminProperties = new SortedSet<string>(); | ||
23 | SortedSet<string> secureProperties = new SortedSet<string>(); | ||
24 | SortedSet<string> hiddenProperties = new SortedSet<string>(); | ||
25 | 26 | ||
26 | foreach (WixPropertyRow wixPropertyRow in this.WixPropertyTable.Rows) | 27 | foreach (var wixPropertyRow in this.Section.Tuples.OfType<WixPropertyTuple>()) |
28 | { | ||
29 | if (wixPropertyRow.Admin) | ||
27 | { | 30 | { |
28 | if (wixPropertyRow.Admin) | 31 | adminProperties.Add(wixPropertyRow.Property_); |
29 | { | ||
30 | adminProperties.Add(wixPropertyRow.Id); | ||
31 | } | ||
32 | |||
33 | if (wixPropertyRow.Hidden) | ||
34 | { | ||
35 | hiddenProperties.Add(wixPropertyRow.Id); | ||
36 | } | ||
37 | |||
38 | if (wixPropertyRow.Secure) | ||
39 | { | ||
40 | secureProperties.Add(wixPropertyRow.Id); | ||
41 | } | ||
42 | } | 32 | } |
43 | 33 | ||
44 | Table propertyTable = this.PropertyTable; | 34 | if (wixPropertyRow.Hidden) |
45 | if (0 < adminProperties.Count) | ||
46 | { | 35 | { |
47 | PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); | 36 | hiddenProperties.Add(wixPropertyRow.Property_); |
48 | row.Property = "AdminProperties"; | ||
49 | row.Value = String.Join(";", adminProperties); | ||
50 | } | 37 | } |
51 | 38 | ||
52 | if (0 < secureProperties.Count) | 39 | if (wixPropertyRow.Secure) |
53 | { | 40 | { |
54 | PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); | 41 | secureProperties.Add(wixPropertyRow.Property_); |
55 | row.Property = "SecureCustomProperties"; | ||
56 | row.Value = String.Join(";", secureProperties); | ||
57 | } | 42 | } |
43 | } | ||
58 | 44 | ||
59 | if (0 < hiddenProperties.Count) | 45 | if (0 < adminProperties.Count) |
60 | { | 46 | { |
61 | PropertyRow row = (PropertyRow)propertyTable.CreateRow(null); | 47 | var tuple = new PropertyTuple(null, new Identifier("AdminProperties", AccessModifier.Private)); |
62 | row.Property = "MsiHiddenProperties"; | 48 | tuple.Property = "AdminProperties"; |
63 | row.Value = String.Join(";", hiddenProperties); | 49 | tuple.Value = String.Join(";", adminProperties); |
64 | } | 50 | |
51 | this.Section.Tuples.Add(tuple); | ||
52 | } | ||
53 | |||
54 | if (0 < secureProperties.Count) | ||
55 | { | ||
56 | var tuple = new PropertyTuple(null, new Identifier("SecureCustomProperties", AccessModifier.Private)); | ||
57 | tuple.Property = "SecureCustomProperties"; | ||
58 | tuple.Value = String.Join(";", secureProperties); | ||
59 | |||
60 | this.Section.Tuples.Add(tuple); | ||
61 | } | ||
62 | |||
63 | if (0 < hiddenProperties.Count) | ||
64 | { | ||
65 | var tuple = new PropertyTuple(null, new Identifier("MsiHiddenProperties", AccessModifier.Private)); | ||
66 | tuple.Property = "MsiHiddenProperties"; | ||
67 | tuple.Value = String.Join(";", hiddenProperties); | ||
68 | |||
69 | this.Section.Tuples.Add(tuple); | ||
65 | } | 70 | } |
66 | } | 71 | } |
67 | } | 72 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs index 0d3e7bd1..32d1cfda 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ExtractMergeModuleFilesCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
@@ -10,7 +10,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
10 | using System.Linq; | 10 | using System.Linq; |
11 | using System.Runtime.InteropServices; | 11 | using System.Runtime.InteropServices; |
12 | using WixToolset.Data; | 12 | using WixToolset.Data; |
13 | using WixToolset.Data.Rows; | ||
14 | using WixToolset.MergeMod; | 13 | using WixToolset.MergeMod; |
15 | using WixToolset.Msi; | 14 | using WixToolset.Msi; |
16 | using WixToolset.Core.Native; | 15 | using WixToolset.Core.Native; |
@@ -23,13 +22,17 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
23 | /// </summary> | 22 | /// </summary> |
24 | internal class ExtractMergeModuleFilesCommand | 23 | internal class ExtractMergeModuleFilesCommand |
25 | { | 24 | { |
26 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 25 | public ExtractMergeModuleFilesCommand(IntermediateSection section, List<WixMergeTuple> wixMergeTuples) |
26 | { | ||
27 | this.Section = section; | ||
28 | this.WixMergeTuples = wixMergeTuples; | ||
29 | } | ||
27 | 30 | ||
28 | public Table FileTable { private get; set; } | 31 | private IntermediateSection Section { get; } |
29 | 32 | ||
30 | public Table WixFileTable { private get; set; } | 33 | private List<WixMergeTuple> WixMergeTuples { get; } |
31 | 34 | ||
32 | public Table WixMergeTable { private get; set; } | 35 | public IEnumerable<FileFacade> FileFacades { private get; set; } |
33 | 36 | ||
34 | public int OutputInstallerVersion { private get; set; } | 37 | public int OutputInstallerVersion { private get; set; } |
35 | 38 | ||
@@ -41,7 +44,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
41 | 44 | ||
42 | public void Execute() | 45 | public void Execute() |
43 | { | 46 | { |
44 | List<FileFacade> mergeModulesFileFacades = new List<FileFacade>(); | 47 | var mergeModulesFileFacades = new List<FileFacade>(); |
45 | 48 | ||
46 | IMsmMerge2 merge = MsmInterop.GetMsmMerge(); | 49 | IMsmMerge2 merge = MsmInterop.GetMsmMerge(); |
47 | 50 | ||
@@ -52,9 +55,9 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
52 | // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let | 55 | // Now since Merge Modules are already slow and generally less desirable than .wixlibs we'll let |
53 | // this case be slightly more expensive because the cost of maintaining an indexed file row collection | 56 | // this case be slightly more expensive because the cost of maintaining an indexed file row collection |
54 | // is a lot more costly for the common cases. | 57 | // is a lot more costly for the common cases. |
55 | Dictionary<string, FileFacade> indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); | 58 | var indexedFileFacades = this.FileFacades.ToDictionary(f => f.File.File, StringComparer.Ordinal); |
56 | 59 | ||
57 | foreach (WixMergeRow wixMergeRow in this.WixMergeTable.Rows) | 60 | foreach (var wixMergeRow in this.WixMergeTuples) |
58 | { | 61 | { |
59 | bool containsFiles = this.CreateFacadesForMergeModuleFiles(wixMergeRow, mergeModulesFileFacades, indexedFileFacades); | 62 | bool containsFiles = this.CreateFacadesForMergeModuleFiles(wixMergeRow, mergeModulesFileFacades, indexedFileFacades); |
60 | 63 | ||
@@ -68,7 +71,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
68 | this.MergeModulesFileFacades = mergeModulesFileFacades; | 71 | this.MergeModulesFileFacades = mergeModulesFileFacades; |
69 | } | 72 | } |
70 | 73 | ||
71 | private bool CreateFacadesForMergeModuleFiles(WixMergeRow wixMergeRow, List<FileFacade> mergeModulesFileFacades, Dictionary<string, FileFacade> indexedFileFacades) | 74 | private bool CreateFacadesForMergeModuleFiles(WixMergeTuple wixMergeRow, List<FileFacade> mergeModulesFileFacades, Dictionary<string, FileFacade> indexedFileFacades) |
72 | { | 75 | { |
73 | bool containsFiles = false; | 76 | bool containsFiles = false; |
74 | 77 | ||
@@ -98,7 +101,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
98 | // rows are created by merging in the actual modules. | 101 | // rows are created by merging in the actual modules. |
99 | var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private)); | 102 | var fileRow = new FileTuple(wixMergeRow.SourceLineNumbers, new Identifier(record[1], AccessModifier.Private)); |
100 | fileRow.File = record[1]; | 103 | fileRow.File = record[1]; |
101 | fileRow.Compressed = (wixMergeRow.FileCompression == YesNoType.Yes) ? true : (wixMergeRow.FileCompression == YesNoType.No) ? (bool?)false : null; | 104 | fileRow.Compressed = wixMergeRow.FileCompression; |
102 | //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); | 105 | //FileRow fileRow = (FileRow)this.FileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); |
103 | //fileRow.File = record[1]; | 106 | //fileRow.File = record[1]; |
104 | //fileRow.Compressed = wixMergeRow.FileCompression; | 107 | //fileRow.Compressed = wixMergeRow.FileCompression; |
@@ -107,7 +110,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
107 | wixFileRow.Directory_ = record[2]; | 110 | wixFileRow.Directory_ = record[2]; |
108 | wixFileRow.DiskId = wixMergeRow.DiskId; | 111 | wixFileRow.DiskId = wixMergeRow.DiskId; |
109 | wixFileRow.PatchGroup = -1; | 112 | wixFileRow.PatchGroup = -1; |
110 | wixFileRow.Source = Path.Combine(this.IntermediateFolder, "MergeId.", wixMergeRow.Number.ToString(CultureInfo.InvariantCulture), record[1]); | 113 | wixFileRow.Source = Path.Combine(this.IntermediateFolder, wixMergeRow.Id.Id, record[1]); |
111 | //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); | 114 | //WixFileRow wixFileRow = (WixFileRow)this.WixFileTable.CreateRow(wixMergeRow.SourceLineNumbers, false); |
112 | //wixFileRow.Directory = record[2]; | 115 | //wixFileRow.Directory = record[2]; |
113 | //wixFileRow.DiskId = wixMergeRow.DiskId; | 116 | //wixFileRow.DiskId = wixMergeRow.DiskId; |
@@ -119,11 +122,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
119 | // If case-sensitive collision with another merge module or a user-authored file identifier. | 122 | // If case-sensitive collision with another merge module or a user-authored file identifier. |
120 | if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) | 123 | if (indexedFileFacades.TryGetValue(mergeModuleFileFacade.File.File, out var collidingFacade)) |
121 | { | 124 | { |
122 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, collidingFacade.File.File)); | 125 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, collidingFacade.File.File)); |
123 | } | 126 | } |
124 | else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module | 127 | else if (uniqueModuleFileIdentifiers.TryGetValue(mergeModuleFileFacade.File.File, out collidingFacade)) // case-insensitive collision with another file identifier in the same merge module |
125 | { | 128 | { |
126 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); | 129 | Messaging.Instance.OnMessage(WixErrors.DuplicateModuleCaseInsensitiveFileIdentifier(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, mergeModuleFileFacade.File.File, collidingFacade.File.File)); |
127 | } | 130 | } |
128 | else // no collision | 131 | else // no collision |
129 | { | 132 | { |
@@ -150,12 +153,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
150 | int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture); | 153 | int moduleInstallerVersion = Convert.ToInt32(moduleInstallerVersionString, CultureInfo.InvariantCulture); |
151 | if (moduleInstallerVersion > this.OutputInstallerVersion) | 154 | if (moduleInstallerVersion > this.OutputInstallerVersion) |
152 | { | 155 | { |
153 | Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, moduleInstallerVersion, this.OutputInstallerVersion)); | 156 | Messaging.Instance.OnMessage(WixWarnings.InvalidHigherInstallerVersionInModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, moduleInstallerVersion, this.OutputInstallerVersion)); |
154 | } | 157 | } |
155 | } | 158 | } |
156 | catch (FormatException) | 159 | catch (FormatException) |
157 | { | 160 | { |
158 | throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); | 161 | throw new WixException(WixErrors.MissingOrInvalidModuleInstallerVersion(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile, moduleInstallerVersionString)); |
159 | } | 162 | } |
160 | } | 163 | } |
161 | } | 164 | } |
@@ -166,24 +169,26 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
166 | } | 169 | } |
167 | catch (Win32Exception) | 170 | catch (Win32Exception) |
168 | { | 171 | { |
169 | throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.SourceFile)); | 172 | throw new WixException(WixErrors.CannotOpenMergeModule(wixMergeRow.SourceLineNumbers, wixMergeRow.Id.Id, wixMergeRow.SourceFile)); |
170 | } | 173 | } |
171 | 174 | ||
172 | return containsFiles; | 175 | return containsFiles; |
173 | } | 176 | } |
174 | 177 | ||
175 | private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeRow wixMergeRow) | 178 | private void ExtractFilesFromMergeModule(IMsmMerge2 merge, WixMergeTuple wixMergeRow) |
176 | { | 179 | { |
177 | bool moduleOpen = false; | 180 | bool moduleOpen = false; |
178 | short mergeLanguage; | 181 | short mergeLanguage; |
179 | 182 | ||
183 | var mergeId = wixMergeRow.Id.Id; | ||
184 | |||
180 | try | 185 | try |
181 | { | 186 | { |
182 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); | 187 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); |
183 | } | 188 | } |
184 | catch (System.FormatException) | 189 | catch (FormatException) |
185 | { | 190 | { |
186 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); | 191 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, mergeId, wixMergeRow.Language.ToString())); |
187 | return; | 192 | return; |
188 | } | 193 | } |
189 | 194 | ||
@@ -192,13 +197,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
192 | merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); | 197 | merge.OpenModule(wixMergeRow.SourceFile, mergeLanguage); |
193 | moduleOpen = true; | 198 | moduleOpen = true; |
194 | 199 | ||
195 | string safeMergeId = wixMergeRow.Number.ToString(CultureInfo.InvariantCulture.NumberFormat); | ||
196 | |||
197 | // extract the module cabinet, then explode all of the files to a temp directory | 200 | // extract the module cabinet, then explode all of the files to a temp directory |
198 | string moduleCabPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, safeMergeId, ".module.cab"); | 201 | string moduleCabPath = Path.Combine(this.IntermediateFolder, mergeId + ".cab"); |
199 | merge.ExtractCAB(moduleCabPath); | 202 | merge.ExtractCAB(moduleCabPath); |
200 | 203 | ||
201 | string mergeIdPath = String.Concat(this.IntermediateFolder, Path.DirectorySeparatorChar, "MergeId.", safeMergeId); | 204 | string mergeIdPath = Path.Combine(this.IntermediateFolder, mergeId); |
202 | Directory.CreateDirectory(mergeIdPath); | 205 | Directory.CreateDirectory(mergeIdPath); |
203 | 206 | ||
204 | using (var extractCab = new WixExtractCab()) | 207 | using (var extractCab = new WixExtractCab()) |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs index 47b58058..a3d3ecf7 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GenerateDatabaseCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs index 9bbb4763..70ba971f 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/GetFileFacadesCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
@@ -8,57 +8,50 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
8 | using System.Linq; | 8 | using System.Linq; |
9 | using WixToolset.Core.Bind; | 9 | using WixToolset.Core.Bind; |
10 | using WixToolset.Data; | 10 | using WixToolset.Data; |
11 | using WixToolset.Data.Rows; | 11 | using WixToolset.Data.Tuples; |
12 | 12 | ||
13 | internal class GetFileFacadesCommand | 13 | internal class GetFileFacadesCommand |
14 | { | 14 | { |
15 | public Table FileTable { private get; set; } | 15 | public GetFileFacadesCommand(IntermediateSection section) |
16 | 16 | { | |
17 | public Table WixFileTable { private get; set; } | 17 | this.Section = section; |
18 | 18 | } | |
19 | public Table WixDeltaPatchFileTable { private get; set; } | ||
20 | 19 | ||
21 | public Table WixDeltaPatchSymbolPathsTable { private get; set; } | 20 | private IntermediateSection Section { get; } |
22 | 21 | ||
23 | public List<FileFacade> FileFacades { get; private set; } | 22 | public List<FileFacade> FileFacades { get; private set; } |
24 | 23 | ||
25 | public void Execute() | 24 | public void Execute() |
26 | { | 25 | { |
27 | throw new NotImplementedException(); | 26 | var facades = new List<FileFacade>(); |
28 | #if TODO | ||
29 | List<FileFacade> facades = new List<FileFacade>(this.FileTable.Rows.Count); | ||
30 | 27 | ||
31 | RowDictionary<WixFileRow> wixFiles = new RowDictionary<WixFileRow>(this.WixFileTable); | 28 | var wixFiles = this.Section.Tuples.OfType<WixFileTuple>().ToDictionary(t => t.File_); |
32 | RowDictionary<WixDeltaPatchFileRow> deltaPatchFiles = new RowDictionary<WixDeltaPatchFileRow>(this.WixDeltaPatchFileTable); | 29 | var deltaPatchFiles = this.Section.Tuples.OfType<WixDeltaPatchFileTuple>().ToDictionary(t => t.File_); |
33 | 30 | ||
34 | foreach (FileRow file in this.FileTable.Rows) | 31 | foreach (var file in this.Section.Tuples.OfType<FileTuple>()) |
35 | { | 32 | { |
36 | WixDeltaPatchFileRow deltaPatchFile = null; | 33 | var wixFile = wixFiles[file.File]; |
37 | 34 | ||
38 | deltaPatchFiles.TryGetValue(file.File, out deltaPatchFile); | 35 | deltaPatchFiles.TryGetValue(file.File, out var deltaPatchFile); |
39 | 36 | ||
40 | facades.Add(new FileFacade(file, wixFiles[file.File], deltaPatchFile)); | 37 | facades.Add(new FileFacade(file, wixFile, deltaPatchFile)); |
41 | } | 38 | } |
42 | 39 | ||
43 | if (null != this.WixDeltaPatchSymbolPathsTable) | 40 | this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); |
44 | { | ||
45 | this.ResolveDeltaPatchSymbolPaths(deltaPatchFiles, facades); | ||
46 | } | ||
47 | 41 | ||
48 | this.FileFacades = facades; | 42 | this.FileFacades = facades; |
49 | #endif | ||
50 | } | 43 | } |
51 | 44 | ||
52 | /// <summary> | 45 | /// <summary> |
53 | /// Merge data from the WixPatchSymbolPaths rows into the WixDeltaPatchFile rows. | 46 | /// Merge data from the WixPatchSymbolPaths rows into the WixDeltaPatchFile rows. |
54 | /// </summary> | 47 | /// </summary> |
55 | public RowDictionary<WixDeltaPatchFileRow> ResolveDeltaPatchSymbolPaths(RowDictionary<WixDeltaPatchFileRow> deltaPatchFiles, IEnumerable<FileFacade> facades) | 48 | public void ResolveDeltaPatchSymbolPaths(Dictionary<string, WixDeltaPatchFileTuple> deltaPatchFiles, IEnumerable<FileFacade> facades) |
56 | { | 49 | { |
57 | ILookup<string, FileFacade> filesByComponent = null; | 50 | ILookup<string, FileFacade> filesByComponent = null; |
58 | ILookup<string, FileFacade> filesByDirectory = null; | 51 | ILookup<string, FileFacade> filesByDirectory = null; |
59 | ILookup<string, FileFacade> filesByDiskId = null; | 52 | ILookup<string, FileFacade> filesByDiskId = null; |
60 | 53 | ||
61 | foreach (WixDeltaPatchSymbolPathsRow row in this.WixDeltaPatchSymbolPathsTable.RowsAs<WixDeltaPatchSymbolPathsRow>().OrderBy(r => r.Type)) | 54 | foreach (var row in this.Section.Tuples.OfType<WixDeltaPatchSymbolPathsTuple>().OrderBy(r => r.Type)) |
62 | { | 55 | { |
63 | switch (row.Type) | 56 | switch (row.Type) |
64 | { | 57 | { |
@@ -72,7 +65,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
72 | filesByComponent = facades.ToLookup(f => f.File.Component_); | 65 | filesByComponent = facades.ToLookup(f => f.File.Component_); |
73 | } | 66 | } |
74 | 67 | ||
75 | foreach (FileFacade facade in filesByComponent[row.Id]) | 68 | foreach (var facade in filesByComponent[row.Id]) |
76 | { | 69 | { |
77 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); | 70 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); |
78 | } | 71 | } |
@@ -84,7 +77,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
84 | filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_); | 77 | filesByDirectory = facades.ToLookup(f => f.WixFile.Directory_); |
85 | } | 78 | } |
86 | 79 | ||
87 | foreach (FileFacade facade in filesByDirectory[row.Id]) | 80 | foreach (var facade in filesByDirectory[row.Id]) |
88 | { | 81 | { |
89 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); | 82 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); |
90 | } | 83 | } |
@@ -96,14 +89,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
96 | filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture)); | 89 | filesByDiskId = facades.ToLookup(f => f.WixFile.DiskId.ToString(CultureInfo.InvariantCulture)); |
97 | } | 90 | } |
98 | 91 | ||
99 | foreach (FileFacade facade in filesByDiskId[row.Id]) | 92 | foreach (var facade in filesByDiskId[row.Id]) |
100 | { | 93 | { |
101 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); | 94 | this.MergeSymbolPaths(row, deltaPatchFiles[facade.File.File]); |
102 | } | 95 | } |
103 | break; | 96 | break; |
104 | 97 | ||
105 | case SymbolPathType.Product: | 98 | case SymbolPathType.Product: |
106 | foreach (WixDeltaPatchFileRow fileRow in deltaPatchFiles.Values) | 99 | foreach (var fileRow in deltaPatchFiles.Values) |
107 | { | 100 | { |
108 | this.MergeSymbolPaths(row, fileRow); | 101 | this.MergeSymbolPaths(row, fileRow); |
109 | } | 102 | } |
@@ -114,8 +107,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
114 | break; | 107 | break; |
115 | } | 108 | } |
116 | } | 109 | } |
117 | |||
118 | return deltaPatchFiles; | ||
119 | } | 110 | } |
120 | 111 | ||
121 | /// <summary> | 112 | /// <summary> |
@@ -124,17 +115,18 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
124 | /// <param name="row">Row from the WixPatchSymbolsPaths table.</param> | 115 | /// <param name="row">Row from the WixPatchSymbolsPaths table.</param> |
125 | /// <param name="file">FileRow into which to set symbol information.</param> | 116 | /// <param name="file">FileRow into which to set symbol information.</param> |
126 | /// <comment>This includes PreviousData as well.</comment> | 117 | /// <comment>This includes PreviousData as well.</comment> |
127 | private void MergeSymbolPaths(WixDeltaPatchSymbolPathsRow row, WixDeltaPatchFileRow file) | 118 | private void MergeSymbolPaths(WixDeltaPatchSymbolPathsTuple row, WixDeltaPatchFileTuple file) |
128 | { | 119 | { |
129 | if (null == file.Symbols) | 120 | if (file.SymbolPaths is null) |
130 | { | 121 | { |
131 | file.Symbols = row.SymbolPaths; | 122 | file.SymbolPaths = row.SymbolPaths; |
132 | } | 123 | } |
133 | else | 124 | else |
134 | { | 125 | { |
135 | file.Symbols = String.Concat(file.Symbols, ";", row.SymbolPaths); | 126 | file.SymbolPaths = String.Concat(file.SymbolPaths, ";", row.SymbolPaths); |
136 | } | 127 | } |
137 | 128 | ||
129 | #if REVISIT_FOR_PATCHING | ||
138 | Field field = row.Fields[2]; | 130 | Field field = row.Fields[2]; |
139 | if (null != field.PreviousData) | 131 | if (null != field.PreviousData) |
140 | { | 132 | { |
@@ -147,6 +139,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
147 | file.PreviousSymbols = String.Concat(file.PreviousSymbols, ";", field.PreviousData); | 139 | file.PreviousSymbols = String.Concat(file.PreviousSymbols, ";", field.PreviousData); |
148 | } | 140 | } |
149 | } | 141 | } |
142 | #endif | ||
150 | } | 143 | } |
151 | } | 144 | } |
152 | } | 145 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs index f1605eca..dcf67c05 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/MergeModulesCommand.cs | |||
@@ -1,20 +1,13 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.Collections.Specialized; | ||
8 | using System.ComponentModel; | ||
9 | using System.Diagnostics; | ||
10 | using System.Globalization; | 7 | using System.Globalization; |
11 | using System.IO; | 8 | using System.IO; |
12 | using System.Linq; | ||
13 | using System.Runtime.InteropServices; | 9 | using System.Runtime.InteropServices; |
14 | using System.Text; | 10 | using System.Text; |
15 | using System.Xml; | ||
16 | using System.Xml.XPath; | ||
17 | using WixToolset.Clr.Interop; | ||
18 | using WixToolset.Data; | 11 | using WixToolset.Data; |
19 | using WixToolset.Data.Rows; | 12 | using WixToolset.Data.Rows; |
20 | using WixToolset.MergeMod; | 13 | using WixToolset.MergeMod; |
@@ -35,12 +28,10 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
35 | 28 | ||
36 | public IEnumerable<string> SuppressedTableNames { private get; set; } | 29 | public IEnumerable<string> SuppressedTableNames { private get; set; } |
37 | 30 | ||
38 | public string TempFilesLocation { private get; set; } | 31 | public string IntermediateFolder { private get; set; } |
39 | 32 | ||
40 | public void Execute() | 33 | public void Execute() |
41 | { | 34 | { |
42 | Debug.Assert(OutputType.Product == this.Output.Type); | ||
43 | |||
44 | Table wixMergeTable = this.Output.Tables["WixMerge"]; | 35 | Table wixMergeTable = this.Output.Tables["WixMerge"]; |
45 | Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"]; | 36 | Table wixFeatureModulesTable = this.Output.Tables["WixFeatureModules"]; |
46 | 37 | ||
@@ -59,7 +50,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
59 | { | 50 | { |
60 | merge = MsmInterop.GetMsmMerge(); | 51 | merge = MsmInterop.GetMsmMerge(); |
61 | 52 | ||
62 | logPath = Path.Combine(this.TempFilesLocation, "merge.log"); | 53 | logPath = Path.Combine(this.IntermediateFolder, "merge.log"); |
63 | merge.OpenLog(logPath); | 54 | merge.OpenLog(logPath); |
64 | logOpen = true; | 55 | logOpen = true; |
65 | 56 | ||
@@ -79,7 +70,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
79 | { | 70 | { |
80 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); | 71 | mergeLanguage = Convert.ToInt16(wixMergeRow.Language, CultureInfo.InvariantCulture); |
81 | } | 72 | } |
82 | catch (System.FormatException) | 73 | catch (FormatException) |
83 | { | 74 | { |
84 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); | 75 | Messaging.Instance.OnMessage(WixErrors.InvalidMergeLanguage(wixMergeRow.SourceLineNumbers, wixMergeRow.Id, wixMergeRow.Language)); |
85 | continue; | 76 | continue; |
@@ -284,7 +275,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
284 | Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles()); | 275 | Messaging.Instance.OnMessage(WixVerboses.ResequencingMergeModuleFiles()); |
285 | using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) | 276 | using (View view = db.OpenView("SELECT `Sequence`, `Attributes` FROM `File` WHERE `File`=?")) |
286 | { | 277 | { |
287 | foreach (FileFacade file in this.FileFacades) | 278 | foreach (var file in this.FileFacades) |
288 | { | 279 | { |
289 | if (!file.FromModule) | 280 | if (!file.FromModule) |
290 | { | 281 | { |
@@ -307,32 +298,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
307 | //recordUpdate.SetInteger(1, file.File.Sequence); | 298 | //recordUpdate.SetInteger(1, file.File.Sequence); |
308 | throw new NotImplementedException(); | 299 | throw new NotImplementedException(); |
309 | 300 | ||
310 | // update the file attributes to match the compression specified | 301 | // Update the file attributes to match the compression specified |
311 | // on the Merge element or on the Package element | 302 | // on the Merge element or on the Package element. |
312 | int attributes = 0; | 303 | var attributes = 0; |
313 | 304 | ||
314 | // get the current value if its not null | 305 | // Get the current value if its not null. |
315 | if (!recordUpdate.IsNull(2)) | 306 | if (!recordUpdate.IsNull(2)) |
316 | { | 307 | { |
317 | attributes = recordUpdate.GetInteger(2); | 308 | attributes = recordUpdate.GetInteger(2); |
318 | } | 309 | } |
319 | 310 | ||
320 | // not specified | ||
321 | if (!file.File.Compressed.HasValue) | 311 | if (!file.File.Compressed.HasValue) |
322 | { | 312 | { |
323 | // clear any compression bits | 313 | // Clear all compression bits. |
324 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; | 314 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; |
325 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; | 315 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; |
326 | } | 316 | } |
327 | else if (file.File.Compressed.Value) | 317 | else if (file.File.Compressed.Value) |
328 | { | 318 | { |
329 | // these are mutually exclusive | ||
330 | attributes |= MsiInterop.MsidbFileAttributesCompressed; | 319 | attributes |= MsiInterop.MsidbFileAttributesCompressed; |
331 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; | 320 | attributes &= ~MsiInterop.MsidbFileAttributesNoncompressed; |
332 | } | 321 | } |
333 | else if (!file.File.Compressed.Value) | 322 | else if (!file.File.Compressed.Value) |
334 | { | 323 | { |
335 | // these are mutually exclusive | ||
336 | attributes |= MsiInterop.MsidbFileAttributesNoncompressed; | 324 | attributes |= MsiInterop.MsidbFileAttributesNoncompressed; |
337 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; | 325 | attributes &= ~MsiInterop.MsidbFileAttributesCompressed; |
338 | } | 326 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs index b3c09b9e..d71724d1 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/ProcessUncompressedFilesCommand.cs | |||
@@ -1,39 +1,42 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | ||
7 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
8 | using System.IO; | 7 | using System.IO; |
9 | using WixToolset.Data; | 8 | using WixToolset.Data; |
10 | using WixToolset.Data.Rows; | ||
11 | using WixToolset.Msi; | 9 | using WixToolset.Msi; |
12 | using WixToolset.Core.Native; | 10 | using WixToolset.Core.Native; |
13 | using WixToolset.Bind; | 11 | using WixToolset.Bind; |
14 | using WixToolset.Core.Bind; | 12 | using WixToolset.Core.Bind; |
15 | using WixToolset.Data.Bind; | 13 | using WixToolset.Data.Bind; |
14 | using WixToolset.Data.Tuples; | ||
15 | using System.Linq; | ||
16 | 16 | ||
17 | /// <summary> | 17 | /// <summary> |
18 | /// Defines the file transfers necessary to layout the uncompressed files. | 18 | /// Defines the file transfers necessary to layout the uncompressed files. |
19 | /// </summary> | 19 | /// </summary> |
20 | internal class ProcessUncompressedFilesCommand | 20 | internal class ProcessUncompressedFilesCommand |
21 | { | 21 | { |
22 | public ProcessUncompressedFilesCommand(IntermediateSection section) | ||
23 | { | ||
24 | this.Section = section; | ||
25 | } | ||
26 | |||
27 | private IntermediateSection Section { get; } | ||
28 | |||
22 | public string DatabasePath { private get; set; } | 29 | public string DatabasePath { private get; set; } |
23 | 30 | ||
24 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 31 | public IEnumerable<FileFacade> FileFacades { private get; set; } |
25 | 32 | ||
26 | public RowDictionary<MediaRow> MediaRows { private get; set; } | ||
27 | |||
28 | public string LayoutDirectory { private get; set; } | 33 | public string LayoutDirectory { private get; set; } |
29 | 34 | ||
30 | public bool Compressed { private get; set; } | 35 | public bool Compressed { private get; set; } |
31 | 36 | ||
32 | public bool LongNamesInImage { private get; set; } | 37 | public bool LongNamesInImage { private get; set; } |
33 | 38 | ||
34 | public Func<MediaRow, string, string, string> ResolveMedia { private get; set; } | 39 | public Func<MediaTuple, string, string, string> ResolveMedia { private get; set; } |
35 | |||
36 | public Table WixMediaTable { private get; set; } | ||
37 | 40 | ||
38 | public IEnumerable<FileTransfer> FileTransfers { get; private set; } | 41 | public IEnumerable<FileTransfer> FileTransfers { get; private set; } |
39 | 42 | ||
@@ -41,9 +44,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
41 | { | 44 | { |
42 | List<FileTransfer> fileTransfers = new List<FileTransfer>(); | 45 | List<FileTransfer> fileTransfers = new List<FileTransfer>(); |
43 | 46 | ||
44 | Hashtable directories = new Hashtable(); | 47 | var directories = new Dictionary<string, ResolvedDirectory>(); |
45 | 48 | ||
46 | RowDictionary<WixMediaRow> wixMediaRows = new RowDictionary<WixMediaRow>(this.WixMediaTable); | 49 | var mediaRows = this.Section.Tuples.OfType<MediaTuple>().ToDictionary(t => t.DiskId); |
50 | |||
51 | var wixMediaRows = this.Section.Tuples.OfType<WixMediaTuple>().ToDictionary(t => t.DiskId_); | ||
47 | 52 | ||
48 | using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) | 53 | using (Database db = new Database(this.DatabasePath, OpenDatabase.ReadOnly)) |
49 | { | 54 | { |
@@ -72,18 +77,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
72 | // for each file in the array of uncompressed files | 77 | // for each file in the array of uncompressed files |
73 | foreach (FileFacade facade in this.FileFacades) | 78 | foreach (FileFacade facade in this.FileFacades) |
74 | { | 79 | { |
75 | MediaRow mediaRow = this.MediaRows.Get(facade.WixFile.DiskId); | 80 | var mediaTuple = mediaRows[facade.WixFile.DiskId]; |
76 | string relativeFileLayoutPath = null; | 81 | string relativeFileLayoutPath = null; |
77 | |||
78 | WixMediaRow wixMediaRow = null; | ||
79 | string mediaLayoutFolder = null; | 82 | string mediaLayoutFolder = null; |
80 | 83 | ||
81 | if (wixMediaRows.TryGetValue(mediaRow.GetKey(), out wixMediaRow)) | 84 | if (wixMediaRows.TryGetValue(facade.WixFile.DiskId, out var wixMediaRow)) |
82 | { | 85 | { |
83 | mediaLayoutFolder = wixMediaRow.Layout; | 86 | mediaLayoutFolder = wixMediaRow.Layout; |
84 | } | 87 | } |
85 | 88 | ||
86 | string mediaLayoutDirectory = this.ResolveMedia(mediaRow, mediaLayoutFolder, this.LayoutDirectory); | 89 | var mediaLayoutDirectory = this.ResolveMedia(mediaTuple, mediaLayoutFolder, this.LayoutDirectory); |
87 | 90 | ||
88 | // setup up the query record and find the appropriate file in the | 91 | // setup up the query record and find the appropriate file in the |
89 | // previously executed file view | 92 | // previously executed file view |
@@ -102,8 +105,7 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
102 | 105 | ||
103 | // finally put together the base media layout path and the relative file layout path | 106 | // finally put together the base media layout path and the relative file layout path |
104 | string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); | 107 | string fileLayoutPath = Path.Combine(mediaLayoutDirectory, relativeFileLayoutPath); |
105 | FileTransfer transfer; | 108 | if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out var transfer)) |
106 | if (FileTransfer.TryCreate(facade.WixFile.Source, fileLayoutPath, false, "File", facade.File.SourceLineNumbers, out transfer)) | ||
107 | { | 109 | { |
108 | fileTransfers.Add(transfer); | 110 | fileTransfers.Add(transfer); |
109 | } | 111 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs new file mode 100644 index 00000000..cf9c0332 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/SequenceActionsCommand.cs | |||
@@ -0,0 +1,671 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Globalization; | ||
8 | using System.Linq; | ||
9 | using WixToolset.Core.Native; | ||
10 | using WixToolset.Data; | ||
11 | using WixToolset.Data.Tuples; | ||
12 | |||
13 | internal class SequenceActionsCommand | ||
14 | { | ||
15 | public SequenceActionsCommand(IntermediateSection section) | ||
16 | { | ||
17 | this.Section = section; | ||
18 | |||
19 | this.RelativeActionsForActions = new Dictionary<string, RelativeActions>(); | ||
20 | |||
21 | this.StandardActionsById = WindowsInstallerStandard.StandardActions().ToDictionary(a => a.Id.Id); | ||
22 | } | ||
23 | |||
24 | private IntermediateSection Section { get; } | ||
25 | |||
26 | private Dictionary<string, RelativeActions> RelativeActionsForActions { get; } | ||
27 | |||
28 | private Dictionary<string, WixActionTuple> StandardActionsById { get; } | ||
29 | |||
30 | public Messaging Messaging { private get; set; } | ||
31 | |||
32 | public void Execute() | ||
33 | { | ||
34 | var actions = this.Section.Tuples.OfType<WixActionTuple>().ToList(); | ||
35 | var suppressActions = this.Section.Tuples.OfType<WixSuppressActionTuple>().ToList(); | ||
36 | |||
37 | this.SequenceActions(actions, suppressActions); | ||
38 | } | ||
39 | |||
40 | /// <summary> | ||
41 | /// Set sequence numbers for all the actions and create rows in the output object. | ||
42 | /// </summary> | ||
43 | /// <param name="actionRows">Collection of actions to schedule.</param> | ||
44 | /// <param name="suppressActionRows">Collection of actions to suppress.</param> | ||
45 | private void SequenceActions(List<WixActionTuple> actionRows, List<WixSuppressActionTuple> suppressActionRows) | ||
46 | { | ||
47 | var overridableActionRows = new Dictionary<string, WixActionTuple>(); | ||
48 | var requiredActionRows = new Dictionary<string, WixActionTuple>(); | ||
49 | |||
50 | // Get the standard actions required based on tuples in the section. | ||
51 | var requiredActionIds = this.GetRequiredActionIds(); | ||
52 | |||
53 | foreach (var actionId in requiredActionIds) | ||
54 | { | ||
55 | var standardAction = this.StandardActionsById[actionId]; | ||
56 | |||
57 | overridableActionRows.Add(standardAction.Id.Id, standardAction); | ||
58 | } | ||
59 | |||
60 | // Index all the action rows and look for collisions. | ||
61 | foreach (var actionRow in this.Section.Tuples.OfType<WixActionTuple>()) | ||
62 | { | ||
63 | if (actionRow.Overridable) // overridable action | ||
64 | { | ||
65 | if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) | ||
66 | { | ||
67 | this.Messaging.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
68 | if (null != collidingActionRow.SourceLineNumbers) | ||
69 | { | ||
70 | this.Messaging.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers)); | ||
71 | } | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | overridableActionRows.Add(actionRow.Id.Id, actionRow); | ||
76 | } | ||
77 | } | ||
78 | else // unsequenced or sequenced action. | ||
79 | { | ||
80 | // Unsequenced action (allowed for certain standard actions). | ||
81 | if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence) | ||
82 | { | ||
83 | if (this.StandardActionsById.TryGetValue(actionRow.Id.Id, out var standardAction)) | ||
84 | { | ||
85 | // Populate the sequence from the standard action | ||
86 | actionRow.Sequence = standardAction.Sequence; | ||
87 | } | ||
88 | else // not a supported unscheduled action. | ||
89 | { | ||
90 | throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | if (overridableActionRows.TryGetValue(actionRow.Id.Id, out var collidingActionRow)) | ||
95 | { | ||
96 | this.Messaging.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
97 | if (null != collidingActionRow.SourceLineNumbers) | ||
98 | { | ||
99 | this.Messaging.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers)); | ||
100 | } | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | requiredActionRows.Add(actionRow.Id.Id, actionRow); | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | // Add the overridable action rows that are not overridden to the required action rows. | ||
110 | foreach (var actionRow in overridableActionRows.Values) | ||
111 | { | ||
112 | if (!requiredActionRows.ContainsKey(actionRow.Id.Id)) | ||
113 | { | ||
114 | requiredActionRows.Add(actionRow.Id.Id, actionRow); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | // Suppress the required actions that are overridable. | ||
119 | foreach (var suppressActionRow in suppressActionRows) | ||
120 | { | ||
121 | var key = suppressActionRow.Id.Id; | ||
122 | |||
123 | // If there is an overridable row to suppress; suppress it. There is no warning if there | ||
124 | // is no action to suppress because the action may be suppressed from a merge module in | ||
125 | // the binder. | ||
126 | if (requiredActionRows.TryGetValue(key, out var requiredActionRow)) | ||
127 | { | ||
128 | if (requiredActionRow.Overridable) | ||
129 | { | ||
130 | this.Messaging.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, suppressActionRow.Action, suppressActionRow.SequenceTable.ToString())); | ||
131 | if (null != requiredActionRow.SourceLineNumbers) | ||
132 | { | ||
133 | this.Messaging.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers)); | ||
134 | } | ||
135 | |||
136 | requiredActionRows.Remove(key); | ||
137 | } | ||
138 | else // suppressing a non-overridable action row | ||
139 | { | ||
140 | this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, suppressActionRow.SequenceTable.ToString(), suppressActionRow.Action)); | ||
141 | if (null != requiredActionRow.SourceLineNumbers) | ||
142 | { | ||
143 | this.Messaging.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers)); | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | |||
149 | // Build up dependency trees of the relatively scheduled actions. | ||
150 | // Use ToList() to create a copy of the required action rows so that new tuples can | ||
151 | // be added while enumerating. | ||
152 | foreach (var actionRow in requiredActionRows.Values.ToList()) | ||
153 | { | ||
154 | if (0 == actionRow.Sequence) | ||
155 | { | ||
156 | // check for standard actions that don't have a sequence number in a merge module | ||
157 | if (SectionType.Module == this.Section.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action)) | ||
158 | { | ||
159 | this.Messaging.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
160 | } | ||
161 | |||
162 | this.SequenceActionRow(actionRow, requiredActionRows); | ||
163 | } | ||
164 | else if (SectionType.Module == this.Section.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number | ||
165 | { | ||
166 | this.Messaging.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | // Look for standard actions with sequence restrictions that aren't necessarily scheduled based | ||
171 | // on the presence of a particular table. | ||
172 | if (requiredActionRows.ContainsKey("InstallExecuteSequence/DuplicateFiles") && !requiredActionRows.ContainsKey("InstallExecuteSequence/InstallFiles")) | ||
173 | { | ||
174 | var standardAction = this.StandardActionsById["InstallExecuteSequence/InstallFiles"]; | ||
175 | requiredActionRows.Add(standardAction.Id.Id, standardAction); | ||
176 | } | ||
177 | |||
178 | // Schedule actions. | ||
179 | List<WixActionTuple> scheduledActionRows; | ||
180 | if (SectionType.Module == this.Section.Type) | ||
181 | { | ||
182 | scheduledActionRows = requiredActionRows.Values.ToList(); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | scheduledActionRows = ScheduleActions(requiredActionRows); | ||
187 | } | ||
188 | |||
189 | // Remove all existing WixActionTuples from the section then add the | ||
190 | // scheduled actions back to the section. Note: we add the indices in | ||
191 | // reverse order to make it easy to remove them from the list later. | ||
192 | var removeIndices = new List<int>(); | ||
193 | for (var i = this.Section.Tuples.Count - 1; i >= 0; --i) | ||
194 | { | ||
195 | var tuple = this.Section.Tuples[i]; | ||
196 | if (tuple.Definition.Type == TupleDefinitionType.WixAction) | ||
197 | { | ||
198 | removeIndices.Add(i); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | foreach (var removeIndex in removeIndices) | ||
203 | { | ||
204 | this.Section.Tuples.RemoveAt(removeIndex); | ||
205 | } | ||
206 | |||
207 | foreach (var action in scheduledActionRows) | ||
208 | { | ||
209 | this.Section.Tuples.Add(action); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | private List<WixActionTuple> ScheduleActions(Dictionary<string, WixActionTuple> requiredActionRows) | ||
214 | { | ||
215 | var scheduledActionRows = new List<WixActionTuple>(); | ||
216 | |||
217 | // Process each sequence table individually. | ||
218 | foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) | ||
219 | { | ||
220 | // Create a collection of just the action rows in this sequence | ||
221 | var sequenceActionRows = requiredActionRows.Values.Where(a => a.SequenceTable == sequenceTable).ToList(); | ||
222 | |||
223 | // Schedule the absolutely scheduled actions (by sorting them by their sequence numbers). | ||
224 | var absoluteActionRows = new List<WixActionTuple>(); | ||
225 | foreach (var actionRow in sequenceActionRows) | ||
226 | { | ||
227 | if (0 != actionRow.Sequence) | ||
228 | { | ||
229 | // Look for sequence number collisions | ||
230 | foreach (var sequenceScheduledActionRow in absoluteActionRows) | ||
231 | { | ||
232 | if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) | ||
233 | { | ||
234 | this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); | ||
235 | if (null != sequenceScheduledActionRow.SourceLineNumbers) | ||
236 | { | ||
237 | this.Messaging.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | absoluteActionRows.Add(actionRow); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | absoluteActionRows.Sort((x, y) => x.Sequence.CompareTo(y.Sequence)); | ||
247 | |||
248 | // Schedule the relatively scheduled actions (by resolving the dependency trees). | ||
249 | var previousUsedSequence = 0; | ||
250 | var relativeActionRows = new List<WixActionTuple>(); | ||
251 | for (int j = 0; j < absoluteActionRows.Count; j++) | ||
252 | { | ||
253 | var absoluteActionRow = absoluteActionRows[j]; | ||
254 | |||
255 | // Get all the relatively scheduled action rows occuring before and after this absolutely scheduled action row. | ||
256 | var relativeActions = this.GetAllRelativeActionsForSequenceType(sequenceTable, absoluteActionRow); | ||
257 | |||
258 | // Check for relatively scheduled actions occuring before/after a special action | ||
259 | // (those actions with a negative sequence number). | ||
260 | if (absoluteActionRow.Sequence < 0 && (relativeActions.PreviousActions.Any() || relativeActions.NextActions.Any())) | ||
261 | { | ||
262 | // Create errors for all the before actions. | ||
263 | foreach (var actionRow in relativeActions.PreviousActions) | ||
264 | { | ||
265 | this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); | ||
266 | } | ||
267 | |||
268 | // Create errors for all the after actions. | ||
269 | foreach (var actionRow in relativeActions.NextActions) | ||
270 | { | ||
271 | this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); | ||
272 | } | ||
273 | |||
274 | // If there is source line information for the absolutely scheduled action display it | ||
275 | if (absoluteActionRow.SourceLineNumbers != null) | ||
276 | { | ||
277 | this.Messaging.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers)); | ||
278 | } | ||
279 | |||
280 | continue; | ||
281 | } | ||
282 | |||
283 | // Schedule the action rows before this one. | ||
284 | var unusedSequence = absoluteActionRow.Sequence - 1; | ||
285 | for (var i = relativeActions.PreviousActions.Count - 1; i >= 0; i--) | ||
286 | { | ||
287 | var relativeActionRow = relativeActions.PreviousActions[i]; | ||
288 | |||
289 | // look for collisions | ||
290 | if (unusedSequence == previousUsedSequence) | ||
291 | { | ||
292 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); | ||
293 | if (absoluteActionRow.SourceLineNumbers != null) | ||
294 | { | ||
295 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); | ||
296 | } | ||
297 | |||
298 | unusedSequence++; | ||
299 | } | ||
300 | |||
301 | relativeActionRow.Sequence = unusedSequence; | ||
302 | relativeActionRows.Add(relativeActionRow); | ||
303 | |||
304 | unusedSequence--; | ||
305 | } | ||
306 | |||
307 | // Determine the next used action sequence number. | ||
308 | var nextUsedSequence = Int16.MaxValue + 1; | ||
309 | if (absoluteActionRows.Count > j + 1) | ||
310 | { | ||
311 | nextUsedSequence = absoluteActionRows[j + 1].Sequence; | ||
312 | } | ||
313 | |||
314 | // Schedule the action rows after this one. | ||
315 | unusedSequence = absoluteActionRow.Sequence + 1; | ||
316 | for (var i = 0; i < relativeActions.NextActions.Count; i++) | ||
317 | { | ||
318 | var relativeActionRow = relativeActions.NextActions[i]; | ||
319 | |||
320 | if (unusedSequence == nextUsedSequence) | ||
321 | { | ||
322 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); | ||
323 | if (absoluteActionRow.SourceLineNumbers != null) | ||
324 | { | ||
325 | this.Messaging.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); | ||
326 | } | ||
327 | |||
328 | unusedSequence--; | ||
329 | } | ||
330 | |||
331 | relativeActionRow.Sequence = unusedSequence; | ||
332 | relativeActionRows.Add(relativeActionRow); | ||
333 | |||
334 | unusedSequence++; | ||
335 | } | ||
336 | |||
337 | // keep track of this sequence number as the previous used sequence number for the next iteration | ||
338 | previousUsedSequence = absoluteActionRow.Sequence; | ||
339 | } | ||
340 | |||
341 | // add the absolutely and relatively scheduled actions to the list of scheduled actions | ||
342 | scheduledActionRows.AddRange(absoluteActionRows); | ||
343 | scheduledActionRows.AddRange(relativeActionRows); | ||
344 | } | ||
345 | |||
346 | return scheduledActionRows; | ||
347 | } | ||
348 | |||
349 | private IEnumerable<string> GetRequiredActionIds() | ||
350 | { | ||
351 | var set = new HashSet<string>(); | ||
352 | |||
353 | // gather the required actions for the output type | ||
354 | if (SectionType.Product == this.Section.Type) | ||
355 | { | ||
356 | // AdminExecuteSequence table | ||
357 | set.Add("AdminExecuteSequence/CostFinalize"); | ||
358 | set.Add("AdminExecuteSequence/CostInitialize"); | ||
359 | set.Add("AdminExecuteSequence/FileCost"); | ||
360 | set.Add("AdminExecuteSequence/InstallAdminPackage"); | ||
361 | set.Add("AdminExecuteSequence/InstallFiles"); | ||
362 | set.Add("AdminExecuteSequence/InstallFinalize"); | ||
363 | set.Add("AdminExecuteSequence/InstallInitialize"); | ||
364 | set.Add("AdminExecuteSequence/InstallValidate"); | ||
365 | |||
366 | // AdminUISequence table | ||
367 | set.Add("AdminUISequence/CostFinalize"); | ||
368 | set.Add("AdminUISequence/CostInitialize"); | ||
369 | set.Add("AdminUISequence/ExecuteAction"); | ||
370 | set.Add("AdminUISequence/FileCost"); | ||
371 | |||
372 | // AdvtExecuteSequence table | ||
373 | set.Add("AdvtExecuteSequence/CostFinalize"); | ||
374 | set.Add("AdvtExecuteSequence/CostInitialize"); | ||
375 | set.Add("AdvtExecuteSequence/InstallFinalize"); | ||
376 | set.Add("AdvtExecuteSequence/InstallValidate"); | ||
377 | set.Add("AdvtExecuteSequence/PublishFeatures"); | ||
378 | set.Add("AdvtExecuteSequence/PublishProduct"); | ||
379 | |||
380 | // InstallExecuteSequence table | ||
381 | set.Add("InstallExecuteSequence/CostFinalize"); | ||
382 | set.Add("InstallExecuteSequence/CostInitialize"); | ||
383 | set.Add("InstallExecuteSequence/FileCost"); | ||
384 | set.Add("InstallExecuteSequence/InstallFinalize"); | ||
385 | set.Add("InstallExecuteSequence/InstallInitialize"); | ||
386 | set.Add("InstallExecuteSequence/InstallValidate"); | ||
387 | set.Add("InstallExecuteSequence/ProcessComponents"); | ||
388 | set.Add("InstallExecuteSequence/PublishFeatures"); | ||
389 | set.Add("InstallExecuteSequence/PublishProduct"); | ||
390 | set.Add("InstallExecuteSequence/RegisterProduct"); | ||
391 | set.Add("InstallExecuteSequence/RegisterUser"); | ||
392 | set.Add("InstallExecuteSequence/UnpublishFeatures"); | ||
393 | set.Add("InstallExecuteSequence/ValidateProductID"); | ||
394 | |||
395 | // InstallUISequence table | ||
396 | set.Add("InstallUISequence/CostFinalize"); | ||
397 | set.Add("InstallUISequence/CostInitialize"); | ||
398 | set.Add("InstallUISequence/ExecuteAction"); | ||
399 | set.Add("InstallUISequence/FileCost"); | ||
400 | set.Add("InstallUISequence/ValidateProductID"); | ||
401 | } | ||
402 | |||
403 | // Gather the required actions for each tuple type. | ||
404 | foreach (var tupleType in this.Section.Tuples.Select(t => t.Definition.Type).Distinct()) | ||
405 | { | ||
406 | switch (tupleType) | ||
407 | { | ||
408 | case TupleDefinitionType.AppSearch: | ||
409 | set.Add("InstallExecuteSequence/AppSearch"); | ||
410 | set.Add("InstallUISequence/AppSearch"); | ||
411 | break; | ||
412 | case TupleDefinitionType.BindImage: | ||
413 | set.Add("InstallExecuteSequence/BindImage"); | ||
414 | break; | ||
415 | case TupleDefinitionType.CCPSearch: | ||
416 | set.Add("InstallExecuteSequence/AppSearch"); | ||
417 | set.Add("InstallExecuteSequence/CCPSearch"); | ||
418 | set.Add("InstallExecuteSequence/RMCCPSearch"); | ||
419 | set.Add("InstallUISequence/AppSearch"); | ||
420 | set.Add("InstallUISequence/CCPSearch"); | ||
421 | set.Add("InstallUISequence/RMCCPSearch"); | ||
422 | break; | ||
423 | case TupleDefinitionType.Class: | ||
424 | set.Add("AdvtExecuteSequence/RegisterClassInfo"); | ||
425 | set.Add("InstallExecuteSequence/RegisterClassInfo"); | ||
426 | set.Add("InstallExecuteSequence/UnregisterClassInfo"); | ||
427 | break; | ||
428 | case TupleDefinitionType.Complus: | ||
429 | set.Add("InstallExecuteSequence/RegisterComPlus"); | ||
430 | set.Add("InstallExecuteSequence/UnregisterComPlus"); | ||
431 | break; | ||
432 | case TupleDefinitionType.CreateFolder: | ||
433 | set.Add("InstallExecuteSequence/CreateFolders"); | ||
434 | set.Add("InstallExecuteSequence/RemoveFolders"); | ||
435 | break; | ||
436 | case TupleDefinitionType.DuplicateFile: | ||
437 | set.Add("InstallExecuteSequence/DuplicateFiles"); | ||
438 | set.Add("InstallExecuteSequence/RemoveDuplicateFiles"); | ||
439 | break; | ||
440 | case TupleDefinitionType.Environment: | ||
441 | set.Add("InstallExecuteSequence/WriteEnvironmentStrings"); | ||
442 | set.Add("InstallExecuteSequence/RemoveEnvironmentStrings"); | ||
443 | break; | ||
444 | case TupleDefinitionType.Extension: | ||
445 | set.Add("AdvtExecuteSequence/RegisterExtensionInfo"); | ||
446 | set.Add("InstallExecuteSequence/RegisterExtensionInfo"); | ||
447 | set.Add("InstallExecuteSequence/UnregisterExtensionInfo"); | ||
448 | break; | ||
449 | case TupleDefinitionType.File: | ||
450 | set.Add("InstallExecuteSequence/InstallFiles"); | ||
451 | set.Add("InstallExecuteSequence/RemoveFiles"); | ||
452 | break; | ||
453 | case TupleDefinitionType.Font: | ||
454 | set.Add("InstallExecuteSequence/RegisterFonts"); | ||
455 | set.Add("InstallExecuteSequence/UnregisterFonts"); | ||
456 | break; | ||
457 | case TupleDefinitionType.IniFile: | ||
458 | case TupleDefinitionType.RemoveIniFile: | ||
459 | set.Add("InstallExecuteSequence/WriteIniValues"); | ||
460 | set.Add("InstallExecuteSequence/RemoveIniValues"); | ||
461 | break; | ||
462 | case TupleDefinitionType.IsolatedComponent: | ||
463 | set.Add("InstallExecuteSequence/IsolateComponents"); | ||
464 | break; | ||
465 | case TupleDefinitionType.LaunchCondition: | ||
466 | set.Add("InstallExecuteSequence/LaunchConditions"); | ||
467 | set.Add("InstallUISequence/LaunchConditions"); | ||
468 | break; | ||
469 | case TupleDefinitionType.MIME: | ||
470 | set.Add("AdvtExecuteSequence/RegisterMIMEInfo"); | ||
471 | set.Add("InstallExecuteSequence/RegisterMIMEInfo"); | ||
472 | set.Add("InstallExecuteSequence/UnregisterMIMEInfo"); | ||
473 | break; | ||
474 | case TupleDefinitionType.MoveFile: | ||
475 | set.Add("InstallExecuteSequence/MoveFiles"); | ||
476 | break; | ||
477 | case TupleDefinitionType.MsiAssembly: | ||
478 | set.Add("AdvtExecuteSequence/MsiPublishAssemblies"); | ||
479 | set.Add("InstallExecuteSequence/MsiPublishAssemblies"); | ||
480 | set.Add("InstallExecuteSequence/MsiUnpublishAssemblies"); | ||
481 | break; | ||
482 | case TupleDefinitionType.MsiServiceConfig: | ||
483 | case TupleDefinitionType.MsiServiceConfigFailureActions: | ||
484 | set.Add("InstallExecuteSequence/MsiConfigureServices"); | ||
485 | break; | ||
486 | case TupleDefinitionType.ODBCDataSource: | ||
487 | case TupleDefinitionType.ODBCTranslator: | ||
488 | case TupleDefinitionType.ODBCDriver: | ||
489 | set.Add("InstallExecuteSequence/SetODBCFolders"); | ||
490 | set.Add("InstallExecuteSequence/InstallODBC"); | ||
491 | set.Add("InstallExecuteSequence/RemoveODBC"); | ||
492 | break; | ||
493 | case TupleDefinitionType.ProgId: | ||
494 | set.Add("AdvtExecuteSequence/RegisterProgIdInfo"); | ||
495 | set.Add("InstallExecuteSequence/RegisterProgIdInfo"); | ||
496 | set.Add("InstallExecuteSequence/UnregisterProgIdInfo"); | ||
497 | break; | ||
498 | case TupleDefinitionType.PublishComponent: | ||
499 | set.Add("AdvtExecuteSequence/PublishComponents"); | ||
500 | set.Add("InstallExecuteSequence/PublishComponents"); | ||
501 | set.Add("InstallExecuteSequence/UnpublishComponents"); | ||
502 | break; | ||
503 | case TupleDefinitionType.Registry: | ||
504 | case TupleDefinitionType.RemoveRegistry: | ||
505 | set.Add("InstallExecuteSequence/WriteRegistryValues"); | ||
506 | set.Add("InstallExecuteSequence/RemoveRegistryValues"); | ||
507 | break; | ||
508 | case TupleDefinitionType.RemoveFile: | ||
509 | set.Add("InstallExecuteSequence/RemoveFiles"); | ||
510 | break; | ||
511 | case TupleDefinitionType.SelfReg: | ||
512 | set.Add("InstallExecuteSequence/SelfRegModules"); | ||
513 | set.Add("InstallExecuteSequence/SelfUnregModules"); | ||
514 | break; | ||
515 | case TupleDefinitionType.ServiceControl: | ||
516 | set.Add("InstallExecuteSequence/StartServices"); | ||
517 | set.Add("InstallExecuteSequence/StopServices"); | ||
518 | set.Add("InstallExecuteSequence/DeleteServices"); | ||
519 | break; | ||
520 | case TupleDefinitionType.ServiceInstall: | ||
521 | set.Add("InstallExecuteSequence/InstallServices"); | ||
522 | break; | ||
523 | case TupleDefinitionType.Shortcut: | ||
524 | set.Add("AdvtExecuteSequence/CreateShortcuts"); | ||
525 | set.Add("InstallExecuteSequence/CreateShortcuts"); | ||
526 | set.Add("InstallExecuteSequence/RemoveShortcuts"); | ||
527 | break; | ||
528 | case TupleDefinitionType.TypeLib: | ||
529 | set.Add("InstallExecuteSequence/RegisterTypeLibraries"); | ||
530 | set.Add("InstallExecuteSequence/UnregisterTypeLibraries"); | ||
531 | break; | ||
532 | case TupleDefinitionType.Upgrade: | ||
533 | set.Add("InstallExecuteSequence/FindRelatedProducts"); | ||
534 | set.Add("InstallUISequence/FindRelatedProducts"); | ||
535 | |||
536 | // Only add the MigrateFeatureStates action if MigrateFeature attribute is set on | ||
537 | // at least one UpgradeVersion element. | ||
538 | if (this.Section.Tuples.OfType<UpgradeTuple>().Any(t => (t.Attributes & MsiInterop.MsidbUpgradeAttributesMigrateFeatures) == MsiInterop.MsidbUpgradeAttributesMigrateFeatures)) | ||
539 | { | ||
540 | set.Add("InstallExecuteSequence/MigrateFeatureStates"); | ||
541 | set.Add("InstallUISequence/MigrateFeatureStates"); | ||
542 | } | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | return set; | ||
548 | } | ||
549 | |||
550 | private IEnumerable<WixActionTuple> GetActions(SequenceTable sequence, string[] actionNames) | ||
551 | { | ||
552 | foreach (var action in WindowsInstallerStandard.StandardActions()) | ||
553 | { | ||
554 | if (action.SequenceTable == sequence && actionNames.Contains(action.Action)) | ||
555 | { | ||
556 | yield return action; | ||
557 | } | ||
558 | } | ||
559 | } | ||
560 | |||
561 | /// <summary> | ||
562 | /// Sequence an action before or after a standard action. | ||
563 | /// </summary> | ||
564 | /// <param name="actionRow">The action row to be sequenced.</param> | ||
565 | /// <param name="requiredActionRows">Collection of actions which must be included.</param> | ||
566 | private void SequenceActionRow(WixActionTuple actionRow, Dictionary<string, WixActionTuple> requiredActionRows) | ||
567 | { | ||
568 | var after = false; | ||
569 | |||
570 | if (actionRow.After != null) | ||
571 | { | ||
572 | after = true; | ||
573 | } | ||
574 | else if (actionRow.Before == null) | ||
575 | { | ||
576 | throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); | ||
577 | } | ||
578 | |||
579 | var parentActionName = (after ? actionRow.After : actionRow.Before); | ||
580 | var parentActionKey = actionRow.SequenceTable.ToString() + "/" + parentActionName; | ||
581 | |||
582 | if (!requiredActionRows.TryGetValue(parentActionKey, out var parentActionRow)) | ||
583 | { | ||
584 | // If the missing parent action is a standard action (with a suggested sequence number), add it. | ||
585 | if (this.StandardActionsById.TryGetValue(parentActionKey, out parentActionRow)) | ||
586 | { | ||
587 | // Create a clone to avoid modifying the static copy of the object. | ||
588 | // TODO: consider this: parentActionRow = parentActionRow.Clone(); | ||
589 | |||
590 | requiredActionRows.Add(parentActionRow.Id.Id, parentActionRow); | ||
591 | } | ||
592 | else | ||
593 | { | ||
594 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName)); | ||
595 | } | ||
596 | } | ||
597 | else if (actionRow == parentActionRow || this.ContainsChildActionRow(actionRow, parentActionRow)) // cycle detected | ||
598 | { | ||
599 | throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action)); | ||
600 | } | ||
601 | |||
602 | // Add this action to the appropriate list of dependent action rows. | ||
603 | var relativeActions = this.GetRelativeActions(parentActionRow); | ||
604 | var relatedRows = (after ? relativeActions.NextActions : relativeActions.PreviousActions); | ||
605 | relatedRows.Add(actionRow); | ||
606 | } | ||
607 | |||
608 | private bool ContainsChildActionRow(WixActionTuple childTuple, WixActionTuple parentTuple) | ||
609 | { | ||
610 | var result = false; | ||
611 | |||
612 | if (this.RelativeActionsForActions.TryGetValue(childTuple.Id.Id, out var relativeActions)) | ||
613 | { | ||
614 | result = relativeActions.NextActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id) || | ||
615 | relativeActions.PreviousActions.Any(a => a.SequenceTable == parentTuple.SequenceTable && a.Id.Id == parentTuple.Id.Id); | ||
616 | } | ||
617 | |||
618 | return result; | ||
619 | } | ||
620 | |||
621 | private RelativeActions GetRelativeActions(WixActionTuple action) | ||
622 | { | ||
623 | if (!this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var relativeActions)) | ||
624 | { | ||
625 | relativeActions = new RelativeActions(); | ||
626 | this.RelativeActionsForActions.Add(action.Id.Id, relativeActions); | ||
627 | } | ||
628 | |||
629 | return relativeActions; | ||
630 | } | ||
631 | |||
632 | private RelativeActions GetAllRelativeActionsForSequenceType(SequenceTable sequenceType, WixActionTuple action) | ||
633 | { | ||
634 | var relativeActions = new RelativeActions(); | ||
635 | |||
636 | if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives)) | ||
637 | { | ||
638 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, relativeActions.PreviousActions); | ||
639 | |||
640 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, relativeActions.NextActions); | ||
641 | } | ||
642 | |||
643 | return relativeActions; | ||
644 | } | ||
645 | |||
646 | private void RecurseRelativeActionsForSequenceType(SequenceTable sequenceType, List<WixActionTuple> actions, List<WixActionTuple> visitedActions) | ||
647 | { | ||
648 | foreach (var action in actions.Where(a => a.SequenceTable == sequenceType)) | ||
649 | { | ||
650 | if (this.RelativeActionsForActions.TryGetValue(action.Id.Id, out var actionRelatives)) | ||
651 | { | ||
652 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.PreviousActions, visitedActions); | ||
653 | } | ||
654 | |||
655 | visitedActions.Add(action); | ||
656 | |||
657 | if (actionRelatives != null) | ||
658 | { | ||
659 | this.RecurseRelativeActionsForSequenceType(sequenceType, actionRelatives.NextActions, visitedActions); | ||
660 | } | ||
661 | } | ||
662 | } | ||
663 | |||
664 | private class RelativeActions | ||
665 | { | ||
666 | public List<WixActionTuple> PreviousActions { get; } = new List<WixActionTuple>(); | ||
667 | |||
668 | public List<WixActionTuple> NextActions { get; } = new List<WixActionTuple>(); | ||
669 | } | ||
670 | } | ||
671 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs index 7da32206..9579e0f8 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateControlTextCommand.cs | |||
@@ -1,6 +1,6 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.IO; | 6 | using System.IO; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs index 20058597..030bc4cc 100644 --- a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateFileFacadesCommand.cs | |||
@@ -1,10 +1,9 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.WindowsInstaller.Databases | 3 | namespace WixToolset.Core.WindowsInstaller.Bind |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.Collections.Specialized; | ||
8 | using System.ComponentModel; | 7 | using System.ComponentModel; |
9 | using System.Globalization; | 8 | using System.Globalization; |
10 | using System.IO; | 9 | using System.IO; |
@@ -14,7 +13,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
14 | using WixToolset.Clr.Interop; | 13 | using WixToolset.Clr.Interop; |
15 | using WixToolset.Core.Bind; | 14 | using WixToolset.Core.Bind; |
16 | using WixToolset.Data; | 15 | using WixToolset.Data; |
17 | using WixToolset.Data.Rows; | ||
18 | using WixToolset.Data.Tuples; | 16 | using WixToolset.Data.Tuples; |
19 | using WixToolset.Msi; | 17 | using WixToolset.Msi; |
20 | 18 | ||
@@ -23,13 +21,16 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
23 | /// </summary> | 21 | /// </summary> |
24 | internal class UpdateFileFacadesCommand | 22 | internal class UpdateFileFacadesCommand |
25 | { | 23 | { |
26 | public IEnumerable<FileFacade> FileFacades { private get; set; } | 24 | public UpdateFileFacadesCommand(IntermediateSection section) |
25 | { | ||
26 | this.Section = section; | ||
27 | } | ||
27 | 28 | ||
28 | public IEnumerable<FileFacade> UpdateFileFacades { private get; set; } | 29 | private IntermediateSection Section { get; } |
29 | 30 | ||
30 | public string ModularizationGuid { private get; set; } | 31 | public IEnumerable<FileFacade> FileFacades { private get; set; } |
31 | 32 | ||
32 | public Output Output { private get; set; } | 33 | public IEnumerable<FileFacade> UpdateFileFacades { private get; set; } |
33 | 34 | ||
34 | public bool OverwriteHash { private get; set; } | 35 | public bool OverwriteHash { private get; set; } |
35 | 36 | ||
@@ -47,6 +48,12 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
47 | 48 | ||
48 | private void UpdateFileFacade(FileFacade file) | 49 | private void UpdateFileFacade(FileFacade file) |
49 | { | 50 | { |
51 | var assemblyNameTuples = new Dictionary<string, MsiAssemblyNameTuple>(); | ||
52 | foreach (var assemblyTuple in this.Section.Tuples.OfType<MsiAssemblyNameTuple>()) | ||
53 | { | ||
54 | assemblyNameTuples.Add(assemblyTuple.Component_ + "/" + assemblyTuple.Name, assemblyTuple); | ||
55 | } | ||
56 | |||
50 | FileInfo fileInfo = null; | 57 | FileInfo fileInfo = null; |
51 | try | 58 | try |
52 | { | 59 | { |
@@ -149,9 +156,8 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
149 | 156 | ||
150 | if (null == file.Hash) | 157 | if (null == file.Hash) |
151 | { | 158 | { |
152 | //Table msiFileHashTable = this.Output.EnsureTable(this.TableDefinitions["MsiFileHash"]); | 159 | file.Hash = new MsiFileHashTuple(file.File.SourceLineNumbers, file.File.Id); |
153 | //file.Hash = msiFileHashTable.CreateRow(file.File.SourceLineNumbers); | 160 | this.Section.Tuples.Add(file.Hash); |
154 | throw new NotImplementedException(); | ||
155 | } | 161 | } |
156 | 162 | ||
157 | file.Hash.File_ = file.File.File; | 163 | file.Hash.File_ = file.File.File; |
@@ -198,13 +204,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
198 | { | 204 | { |
199 | if (!String.IsNullOrEmpty(file.File.Version)) | 205 | if (!String.IsNullOrEmpty(file.File.Version)) |
200 | { | 206 | { |
201 | string key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)); | 207 | var key = String.Format(CultureInfo.InvariantCulture, "fileversion.{0}", file.File.File); |
202 | this.VariableCache[key] = file.File.Version; | 208 | this.VariableCache[key] = file.File.Version; |
203 | } | 209 | } |
204 | 210 | ||
205 | if (!String.IsNullOrEmpty(file.File.Language)) | 211 | if (!String.IsNullOrEmpty(file.File.Language)) |
206 | { | 212 | { |
207 | string key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", Common.Demodularize(this.Output.Type, ModularizationGuid, file.File.File)); | 213 | var key = String.Format(CultureInfo.InvariantCulture, "filelanguage.{0}", file.File.File); |
208 | this.VariableCache[key] = file.File.Language; | 214 | this.VariableCache[key] = file.File.Language; |
209 | } | 215 | } |
210 | } | 216 | } |
@@ -214,14 +220,13 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
214 | if (FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType) | 220 | if (FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType) |
215 | { | 221 | { |
216 | bool targetNetfx1 = false; | 222 | bool targetNetfx1 = false; |
217 | StringDictionary assemblyNameValues = new StringDictionary(); | 223 | var assemblyNameValues = new Dictionary<string, string>(); |
218 | 224 | ||
219 | ClrInterop.IReferenceIdentity referenceIdentity = null; | ||
220 | Guid referenceIdentityGuid = ClrInterop.ReferenceIdentityGuid; | 225 | Guid referenceIdentityGuid = ClrInterop.ReferenceIdentityGuid; |
221 | uint result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out referenceIdentity); | 226 | var result = ClrInterop.GetAssemblyIdentityFromFile(fileInfo.FullName, ref referenceIdentityGuid, out var referenceIdentity); |
222 | if (0 == result && null != referenceIdentity) | 227 | if (0 == result && null != referenceIdentity) |
223 | { | 228 | { |
224 | string imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion"); | 229 | var imageRuntimeVersion = referenceIdentity.GetAttribute(null, "ImageRuntimeVersion"); |
225 | if (null != imageRuntimeVersion) | 230 | if (null != imageRuntimeVersion) |
226 | { | 231 | { |
227 | targetNetfx1 = imageRuntimeVersion.StartsWith("v1", StringComparison.OrdinalIgnoreCase); | 232 | targetNetfx1 = imageRuntimeVersion.StartsWith("v1", StringComparison.OrdinalIgnoreCase); |
@@ -269,15 +274,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
269 | return; | 274 | return; |
270 | } | 275 | } |
271 | 276 | ||
272 | Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); | 277 | if (assemblyNameValues.TryGetValue("name", out var value)) |
273 | if (assemblyNameValues.ContainsKey("name")) | ||
274 | { | 278 | { |
275 | this.SetMsiAssemblyName(assemblyNameTable, file, "name", assemblyNameValues["name"]); | 279 | this.SetMsiAssemblyName(assemblyNameTuples, file, "name", value); |
276 | } | 280 | } |
277 | 281 | ||
278 | if (!String.IsNullOrEmpty(version)) | 282 | if (!String.IsNullOrEmpty(version)) |
279 | { | 283 | { |
280 | this.SetMsiAssemblyName(assemblyNameTable, file, "fileVersion", version); | 284 | this.SetMsiAssemblyName(assemblyNameTuples, file, "fileVersion", version); |
281 | } | 285 | } |
282 | 286 | ||
283 | if (assemblyNameValues.ContainsKey("version")) | 287 | if (assemblyNameValues.ContainsKey("version")) |
@@ -303,33 +307,33 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
303 | } | 307 | } |
304 | } | 308 | } |
305 | 309 | ||
306 | this.SetMsiAssemblyName(assemblyNameTable, file, "version", assemblyVersion); | 310 | this.SetMsiAssemblyName(assemblyNameTuples, file, "version", assemblyVersion); |
307 | } | 311 | } |
308 | 312 | ||
309 | if (assemblyNameValues.ContainsKey("culture")) | 313 | if (assemblyNameValues.ContainsKey("culture")) |
310 | { | 314 | { |
311 | this.SetMsiAssemblyName(assemblyNameTable, file, "culture", assemblyNameValues["culture"]); | 315 | this.SetMsiAssemblyName(assemblyNameTuples, file, "culture", assemblyNameValues["culture"]); |
312 | } | 316 | } |
313 | 317 | ||
314 | if (assemblyNameValues.ContainsKey("publicKeyToken")) | 318 | if (assemblyNameValues.ContainsKey("publicKeyToken")) |
315 | { | 319 | { |
316 | this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]); | 320 | this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", assemblyNameValues["publicKeyToken"]); |
317 | } | 321 | } |
318 | 322 | ||
319 | if (!String.IsNullOrEmpty(file.WixFile.ProcessorArchitecture)) | 323 | if (!String.IsNullOrEmpty(file.WixFile.ProcessorArchitecture)) |
320 | { | 324 | { |
321 | this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", file.WixFile.ProcessorArchitecture); | 325 | this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", file.WixFile.ProcessorArchitecture); |
322 | } | 326 | } |
323 | 327 | ||
324 | if (assemblyNameValues.ContainsKey("processorArchitecture")) | 328 | if (assemblyNameValues.ContainsKey("processorArchitecture")) |
325 | { | 329 | { |
326 | this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]); | 330 | this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", assemblyNameValues["processorArchitecture"]); |
327 | } | 331 | } |
328 | 332 | ||
329 | // add the assembly name to the information cache | 333 | // add the assembly name to the information cache |
330 | if (null != this.VariableCache) | 334 | if (null != this.VariableCache) |
331 | { | 335 | { |
332 | string fileId = Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File); | 336 | string fileId = file.File.File; |
333 | string key = String.Concat("assemblyfullname.", fileId); | 337 | string key = String.Concat("assemblyfullname.", fileId); |
334 | string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]); | 338 | string assemblyName = String.Concat(assemblyNameValues["name"], ", version=", assemblyNameValues["version"], ", culture=", assemblyNameValues["culture"], ", publicKeyToken=", String.IsNullOrEmpty(assemblyNameValues["publicKeyToken"]) ? "null" : assemblyNameValues["publicKeyToken"]); |
335 | if (assemblyNameValues.ContainsKey("processorArchitecture")) | 339 | if (assemblyNameValues.ContainsKey("processorArchitecture")) |
@@ -437,30 +441,29 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
437 | Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source), "manifest", xe.Message)); | 441 | Messaging.Instance.OnMessage(WixErrors.InvalidXml(new SourceLineNumber(fileManifest.WixFile.Source), "manifest", xe.Message)); |
438 | } | 442 | } |
439 | 443 | ||
440 | Table assemblyNameTable = this.Output.EnsureTable(this.TableDefinitions["MsiAssemblyName"]); | ||
441 | if (!String.IsNullOrEmpty(win32Name)) | 444 | if (!String.IsNullOrEmpty(win32Name)) |
442 | { | 445 | { |
443 | this.SetMsiAssemblyName(assemblyNameTable, file, "name", win32Name); | 446 | this.SetMsiAssemblyName(assemblyNameTuples, file, "name", win32Name); |
444 | } | 447 | } |
445 | 448 | ||
446 | if (!String.IsNullOrEmpty(win32Version)) | 449 | if (!String.IsNullOrEmpty(win32Version)) |
447 | { | 450 | { |
448 | this.SetMsiAssemblyName(assemblyNameTable, file, "version", win32Version); | 451 | this.SetMsiAssemblyName(assemblyNameTuples, file, "version", win32Version); |
449 | } | 452 | } |
450 | 453 | ||
451 | if (!String.IsNullOrEmpty(win32Type)) | 454 | if (!String.IsNullOrEmpty(win32Type)) |
452 | { | 455 | { |
453 | this.SetMsiAssemblyName(assemblyNameTable, file, "type", win32Type); | 456 | this.SetMsiAssemblyName(assemblyNameTuples, file, "type", win32Type); |
454 | } | 457 | } |
455 | 458 | ||
456 | if (!String.IsNullOrEmpty(win32ProcessorArchitecture)) | 459 | if (!String.IsNullOrEmpty(win32ProcessorArchitecture)) |
457 | { | 460 | { |
458 | this.SetMsiAssemblyName(assemblyNameTable, file, "processorArchitecture", win32ProcessorArchitecture); | 461 | this.SetMsiAssemblyName(assemblyNameTuples, file, "processorArchitecture", win32ProcessorArchitecture); |
459 | } | 462 | } |
460 | 463 | ||
461 | if (!String.IsNullOrEmpty(win32PublicKeyToken)) | 464 | if (!String.IsNullOrEmpty(win32PublicKeyToken)) |
462 | { | 465 | { |
463 | this.SetMsiAssemblyName(assemblyNameTable, file, "publicKeyToken", win32PublicKeyToken); | 466 | this.SetMsiAssemblyName(assemblyNameTuples, file, "publicKeyToken", win32PublicKeyToken); |
464 | } | 467 | } |
465 | } | 468 | } |
466 | } | 469 | } |
@@ -469,11 +472,11 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
469 | /// Set an MsiAssemblyName row. If it was directly authored, override the value, otherwise | 472 | /// Set an MsiAssemblyName row. If it was directly authored, override the value, otherwise |
470 | /// create a new row. | 473 | /// create a new row. |
471 | /// </summary> | 474 | /// </summary> |
472 | /// <param name="assemblyNameTable">MsiAssemblyName table.</param> | 475 | /// <param name="assemblyNameTuples">MsiAssemblyName table.</param> |
473 | /// <param name="file">FileFacade containing the assembly read for the MsiAssemblyName row.</param> | 476 | /// <param name="file">FileFacade containing the assembly read for the MsiAssemblyName row.</param> |
474 | /// <param name="name">MsiAssemblyName name.</param> | 477 | /// <param name="name">MsiAssemblyName name.</param> |
475 | /// <param name="value">MsiAssemblyName value.</param> | 478 | /// <param name="value">MsiAssemblyName value.</param> |
476 | private void SetMsiAssemblyName(Table assemblyNameTable, FileFacade file, string name, string value) | 479 | private void SetMsiAssemblyName(Dictionary<string, MsiAssemblyNameTuple> assemblyNameTuples, FileFacade file, string name, string value) |
477 | { | 480 | { |
478 | // check for null value (this can occur when grabbing the file version from an assembly without one) | 481 | // check for null value (this can occur when grabbing the file version from an assembly without one) |
479 | if (String.IsNullOrEmpty(value)) | 482 | if (String.IsNullOrEmpty(value)) |
@@ -482,18 +485,6 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
482 | } | 485 | } |
483 | else | 486 | else |
484 | { | 487 | { |
485 | Row assemblyNameRow = null; | ||
486 | |||
487 | // override directly authored value | ||
488 | foreach (Row row in assemblyNameTable.Rows) | ||
489 | { | ||
490 | if ((string)row[0] == file.File.Component_ && (string)row[1] == name) | ||
491 | { | ||
492 | assemblyNameRow = row; | ||
493 | break; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail. | 488 | // if the assembly will be GAC'd and the name in the file table doesn't match the name in the MsiAssemblyName table, error because the install will fail. |
498 | if ("name" == name && FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType && | 489 | if ("name" == name && FileAssemblyType.DotNetAssembly == file.WixFile.AssemblyType && |
499 | String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) && | 490 | String.IsNullOrEmpty(file.WixFile.File_AssemblyApplication) && |
@@ -502,17 +493,14 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
502 | Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value)); | 493 | Messaging.Instance.OnMessage(WixErrors.GACAssemblyIdentityWarning(file.File.SourceLineNumbers, Path.GetFileNameWithoutExtension(file.File.LongFileName), value)); |
503 | } | 494 | } |
504 | 495 | ||
505 | if (null == assemblyNameRow) | 496 | // override directly authored value |
497 | var lookup = String.Concat(file.File.Component_, "/", name); | ||
498 | if (assemblyNameTuples.TryGetValue(lookup, out var assemblyNameRow)) | ||
506 | { | 499 | { |
507 | throw new NotImplementedException(); | 500 | assemblyNameRow = new MsiAssemblyNameTuple(file.File.SourceLineNumbers); |
508 | #if TODO | 501 | assemblyNameRow.Component_ = file.File.Component_; |
509 | assemblyNameRow = assemblyNameTable.CreateRow(file.File.SourceLineNumbers); | 502 | assemblyNameRow.Name = name; |
510 | assemblyNameRow[0] = file.File.Component_; | 503 | assemblyNameRow.Value = value; |
511 | assemblyNameRow[1] = name; | ||
512 | assemblyNameRow[2] = value; | ||
513 | |||
514 | // put the MsiAssemblyName row in the same section as the related File row | ||
515 | assemblyNameRow.SectionId = file.File.SectionId; | ||
516 | 504 | ||
517 | if (null == file.AssemblyNames) | 505 | if (null == file.AssemblyNames) |
518 | { | 506 | { |
@@ -520,17 +508,15 @@ namespace WixToolset.Core.WindowsInstaller.Databases | |||
520 | } | 508 | } |
521 | 509 | ||
522 | file.AssemblyNames.Add(assemblyNameRow); | 510 | file.AssemblyNames.Add(assemblyNameRow); |
523 | #endif | 511 | this.Section.Tuples.Add(assemblyNameRow); |
524 | } | ||
525 | else | ||
526 | { | ||
527 | assemblyNameRow[2] = value; | ||
528 | } | 512 | } |
529 | 513 | ||
514 | assemblyNameRow.Value = value; | ||
515 | |||
530 | if (this.VariableCache != null) | 516 | if (this.VariableCache != null) |
531 | { | 517 | { |
532 | string key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, Common.Demodularize(this.Output.Type, this.ModularizationGuid, file.File.File)).ToLowerInvariant(); | 518 | var key = String.Format(CultureInfo.InvariantCulture, "assembly{0}.{1}", name, file.File.File).ToLowerInvariant(); |
533 | this.VariableCache[key] = (string)assemblyNameRow[2]; | 519 | this.VariableCache[key] = value; |
534 | } | 520 | } |
535 | } | 521 | } |
536 | } | 522 | } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs new file mode 100644 index 00000000..db74eda5 --- /dev/null +++ b/src/WixToolset.Core.WindowsInstaller/Bind/UpdateMediaSequencesCommand.cs | |||
@@ -0,0 +1,126 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core.WindowsInstaller.Bind | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Linq; | ||
8 | using WixToolset.Core.Bind; | ||
9 | using WixToolset.Data; | ||
10 | using WixToolset.Data.Rows; | ||
11 | using WixToolset.Data.Tuples; | ||
12 | |||
13 | internal class UpdateMediaSequencesCommand | ||
14 | { | ||
15 | public UpdateMediaSequencesCommand(Output output, List<FileFacade> fileFacades, Dictionary<int, MediaTuple> assignedMediaRows) | ||
16 | { | ||
17 | this.Output = output; | ||
18 | this.FileFacades = fileFacades; | ||
19 | } | ||
20 | |||
21 | private Output Output { get; } | ||
22 | |||
23 | private List<FileFacade> FileFacades { get; } | ||
24 | |||
25 | public void Execute() | ||
26 | { | ||
27 | var fileRows = new RowDictionary<FileRow>(this.Output.Tables["File"]); | ||
28 | var mediaRows = new RowDictionary<MediaRow>(this.Output.Tables["Media"]); | ||
29 | |||
30 | // Calculate sequence numbers and media disk id layout for all file media information objects. | ||
31 | if (OutputType.Module == this.Output.Type) | ||
32 | { | ||
33 | var lastSequence = 0; | ||
34 | |||
35 | // Order by Component to group the files by directory. | ||
36 | var optimized = this.OptimizedFileFacades(); | ||
37 | foreach (var fileId in optimized.Select(f => f.File.File)) | ||
38 | { | ||
39 | var fileRow = fileRows.Get(fileId); | ||
40 | fileRow.Sequence = ++lastSequence; | ||
41 | } | ||
42 | } | ||
43 | else | ||
44 | { | ||
45 | int lastSequence = 0; | ||
46 | MediaRow mediaRow = null; | ||
47 | Dictionary<int, List<FileFacade>> patchGroups = new Dictionary<int, List<FileFacade>>(); | ||
48 | |||
49 | // sequence the non-patch-added files | ||
50 | var optimized = this.OptimizedFileFacades(); | ||
51 | foreach (FileFacade facade in optimized) | ||
52 | { | ||
53 | if (null == mediaRow) | ||
54 | { | ||
55 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
56 | if (OutputType.Patch == this.Output.Type) | ||
57 | { | ||
58 | // patch Media cannot start at zero | ||
59 | lastSequence = mediaRow.LastSequence; | ||
60 | } | ||
61 | } | ||
62 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
63 | { | ||
64 | mediaRow.LastSequence = lastSequence; | ||
65 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
66 | } | ||
67 | |||
68 | if (0 < facade.WixFile.PatchGroup) | ||
69 | { | ||
70 | if (patchGroups.TryGetValue(facade.WixFile.PatchGroup, out var patchGroup)) | ||
71 | { | ||
72 | patchGroup = new List<FileFacade>(); | ||
73 | patchGroups.Add(facade.WixFile.PatchGroup, patchGroup); | ||
74 | } | ||
75 | |||
76 | patchGroup.Add(facade); | ||
77 | } | ||
78 | else | ||
79 | { | ||
80 | var fileRow = fileRows.Get(facade.File.File); | ||
81 | fileRow.Sequence = ++lastSequence; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | if (null != mediaRow) | ||
86 | { | ||
87 | mediaRow.LastSequence = lastSequence; | ||
88 | mediaRow = null; | ||
89 | } | ||
90 | |||
91 | // sequence the patch-added files | ||
92 | foreach (var patchGroup in patchGroups.Values) | ||
93 | { | ||
94 | foreach (var facade in patchGroup) | ||
95 | { | ||
96 | if (null == mediaRow) | ||
97 | { | ||
98 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
99 | } | ||
100 | else if (mediaRow.DiskId != facade.WixFile.DiskId) | ||
101 | { | ||
102 | mediaRow.LastSequence = lastSequence; | ||
103 | mediaRow = mediaRows.Get(facade.WixFile.DiskId); | ||
104 | } | ||
105 | |||
106 | var fileRow = fileRows.Get(facade.File.File); | ||
107 | fileRow.Sequence = ++lastSequence; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (null != mediaRow) | ||
112 | { | ||
113 | mediaRow.LastSequence = lastSequence; | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | private IEnumerable<FileFacade> OptimizedFileFacades() | ||
119 | { | ||
120 | // TODO: Sort these facades even smarter by directory path and component id | ||
121 | // and maybe file size or file extension and other creative ideas to | ||
122 | // get optimal install speed out of MSI. | ||
123 | return this.FileFacades.OrderBy(f => f.File.Component_); | ||
124 | } | ||
125 | } | ||
126 | } | ||
diff --git a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs index 72c876e0..58384325 100644 --- a/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Inscribe/InscribeMsiPackageCommand.cs | |||
@@ -18,7 +18,7 @@ namespace WixToolset.Core.WindowsInstaller.Inscribe | |||
18 | public InscribeMsiPackageCommand(IInscribeContext context) | 18 | public InscribeMsiPackageCommand(IInscribeContext context) |
19 | { | 19 | { |
20 | this.Context = context; | 20 | this.Context = context; |
21 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 21 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
22 | } | 22 | } |
23 | 23 | ||
24 | private IInscribeContext Context { get; } | 24 | private IInscribeContext Context { get; } |
diff --git a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs index 3e40a51f..17617dbc 100644 --- a/src/WixToolset.Core.WindowsInstaller/MstBackend.cs +++ b/src/WixToolset.Core.WindowsInstaller/MstBackend.cs | |||
@@ -3,7 +3,6 @@ | |||
3 | namespace WixToolset.Core.WindowsInstaller | 3 | namespace WixToolset.Core.WindowsInstaller |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using WixToolset.Core.WindowsInstaller.Databases; | ||
7 | using WixToolset.Core.WindowsInstaller.Unbind; | 6 | using WixToolset.Core.WindowsInstaller.Unbind; |
8 | using WixToolset.Data; | 7 | using WixToolset.Data; |
9 | using WixToolset.Data.Bind; | 8 | using WixToolset.Data.Bind; |
diff --git a/src/WixToolset.Core.WindowsInstaller/Patch.cs b/src/WixToolset.Core.WindowsInstaller/Patch.cs index f4dac6e6..8e617fdb 100644 --- a/src/WixToolset.Core.WindowsInstaller/Patch.cs +++ b/src/WixToolset.Core.WindowsInstaller/Patch.cs | |||
@@ -29,7 +29,7 @@ namespace WixToolset.Data | |||
29 | public Patch() | 29 | public Patch() |
30 | { | 30 | { |
31 | this.inspectorExtensions = new List<IInspectorExtension>(); | 31 | this.inspectorExtensions = new List<IInspectorExtension>(); |
32 | this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); | 32 | this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandardInternal.GetTableDefinitions()); |
33 | } | 33 | } |
34 | 34 | ||
35 | /// <summary> | 35 | /// <summary> |
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs index 15445bc8..9cd7b775 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindDatabaseCommand.cs | |||
@@ -27,7 +27,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
27 | this.SuppressDemodularization = suppressDemodularization; | 27 | this.SuppressDemodularization = suppressDemodularization; |
28 | this.SkipSummaryInfo = skipSummaryInfo; | 28 | this.SkipSummaryInfo = skipSummaryInfo; |
29 | 29 | ||
30 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 30 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
31 | } | 31 | } |
32 | 32 | ||
33 | public Messaging Messaging { get; } | 33 | public Messaging Messaging { get; } |
diff --git a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs index c0eda9c7..7eb81ac7 100644 --- a/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs +++ b/src/WixToolset.Core.WindowsInstaller/Unbind/UnbindTranformCommand.cs | |||
@@ -4,16 +4,13 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | 6 | using System.Collections; |
7 | using System.Collections.Generic; | ||
8 | using System.ComponentModel; | 7 | using System.ComponentModel; |
9 | using System.Globalization; | 8 | using System.Globalization; |
10 | using System.IO; | 9 | using System.IO; |
11 | using System.Linq; | 10 | using System.Linq; |
12 | using System.Text.RegularExpressions; | ||
13 | using WixToolset.Core.Native; | 11 | using WixToolset.Core.Native; |
14 | using WixToolset.Core.WindowsInstaller.Databases; | 12 | using WixToolset.Core.WindowsInstaller.Bind; |
15 | using WixToolset.Data; | 13 | using WixToolset.Data; |
16 | using WixToolset.Data.Rows; | ||
17 | using WixToolset.Extensibility; | 14 | using WixToolset.Extensibility; |
18 | using WixToolset.Msi; | 15 | using WixToolset.Msi; |
19 | 16 | ||
@@ -26,7 +23,7 @@ namespace WixToolset.Core.WindowsInstaller.Unbind | |||
26 | this.ExportBasePath = exportBasePath; | 23 | this.ExportBasePath = exportBasePath; |
27 | this.IntermediateFolder = intermediateFolder; | 24 | this.IntermediateFolder = intermediateFolder; |
28 | 25 | ||
29 | this.TableDefinitions = WindowsInstallerStandard.GetTableDefinitions(); | 26 | this.TableDefinitions = WindowsInstallerStandardInternal.GetTableDefinitions(); |
30 | } | 27 | } |
31 | 28 | ||
32 | private Messaging Messaging { get; } | 29 | private Messaging Messaging { get; } |
diff --git a/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs b/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs index 7de40fb8..7e7c21b1 100644 --- a/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs +++ b/src/WixToolset.Core/Bind/ExtractEmbeddedFilesCommand.cs | |||
@@ -11,7 +11,12 @@ namespace WixToolset.Core.Bind | |||
11 | 11 | ||
12 | public class ExtractEmbeddedFilesCommand | 12 | public class ExtractEmbeddedFilesCommand |
13 | { | 13 | { |
14 | public IEnumerable<IExpectedExtractFile> FilesWithEmbeddedFiles { private get; set; } | 14 | public ExtractEmbeddedFilesCommand(IEnumerable<IExpectedExtractFile> embeddedFiles) |
15 | { | ||
16 | this.FilesWithEmbeddedFiles = embeddedFiles; | ||
17 | } | ||
18 | |||
19 | private IEnumerable<IExpectedExtractFile> FilesWithEmbeddedFiles { get; } | ||
15 | 20 | ||
16 | public void Execute() | 21 | public void Execute() |
17 | { | 22 | { |
@@ -28,10 +33,10 @@ namespace WixToolset.Core.Bind | |||
28 | // a .wixlib embedded in a WixExtension). | 33 | // a .wixlib embedded in a WixExtension). |
29 | if ("embeddedresource" == baseUri.Scheme) | 34 | if ("embeddedresource" == baseUri.Scheme) |
30 | { | 35 | { |
31 | string assemblyPath = Path.GetFullPath(baseUri.LocalPath); | 36 | var assemblyPath = Path.GetFullPath(baseUri.LocalPath); |
32 | string resourceName = baseUri.Fragment.TrimStart('#'); | 37 | var resourceName = baseUri.Fragment.TrimStart('#'); |
33 | 38 | ||
34 | Assembly assembly = Assembly.LoadFile(assemblyPath); | 39 | var assembly = Assembly.LoadFile(assemblyPath); |
35 | stream = assembly.GetManifestResourceStream(resourceName); | 40 | stream = assembly.GetManifestResourceStream(resourceName); |
36 | } | 41 | } |
37 | else // normal file (usually a binary .wixlib on disk). | 42 | else // normal file (usually a binary .wixlib on disk). |
@@ -39,7 +44,7 @@ namespace WixToolset.Core.Bind | |||
39 | stream = File.OpenRead(baseUri.LocalPath); | 44 | stream = File.OpenRead(baseUri.LocalPath); |
40 | } | 45 | } |
41 | 46 | ||
42 | using (FileStructure fs = FileStructure.Read(stream)) | 47 | using (var fs = FileStructure.Read(stream)) |
43 | { | 48 | { |
44 | var uniqueIndicies = new SortedSet<int>(); | 49 | var uniqueIndicies = new SortedSet<int>(); |
45 | 50 | ||
diff --git a/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs b/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs index d05135cf..4585b71a 100644 --- a/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs +++ b/src/WixToolset.Core/Bind/ResolveDelayedFieldsCommand.cs | |||
@@ -12,25 +12,28 @@ namespace WixToolset.Core.Bind | |||
12 | /// Resolves the fields which had variables that needed to be resolved after the file information | 12 | /// Resolves the fields which had variables that needed to be resolved after the file information |
13 | /// was loaded. | 13 | /// was loaded. |
14 | /// </summary> | 14 | /// </summary> |
15 | public class ResolveDelayedFieldsCommand : ICommand | 15 | public class ResolveDelayedFieldsCommand |
16 | { | 16 | { |
17 | public OutputType OutputType { private get; set;} | 17 | /// <summary> |
18 | 18 | /// Resolve delayed fields. | |
19 | public IEnumerable<IDelayedField> DelayedFields { private get; set;} | 19 | /// </summary> |
20 | /// <param name="delayedFields">The fields which had resolution delayed.</param> | ||
21 | /// <param name="variableCache">The file information to use when resolving variables.</param> | ||
22 | public ResolveDelayedFieldsCommand(IEnumerable<IDelayedField> delayedFields, Dictionary<string, string> variableCache) | ||
23 | { | ||
24 | this.DelayedFields = delayedFields; | ||
25 | this.VariableCache = variableCache; | ||
26 | } | ||
20 | 27 | ||
21 | public IDictionary<string, string> VariableCache { private get; set; } | 28 | private IEnumerable<IDelayedField> DelayedFields { get;} |
22 | 29 | ||
23 | public string ModularizationGuid { private get; set; } | 30 | private IDictionary<string, string> VariableCache { get; } |
24 | 31 | ||
25 | /// <param name="output">Internal representation of the msi database to operate upon.</param> | ||
26 | /// <param name="delayedFields">The fields which had resolution delayed.</param> | ||
27 | /// <param name="variableCache">The file information to use when resolving variables.</param> | ||
28 | /// <param name="modularizationGuid">The modularization guid (used in case of a merge module).</param> | ||
29 | public void Execute() | 32 | public void Execute() |
30 | { | 33 | { |
31 | var deferredFields = new List<IDelayedField>(); | 34 | var deferredFields = new List<IDelayedField>(); |
32 | 35 | ||
33 | foreach (IDelayedField delayedField in this.DelayedFields) | 36 | foreach (var delayedField in this.DelayedFields) |
34 | { | 37 | { |
35 | try | 38 | try |
36 | { | 39 | { |
@@ -42,7 +45,7 @@ namespace WixToolset.Core.Bind | |||
42 | var value = WixVariableResolver.ResolveDelayedVariables(propertyRow.SourceLineNumbers, delayedField.Field.AsString(), this.VariableCache); | 45 | var value = WixVariableResolver.ResolveDelayedVariables(propertyRow.SourceLineNumbers, delayedField.Field.AsString(), this.VariableCache); |
43 | 46 | ||
44 | // update the variable cache with the new value | 47 | // update the variable cache with the new value |
45 | var key = String.Concat("property.", Common.Demodularize(this.OutputType, this.ModularizationGuid, (string)propertyRow[0])); | 48 | var key = String.Concat("property.", propertyRow.AsString(0)); |
46 | this.VariableCache[key] = value; | 49 | this.VariableCache[key] = value; |
47 | 50 | ||
48 | // update the field data | 51 | // update the field data |
@@ -62,43 +65,31 @@ namespace WixToolset.Core.Bind | |||
62 | 65 | ||
63 | // add specialization for ProductVersion fields | 66 | // add specialization for ProductVersion fields |
64 | string keyProductVersion = "property.ProductVersion"; | 67 | string keyProductVersion = "property.ProductVersion"; |
65 | if (this.VariableCache.ContainsKey(keyProductVersion)) | 68 | if (this.VariableCache.TryGetValue(keyProductVersion, out var versionValue) && Version.TryParse(versionValue, out Version productVersion)) |
66 | { | 69 | { |
67 | string value = this.VariableCache[keyProductVersion]; | 70 | // Don't add the variable if it already exists (developer defined a property with the same name). |
68 | Version productVersion = null; | 71 | string fieldKey = String.Concat(keyProductVersion, ".Major"); |
69 | 72 | if (!this.VariableCache.ContainsKey(fieldKey)) | |
70 | try | ||
71 | { | 73 | { |
72 | productVersion = new Version(value); | 74 | this.VariableCache[fieldKey] = productVersion.Major.ToString(CultureInfo.InvariantCulture); |
73 | 75 | } | |
74 | // Don't add the variable if it already exists (developer defined a property with the same name). | ||
75 | string fieldKey = String.Concat(keyProductVersion, ".Major"); | ||
76 | if (!this.VariableCache.ContainsKey(fieldKey)) | ||
77 | { | ||
78 | this.VariableCache[fieldKey] = productVersion.Major.ToString(CultureInfo.InvariantCulture); | ||
79 | } | ||
80 | |||
81 | fieldKey = String.Concat(keyProductVersion, ".Minor"); | ||
82 | if (!this.VariableCache.ContainsKey(fieldKey)) | ||
83 | { | ||
84 | this.VariableCache[fieldKey] = productVersion.Minor.ToString(CultureInfo.InvariantCulture); | ||
85 | } | ||
86 | 76 | ||
87 | fieldKey = String.Concat(keyProductVersion, ".Build"); | 77 | fieldKey = String.Concat(keyProductVersion, ".Minor"); |
88 | if (!this.VariableCache.ContainsKey(fieldKey)) | 78 | if (!this.VariableCache.ContainsKey(fieldKey)) |
89 | { | 79 | { |
90 | this.VariableCache[fieldKey] = productVersion.Build.ToString(CultureInfo.InvariantCulture); | 80 | this.VariableCache[fieldKey] = productVersion.Minor.ToString(CultureInfo.InvariantCulture); |
91 | } | 81 | } |
92 | 82 | ||
93 | fieldKey = String.Concat(keyProductVersion, ".Revision"); | 83 | fieldKey = String.Concat(keyProductVersion, ".Build"); |
94 | if (!this.VariableCache.ContainsKey(fieldKey)) | 84 | if (!this.VariableCache.ContainsKey(fieldKey)) |
95 | { | 85 | { |
96 | this.VariableCache[fieldKey] = productVersion.Revision.ToString(CultureInfo.InvariantCulture); | 86 | this.VariableCache[fieldKey] = productVersion.Build.ToString(CultureInfo.InvariantCulture); |
97 | } | ||
98 | } | 87 | } |
99 | catch | 88 | |
89 | fieldKey = String.Concat(keyProductVersion, ".Revision"); | ||
90 | if (!this.VariableCache.ContainsKey(fieldKey)) | ||
100 | { | 91 | { |
101 | // Ignore the error introduced by new behavior. | 92 | this.VariableCache[fieldKey] = productVersion.Revision.ToString(CultureInfo.InvariantCulture); |
102 | } | 93 | } |
103 | } | 94 | } |
104 | 95 | ||
@@ -113,7 +104,6 @@ namespace WixToolset.Core.Bind | |||
113 | catch (WixException we) | 104 | catch (WixException we) |
114 | { | 105 | { |
115 | Messaging.Instance.OnMessage(we.Error); | 106 | Messaging.Instance.OnMessage(we.Error); |
116 | continue; | ||
117 | } | 107 | } |
118 | } | 108 | } |
119 | } | 109 | } |
diff --git a/src/WixToolset.Core/Bind/ResolvedDirectory.cs b/src/WixToolset.Core/Bind/ResolvedDirectory.cs index fca706d8..9d07fc93 100644 --- a/src/WixToolset.Core/Bind/ResolvedDirectory.cs +++ b/src/WixToolset.Core/Bind/ResolvedDirectory.cs | |||
@@ -7,15 +7,6 @@ namespace WixToolset.Bind | |||
7 | /// </summary> | 7 | /// </summary> |
8 | public struct ResolvedDirectory | 8 | public struct ResolvedDirectory |
9 | { | 9 | { |
10 | /// <summary>The directory parent.</summary> | ||
11 | public string DirectoryParent; | ||
12 | |||
13 | /// <summary>The name of this directory.</summary> | ||
14 | public string Name; | ||
15 | |||
16 | /// <summary>The path of this directory.</summary> | ||
17 | public string Path; | ||
18 | |||
19 | /// <summary> | 10 | /// <summary> |
20 | /// Constructor for ResolvedDirectory. | 11 | /// Constructor for ResolvedDirectory. |
21 | /// </summary> | 12 | /// </summary> |
@@ -27,5 +18,14 @@ namespace WixToolset.Bind | |||
27 | this.Name = name; | 18 | this.Name = name; |
28 | this.Path = null; | 19 | this.Path = null; |
29 | } | 20 | } |
21 | |||
22 | /// <summary>The directory parent.</summary> | ||
23 | public string DirectoryParent { get; set; } | ||
24 | |||
25 | /// <summary>The name of this directory.</summary> | ||
26 | public string Name { get; set; } | ||
27 | |||
28 | /// <summary>The path of this directory.</summary> | ||
29 | public string Path { get; set; } | ||
30 | } | 30 | } |
31 | } | 31 | } |
diff --git a/src/WixToolset.Core/Binder.cs b/src/WixToolset.Core/Binder.cs index 07a92d02..e282ead8 100644 --- a/src/WixToolset.Core/Binder.cs +++ b/src/WixToolset.Core/Binder.cs | |||
@@ -609,9 +609,9 @@ namespace WixToolset.Core | |||
609 | /// <param name="directory">Directory identifier.</param> | 609 | /// <param name="directory">Directory identifier.</param> |
610 | /// <param name="canonicalize">Canonicalize the path for standard directories.</param> | 610 | /// <param name="canonicalize">Canonicalize the path for standard directories.</param> |
611 | /// <returns>Source path of a directory.</returns> | 611 | /// <returns>Source path of a directory.</returns> |
612 | public static string GetDirectoryPath(Hashtable directories, Hashtable componentIdGenSeeds, string directory, bool canonicalize) | 612 | public static string GetDirectoryPath(Dictionary<string, ResolvedDirectory> directories, Dictionary<string, string> componentIdGenSeeds, string directory, bool canonicalize) |
613 | { | 613 | { |
614 | if (!directories.Contains(directory)) | 614 | if (!directories.ContainsKey(directory)) |
615 | { | 615 | { |
616 | throw new WixException(WixErrors.ExpectedDirectory(directory)); | 616 | throw new WixException(WixErrors.ExpectedDirectory(directory)); |
617 | } | 617 | } |
@@ -620,7 +620,7 @@ namespace WixToolset.Core | |||
620 | 620 | ||
621 | if (null == resolvedDirectory.Path) | 621 | if (null == resolvedDirectory.Path) |
622 | { | 622 | { |
623 | if (null != componentIdGenSeeds && componentIdGenSeeds.Contains(directory)) | 623 | if (null != componentIdGenSeeds && componentIdGenSeeds.ContainsKey(directory)) |
624 | { | 624 | { |
625 | resolvedDirectory.Path = (string)componentIdGenSeeds[directory]; | 625 | resolvedDirectory.Path = (string)componentIdGenSeeds[directory]; |
626 | } | 626 | } |
@@ -670,7 +670,7 @@ namespace WixToolset.Core | |||
670 | /// <param name="compressed">Specifies the package is compressed.</param> | 670 | /// <param name="compressed">Specifies the package is compressed.</param> |
671 | /// <param name="useLongName">Specifies the package uses long file names.</param> | 671 | /// <param name="useLongName">Specifies the package uses long file names.</param> |
672 | /// <returns>Source path of file relative to package directory.</returns> | 672 | /// <returns>Source path of file relative to package directory.</returns> |
673 | public static string GetFileSourcePath(Hashtable directories, string directoryId, string fileName, bool compressed, bool useLongName) | 673 | public static string GetFileSourcePath(Dictionary<string, ResolvedDirectory> directories, string directoryId, string fileName, bool compressed, bool useLongName) |
674 | { | 674 | { |
675 | string fileSourcePath = Common.GetName(fileName, true, useLongName); | 675 | string fileSourcePath = Common.GetName(fileName, true, useLongName); |
676 | 676 | ||
diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index e0475baa..903aae61 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs | |||
@@ -7137,7 +7137,7 @@ namespace WixToolset | |||
7137 | } | 7137 | } |
7138 | 7138 | ||
7139 | // finally, schedule RemoveExistingProducts | 7139 | // finally, schedule RemoveExistingProducts |
7140 | row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixAction); | 7140 | row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixAction, new Identifier("InstallExecuteSequence/RemoveExistingProducts", AccessModifier.Public)); |
7141 | row.Set(0, "InstallExecuteSequence"); | 7141 | row.Set(0, "InstallExecuteSequence"); |
7142 | row.Set(1, "RemoveExistingProducts"); | 7142 | row.Set(1, "RemoveExistingProducts"); |
7143 | // row.Set(2, condition); | 7143 | // row.Set(2, condition); |
@@ -7641,11 +7641,11 @@ namespace WixToolset | |||
7641 | row.Set(4, diskId); | 7641 | row.Set(4, diskId); |
7642 | if (YesNoType.Yes == fileCompression) | 7642 | if (YesNoType.Yes == fileCompression) |
7643 | { | 7643 | { |
7644 | row.Set(5, 1); | 7644 | row.Set(5, true); |
7645 | } | 7645 | } |
7646 | else if (YesNoType.No == fileCompression) | 7646 | else if (YesNoType.No == fileCompression) |
7647 | { | 7647 | { |
7648 | row.Set(5, 0); | 7648 | row.Set(5, false); |
7649 | } | 7649 | } |
7650 | else // YesNoType.NotSet == fileCompression | 7650 | else // YesNoType.NotSet == fileCompression |
7651 | { | 7651 | { |
@@ -9525,7 +9525,7 @@ namespace WixToolset | |||
9525 | var patchIdRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchId); | 9525 | var patchIdRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchId); |
9526 | patchIdRow.Set(0, patchId); | 9526 | patchIdRow.Set(0, patchId); |
9527 | patchIdRow.Set(1, clientPatchId); | 9527 | patchIdRow.Set(1, clientPatchId); |
9528 | patchIdRow.Set(2, optimizePatchSizeForLargeFiles ? 1 : 0); | 9528 | patchIdRow.Set(2, optimizePatchSizeForLargeFiles); |
9529 | patchIdRow.Set(3, apiPatchingSymbolFlags); | 9529 | patchIdRow.Set(3, apiPatchingSymbolFlags); |
9530 | 9530 | ||
9531 | if (allowRemoval) | 9531 | if (allowRemoval) |
diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index 59481387..7faf69ba 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs | |||
@@ -23,9 +23,6 @@ namespace WixToolset.Core | |||
23 | private static readonly string emptyGuid = Guid.Empty.ToString("B"); | 23 | private static readonly string emptyGuid = Guid.Empty.ToString("B"); |
24 | 24 | ||
25 | private bool sectionIdOnRows; | 25 | private bool sectionIdOnRows; |
26 | //private WixActionRowCollection standardActions; | ||
27 | //private Output activeOutput; | ||
28 | //private TableDefinitionCollection tableDefinitions; | ||
29 | 26 | ||
30 | /// <summary> | 27 | /// <summary> |
31 | /// Creates a linker. | 28 | /// Creates a linker. |
@@ -34,9 +31,6 @@ namespace WixToolset.Core | |||
34 | { | 31 | { |
35 | this.sectionIdOnRows = true; // TODO: what is the correct value for this? | 32 | this.sectionIdOnRows = true; // TODO: what is the correct value for this? |
36 | 33 | ||
37 | //this.standardActions = WindowsInstallerStandard.GetStandardActions(); | ||
38 | //this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); | ||
39 | |||
40 | //this.extensionData = new List<IExtensionData>(); | 34 | //this.extensionData = new List<IExtensionData>(); |
41 | //this.inspectorExtensions = new List<InspectorExtension>(); | 35 | //this.inspectorExtensions = new List<InspectorExtension>(); |
42 | } | 36 | } |
@@ -108,11 +102,6 @@ namespace WixToolset.Core | |||
108 | 102 | ||
109 | //this.activeOutput = null; | 103 | //this.activeOutput = null; |
110 | 104 | ||
111 | #if MOVE_TO_BACKEND | ||
112 | var actionRows = new List<IntermediateTuple>(); | ||
113 | var suppressActionRows = new List<IntermediateTuple>(); | ||
114 | #endif | ||
115 | |||
116 | //TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection(); | 105 | //TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection(); |
117 | //IntermediateTuple customRows = new List<IntermediateTuple>(); | 106 | //IntermediateTuple customRows = new List<IntermediateTuple>(); |
118 | 107 | ||
@@ -232,7 +221,7 @@ namespace WixToolset.Core | |||
232 | } | 221 | } |
233 | 222 | ||
234 | // Report duplicates that would ultimately end up being primary key collisions. | 223 | // Report duplicates that would ultimately end up being primary key collisions. |
235 | ReportConflictingSymbolsCommand reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections); | 224 | var reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections); |
236 | reportDupes.Execute(); | 225 | reportDupes.Execute(); |
237 | 226 | ||
238 | if (Messaging.Instance.EncounteredError) | 227 | if (Messaging.Instance.EncounteredError) |
@@ -394,19 +383,6 @@ namespace WixToolset.Core | |||
394 | } | 383 | } |
395 | break; | 384 | break; |
396 | 385 | ||
397 | #if MOVE_TO_BACKEND | ||
398 | case TupleDefinitionType.WixAction: | ||
399 | //if (this.sectionIdOnRows) | ||
400 | //{ | ||
401 | // foreach (Row row in table.Rows) | ||
402 | // { | ||
403 | // row.SectionId = sectionId; | ||
404 | // } | ||
405 | //} | ||
406 | actionRows.Add(tuple); | ||
407 | break; | ||
408 | #endif | ||
409 | |||
410 | #if SOLVE_CUSTOM_TABLE | 386 | #if SOLVE_CUSTOM_TABLE |
411 | case "WixCustomTable": | 387 | case "WixCustomTable": |
412 | this.LinkCustomTable(table, customTableDefinitions); | 388 | this.LinkCustomTable(table, customTableDefinitions); |
@@ -455,12 +431,6 @@ namespace WixToolset.Core | |||
455 | } | 431 | } |
456 | break; | 432 | break; |
457 | 433 | ||
458 | #if MOVE_TO_BACKEND | ||
459 | case TupleDefinitionType.WixSuppressAction: | ||
460 | suppressActionRows.Add(tuple); | ||
461 | break; | ||
462 | #endif | ||
463 | |||
464 | case TupleDefinitionType.WixComplexReference: | 434 | case TupleDefinitionType.WixComplexReference: |
465 | copyTuple = false; | 435 | copyTuple = false; |
466 | break; | 436 | break; |
@@ -539,11 +509,6 @@ namespace WixToolset.Core | |||
539 | #endif | 509 | #endif |
540 | 510 | ||
541 | #if MOVE_TO_BACKEND | 511 | #if MOVE_TO_BACKEND |
542 | // sequence all the actions | ||
543 | this.SequenceActions(actionRows, suppressActionRows); | ||
544 | #endif | ||
545 | |||
546 | #if MOVE_TO_BACKEND | ||
547 | // check for missing table and add them or display an error as appropriate | 512 | // check for missing table and add them or display an error as appropriate |
548 | switch (this.activeOutput.Type) | 513 | switch (this.activeOutput.Type) |
549 | { | 514 | { |
@@ -1140,6 +1105,7 @@ namespace WixToolset.Core | |||
1140 | } | 1105 | } |
1141 | } | 1106 | } |
1142 | #endif | 1107 | #endif |
1108 | |||
1143 | /// <summary> | 1109 | /// <summary> |
1144 | /// Sends a message to the message delegate if there is one. | 1110 | /// Sends a message to the message delegate if there is one. |
1145 | /// </summary> | 1111 | /// </summary> |
@@ -1726,638 +1692,6 @@ namespace WixToolset.Core | |||
1726 | } | 1692 | } |
1727 | #endif | 1693 | #endif |
1728 | 1694 | ||
1729 | #if MOVE_TO_BACKEND | ||
1730 | /// <summary> | ||
1731 | /// Set sequence numbers for all the actions and create rows in the output object. | ||
1732 | /// </summary> | ||
1733 | /// <param name="actionRows">Collection of actions to schedule.</param> | ||
1734 | /// <param name="suppressActionRows">Collection of actions to suppress.</param> | ||
1735 | private void SequenceActions(List<IntermediateTuple> actionRows, List<IntermediateTuple> suppressActionRows) | ||
1736 | { | ||
1737 | var overridableActionRows = new WixActionRowCollection(); | ||
1738 | var requiredActionRows = new WixActionRowCollection(); | ||
1739 | ArrayList scheduledActionRows = new ArrayList(); | ||
1740 | |||
1741 | // gather the required actions for the output type | ||
1742 | if (OutputType.Product == this.activeOutput.Type) | ||
1743 | { | ||
1744 | // AdminExecuteSequence table | ||
1745 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostFinalize"]); | ||
1746 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "CostInitialize"]); | ||
1747 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "FileCost"]); | ||
1748 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallAdminPackage"]); | ||
1749 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFiles"]); | ||
1750 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallFinalize"]); | ||
1751 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallInitialize"]); | ||
1752 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminExecuteSequence, "InstallValidate"]); | ||
1753 | |||
1754 | // AdminUISequence table | ||
1755 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostFinalize"]); | ||
1756 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "CostInitialize"]); | ||
1757 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "ExecuteAction"]); | ||
1758 | overridableActionRows.Add(this.standardActions[SequenceTable.AdminUISequence, "FileCost"]); | ||
1759 | |||
1760 | // AdvtExecuteSequence table | ||
1761 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostFinalize"]); | ||
1762 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CostInitialize"]); | ||
1763 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallFinalize"]); | ||
1764 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallInitialize"]); | ||
1765 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "InstallValidate"]); | ||
1766 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishFeatures"]); | ||
1767 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishProduct"]); | ||
1768 | |||
1769 | // InstallExecuteSequence table | ||
1770 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostFinalize"]); | ||
1771 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CostInitialize"]); | ||
1772 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FileCost"]); | ||
1773 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFinalize"]); | ||
1774 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallInitialize"]); | ||
1775 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallValidate"]); | ||
1776 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ProcessComponents"]); | ||
1777 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishFeatures"]); | ||
1778 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishProduct"]); | ||
1779 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProduct"]); | ||
1780 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterUser"]); | ||
1781 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishFeatures"]); | ||
1782 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "ValidateProductID"]); | ||
1783 | |||
1784 | // InstallUISequence table | ||
1785 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostFinalize"]); | ||
1786 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CostInitialize"]); | ||
1787 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ExecuteAction"]); | ||
1788 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FileCost"]); | ||
1789 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "ValidateProductID"]); | ||
1790 | } | ||
1791 | |||
1792 | // gather the required actions for each table | ||
1793 | foreach (Table table in this.activeOutput.Tables) | ||
1794 | { | ||
1795 | switch (table.Name) | ||
1796 | { | ||
1797 | case "AppSearch": | ||
1798 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true); | ||
1799 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true); | ||
1800 | break; | ||
1801 | case "BindImage": | ||
1802 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "BindImage"], true); | ||
1803 | break; | ||
1804 | case "CCPSearch": | ||
1805 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "AppSearch"], true); | ||
1806 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CCPSearch"], true); | ||
1807 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RMCCPSearch"], true); | ||
1808 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "AppSearch"], true); | ||
1809 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "CCPSearch"], true); | ||
1810 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "RMCCPSearch"], true); | ||
1811 | break; | ||
1812 | case "Class": | ||
1813 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterClassInfo"], true); | ||
1814 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterClassInfo"], true); | ||
1815 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterClassInfo"], true); | ||
1816 | break; | ||
1817 | case "Complus": | ||
1818 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterComPlus"], true); | ||
1819 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterComPlus"], true); | ||
1820 | break; | ||
1821 | case "CreateFolder": | ||
1822 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateFolders"], true); | ||
1823 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFolders"], true); | ||
1824 | break; | ||
1825 | case "DuplicateFile": | ||
1826 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DuplicateFiles"], true); | ||
1827 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveDuplicateFiles"], true); | ||
1828 | break; | ||
1829 | case "Environment": | ||
1830 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteEnvironmentStrings"], true); | ||
1831 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveEnvironmentStrings"], true); | ||
1832 | break; | ||
1833 | case "Extension": | ||
1834 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterExtensionInfo"], true); | ||
1835 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterExtensionInfo"], true); | ||
1836 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterExtensionInfo"], true); | ||
1837 | break; | ||
1838 | case "File": | ||
1839 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true); | ||
1840 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true); | ||
1841 | break; | ||
1842 | case "Font": | ||
1843 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterFonts"], true); | ||
1844 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterFonts"], true); | ||
1845 | break; | ||
1846 | case "IniFile": | ||
1847 | case "RemoveIniFile": | ||
1848 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteIniValues"], true); | ||
1849 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveIniValues"], true); | ||
1850 | break; | ||
1851 | case "IsolatedComponent": | ||
1852 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "IsolateComponents"], true); | ||
1853 | break; | ||
1854 | case "LaunchCondition": | ||
1855 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "LaunchConditions"], true); | ||
1856 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "LaunchConditions"], true); | ||
1857 | break; | ||
1858 | case "MIME": | ||
1859 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterMIMEInfo"], true); | ||
1860 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterMIMEInfo"], true); | ||
1861 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterMIMEInfo"], true); | ||
1862 | break; | ||
1863 | case "MoveFile": | ||
1864 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MoveFiles"], true); | ||
1865 | break; | ||
1866 | case "MsiAssembly": | ||
1867 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "MsiPublishAssemblies"], true); | ||
1868 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiPublishAssemblies"], true); | ||
1869 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiUnpublishAssemblies"], true); | ||
1870 | break; | ||
1871 | case "MsiServiceConfig": | ||
1872 | case "MsiServiceConfigFailureActions": | ||
1873 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MsiConfigureServices"], true); | ||
1874 | break; | ||
1875 | case "ODBCDataSource": | ||
1876 | case "ODBCTranslator": | ||
1877 | case "ODBCDriver": | ||
1878 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SetODBCFolders"], true); | ||
1879 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallODBC"], true); | ||
1880 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveODBC"], true); | ||
1881 | break; | ||
1882 | case "ProgId": | ||
1883 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "RegisterProgIdInfo"], true); | ||
1884 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterProgIdInfo"], true); | ||
1885 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterProgIdInfo"], true); | ||
1886 | break; | ||
1887 | case "PublishComponent": | ||
1888 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "PublishComponents"], true); | ||
1889 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "PublishComponents"], true); | ||
1890 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnpublishComponents"], true); | ||
1891 | break; | ||
1892 | case "Registry": | ||
1893 | case "RemoveRegistry": | ||
1894 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "WriteRegistryValues"], true); | ||
1895 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveRegistryValues"], true); | ||
1896 | break; | ||
1897 | case "RemoveFile": | ||
1898 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveFiles"], true); | ||
1899 | break; | ||
1900 | case "SelfReg": | ||
1901 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfRegModules"], true); | ||
1902 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "SelfUnregModules"], true); | ||
1903 | break; | ||
1904 | case "ServiceControl": | ||
1905 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StartServices"], true); | ||
1906 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "StopServices"], true); | ||
1907 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "DeleteServices"], true); | ||
1908 | break; | ||
1909 | case "ServiceInstall": | ||
1910 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallServices"], true); | ||
1911 | break; | ||
1912 | case "Shortcut": | ||
1913 | overridableActionRows.Add(this.standardActions[SequenceTable.AdvtExecuteSequence, "CreateShortcuts"], true); | ||
1914 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "CreateShortcuts"], true); | ||
1915 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RemoveShortcuts"], true); | ||
1916 | break; | ||
1917 | case "TypeLib": | ||
1918 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "RegisterTypeLibraries"], true); | ||
1919 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "UnregisterTypeLibraries"], true); | ||
1920 | break; | ||
1921 | case "Upgrade": | ||
1922 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "FindRelatedProducts"], true); | ||
1923 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "FindRelatedProducts"], true); | ||
1924 | // Only add the MigrateFeatureStates action if MigrateFeature attribute is set to yes on at least one UpgradeVersion element. | ||
1925 | foreach (Row row in table.Rows) | ||
1926 | { | ||
1927 | int options = (int)row[4]; | ||
1928 | if (MsiInterop.MsidbUpgradeAttributesMigrateFeatures == (options & MsiInterop.MsidbUpgradeAttributesMigrateFeatures)) | ||
1929 | { | ||
1930 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "MigrateFeatureStates"], true); | ||
1931 | overridableActionRows.Add(this.standardActions[SequenceTable.InstallUISequence, "MigrateFeatureStates"], true); | ||
1932 | break; | ||
1933 | } | ||
1934 | } | ||
1935 | break; | ||
1936 | } | ||
1937 | } | ||
1938 | |||
1939 | // index all the action rows (look for collisions) | ||
1940 | foreach (WixActionRow actionRow in actionRows) | ||
1941 | { | ||
1942 | if (actionRow.Overridable) // overridable action | ||
1943 | { | ||
1944 | WixActionRow collidingActionRow = overridableActionRows[actionRow.SequenceTable, actionRow.Action]; | ||
1945 | |||
1946 | if (null != collidingActionRow) | ||
1947 | { | ||
1948 | this.OnMessage(WixErrors.OverridableActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
1949 | if (null != collidingActionRow.SourceLineNumbers) | ||
1950 | { | ||
1951 | this.OnMessage(WixErrors.OverridableActionCollision2(collidingActionRow.SourceLineNumbers)); | ||
1952 | } | ||
1953 | } | ||
1954 | else | ||
1955 | { | ||
1956 | overridableActionRows.Add(actionRow); | ||
1957 | } | ||
1958 | } | ||
1959 | else // unscheduled/scheduled action | ||
1960 | { | ||
1961 | // unscheduled action (allowed for certain standard actions) | ||
1962 | if (null == actionRow.Before && null == actionRow.After && 0 == actionRow.Sequence) | ||
1963 | { | ||
1964 | WixActionRow standardAction = this.standardActions[actionRow.SequenceTable, actionRow.Action]; | ||
1965 | |||
1966 | if (null != standardAction) | ||
1967 | { | ||
1968 | // populate the sequence from the standard action | ||
1969 | actionRow.Sequence = standardAction.Sequence; | ||
1970 | } | ||
1971 | else // not a supported unscheduled action | ||
1972 | { | ||
1973 | throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1977 | WixActionRow collidingActionRow = requiredActionRows[actionRow.SequenceTable, actionRow.Action]; | ||
1978 | |||
1979 | if (null != collidingActionRow) | ||
1980 | { | ||
1981 | this.OnMessage(WixErrors.ActionCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
1982 | if (null != collidingActionRow.SourceLineNumbers) | ||
1983 | { | ||
1984 | this.OnMessage(WixErrors.ActionCollision2(collidingActionRow.SourceLineNumbers)); | ||
1985 | } | ||
1986 | } | ||
1987 | else | ||
1988 | { | ||
1989 | requiredActionRows.Add(actionRow.Clone()); | ||
1990 | } | ||
1991 | } | ||
1992 | } | ||
1993 | |||
1994 | // add the overridable action rows that are not overridden to the required action rows | ||
1995 | foreach (WixActionRow actionRow in overridableActionRows) | ||
1996 | { | ||
1997 | if (null == requiredActionRows[actionRow.SequenceTable, actionRow.Action]) | ||
1998 | { | ||
1999 | requiredActionRows.Add(actionRow.Clone()); | ||
2000 | } | ||
2001 | } | ||
2002 | |||
2003 | // suppress the required actions that are overridable | ||
2004 | foreach (Row suppressActionRow in suppressActionRows) | ||
2005 | { | ||
2006 | SequenceTable sequenceTable = (SequenceTable)Enum.Parse(typeof(SequenceTable), (string)suppressActionRow[0]); | ||
2007 | string action = (string)suppressActionRow[1]; | ||
2008 | |||
2009 | // get the action being suppressed (if it exists) | ||
2010 | WixActionRow requiredActionRow = requiredActionRows[sequenceTable, action]; | ||
2011 | |||
2012 | // if there is an overridable row to suppress; suppress it | ||
2013 | // there is no warning if there is no action to suppress because the action may be suppressed from a merge module in the binder | ||
2014 | if (null != requiredActionRow) | ||
2015 | { | ||
2016 | if (requiredActionRow.Overridable) | ||
2017 | { | ||
2018 | this.OnMessage(WixWarnings.SuppressAction(suppressActionRow.SourceLineNumbers, action, sequenceTable.ToString())); | ||
2019 | if (null != requiredActionRow.SourceLineNumbers) | ||
2020 | { | ||
2021 | this.OnMessage(WixWarnings.SuppressAction2(requiredActionRow.SourceLineNumbers)); | ||
2022 | } | ||
2023 | requiredActionRows.Remove(sequenceTable, action); | ||
2024 | } | ||
2025 | else // suppressing a non-overridable action row | ||
2026 | { | ||
2027 | this.OnMessage(WixErrors.SuppressNonoverridableAction(suppressActionRow.SourceLineNumbers, sequenceTable.ToString(), action)); | ||
2028 | if (null != requiredActionRow.SourceLineNumbers) | ||
2029 | { | ||
2030 | this.OnMessage(WixErrors.SuppressNonoverridableAction2(requiredActionRow.SourceLineNumbers)); | ||
2031 | } | ||
2032 | } | ||
2033 | } | ||
2034 | } | ||
2035 | |||
2036 | // create a copy of the required action rows so that new rows can be added while enumerating | ||
2037 | WixActionRow[] copyOfRequiredActionRows = new WixActionRow[requiredActionRows.Count]; | ||
2038 | requiredActionRows.CopyTo(copyOfRequiredActionRows, 0); | ||
2039 | |||
2040 | // build up dependency trees of the relatively scheduled actions | ||
2041 | foreach (WixActionRow actionRow in copyOfRequiredActionRows) | ||
2042 | { | ||
2043 | if (0 == actionRow.Sequence) | ||
2044 | { | ||
2045 | // check for standard actions that don't have a sequence number in a merge module | ||
2046 | if (OutputType.Module == this.activeOutput.Type && WindowsInstallerStandard.IsStandardAction(actionRow.Action)) | ||
2047 | { | ||
2048 | this.OnMessage(WixErrors.StandardActionRelativelyScheduledInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
2049 | } | ||
2050 | |||
2051 | this.SequenceActionRow(actionRow, requiredActionRows); | ||
2052 | } | ||
2053 | else if (OutputType.Module == this.activeOutput.Type && 0 < actionRow.Sequence && !WindowsInstallerStandard.IsStandardAction(actionRow.Action)) // check for custom actions and dialogs that have a sequence number | ||
2054 | { | ||
2055 | this.OnMessage(WixErrors.CustomActionSequencedInModule(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action)); | ||
2056 | } | ||
2057 | } | ||
2058 | |||
2059 | // look for standard actions with sequence restrictions that aren't necessarily scheduled based on the presence of a particular table | ||
2060 | if (requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "DuplicateFiles") && !requiredActionRows.Contains(SequenceTable.InstallExecuteSequence, "InstallFiles")) | ||
2061 | { | ||
2062 | requiredActionRows.Add(this.standardActions[SequenceTable.InstallExecuteSequence, "InstallFiles"], true); | ||
2063 | } | ||
2064 | |||
2065 | // schedule actions | ||
2066 | if (OutputType.Module == this.activeOutput.Type) | ||
2067 | { | ||
2068 | // add the action row to the list of scheduled action rows | ||
2069 | scheduledActionRows.AddRange(requiredActionRows); | ||
2070 | } | ||
2071 | else | ||
2072 | { | ||
2073 | // process each sequence table individually | ||
2074 | foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable))) | ||
2075 | { | ||
2076 | // create a collection of just the action rows in this sequence | ||
2077 | WixActionRowCollection sequenceActionRows = new WixActionRowCollection(); | ||
2078 | foreach (WixActionRow actionRow in requiredActionRows) | ||
2079 | { | ||
2080 | if (sequenceTable == actionRow.SequenceTable) | ||
2081 | { | ||
2082 | sequenceActionRows.Add(actionRow); | ||
2083 | } | ||
2084 | } | ||
2085 | |||
2086 | // schedule the absolutely scheduled actions (by sorting them by their sequence numbers) | ||
2087 | ArrayList absoluteActionRows = new ArrayList(); | ||
2088 | foreach (WixActionRow actionRow in sequenceActionRows) | ||
2089 | { | ||
2090 | if (0 != actionRow.Sequence) | ||
2091 | { | ||
2092 | // look for sequence number collisions | ||
2093 | foreach (WixActionRow sequenceScheduledActionRow in absoluteActionRows) | ||
2094 | { | ||
2095 | if (sequenceScheduledActionRow.Sequence == actionRow.Sequence) | ||
2096 | { | ||
2097 | this.OnMessage(WixWarnings.ActionSequenceCollision(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, sequenceScheduledActionRow.Action, actionRow.Sequence)); | ||
2098 | if (null != sequenceScheduledActionRow.SourceLineNumbers) | ||
2099 | { | ||
2100 | this.OnMessage(WixWarnings.ActionSequenceCollision2(sequenceScheduledActionRow.SourceLineNumbers)); | ||
2101 | } | ||
2102 | } | ||
2103 | } | ||
2104 | |||
2105 | absoluteActionRows.Add(actionRow); | ||
2106 | } | ||
2107 | } | ||
2108 | absoluteActionRows.Sort(); | ||
2109 | |||
2110 | // schedule the relatively scheduled actions (by resolving the dependency trees) | ||
2111 | int previousUsedSequence = 0; | ||
2112 | ArrayList relativeActionRows = new ArrayList(); | ||
2113 | for (int j = 0; j < absoluteActionRows.Count; j++) | ||
2114 | { | ||
2115 | WixActionRow absoluteActionRow = (WixActionRow)absoluteActionRows[j]; | ||
2116 | int unusedSequence; | ||
2117 | |||
2118 | // get all the relatively scheduled action rows occuring before this absolutely scheduled action row | ||
2119 | RowIndexedList<WixActionRow> allPreviousActionRows = new RowIndexedList<WixActionRow>(); | ||
2120 | absoluteActionRow.GetAllPreviousActionRows(sequenceTable, allPreviousActionRows); | ||
2121 | |||
2122 | // get all the relatively scheduled action rows occuring after this absolutely scheduled action row | ||
2123 | RowIndexedList<WixActionRow> allNextActionRows = new RowIndexedList<WixActionRow>(); | ||
2124 | absoluteActionRow.GetAllNextActionRows(sequenceTable, allNextActionRows); | ||
2125 | |||
2126 | // check for relatively scheduled actions occuring before/after a special action (these have a negative sequence number) | ||
2127 | if (0 > absoluteActionRow.Sequence && (0 < allPreviousActionRows.Count || 0 < allNextActionRows.Count)) | ||
2128 | { | ||
2129 | // create errors for all the before actions | ||
2130 | foreach (WixActionRow actionRow in allPreviousActionRows) | ||
2131 | { | ||
2132 | this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); | ||
2133 | } | ||
2134 | |||
2135 | // create errors for all the after actions | ||
2136 | foreach (WixActionRow actionRow in allNextActionRows) | ||
2137 | { | ||
2138 | this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, absoluteActionRow.Action)); | ||
2139 | } | ||
2140 | |||
2141 | // if there is source line information for the absolutely scheduled action display it | ||
2142 | if (null != absoluteActionRow.SourceLineNumbers) | ||
2143 | { | ||
2144 | this.OnMessage(WixErrors.ActionScheduledRelativeToTerminationAction2(absoluteActionRow.SourceLineNumbers)); | ||
2145 | } | ||
2146 | |||
2147 | continue; | ||
2148 | } | ||
2149 | |||
2150 | // schedule the action rows before this one | ||
2151 | unusedSequence = absoluteActionRow.Sequence - 1; | ||
2152 | for (int i = allPreviousActionRows.Count - 1; i >= 0; i--) | ||
2153 | { | ||
2154 | WixActionRow relativeActionRow = (WixActionRow)allPreviousActionRows[i]; | ||
2155 | |||
2156 | // look for collisions | ||
2157 | if (unusedSequence == previousUsedSequence) | ||
2158 | { | ||
2159 | this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); | ||
2160 | if (null != absoluteActionRow.SourceLineNumbers) | ||
2161 | { | ||
2162 | this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); | ||
2163 | } | ||
2164 | |||
2165 | unusedSequence++; | ||
2166 | } | ||
2167 | |||
2168 | relativeActionRow.Sequence = unusedSequence; | ||
2169 | relativeActionRows.Add(relativeActionRow); | ||
2170 | |||
2171 | unusedSequence--; | ||
2172 | } | ||
2173 | |||
2174 | // determine the next used action sequence number | ||
2175 | int nextUsedSequence; | ||
2176 | if (absoluteActionRows.Count > j + 1) | ||
2177 | { | ||
2178 | nextUsedSequence = ((WixActionRow)absoluteActionRows[j + 1]).Sequence; | ||
2179 | } | ||
2180 | else | ||
2181 | { | ||
2182 | nextUsedSequence = short.MaxValue + 1; | ||
2183 | } | ||
2184 | |||
2185 | // schedule the action rows after this one | ||
2186 | unusedSequence = absoluteActionRow.Sequence + 1; | ||
2187 | for (int i = 0; i < allNextActionRows.Count; i++) | ||
2188 | { | ||
2189 | WixActionRow relativeActionRow = (WixActionRow)allNextActionRows[i]; | ||
2190 | |||
2191 | if (unusedSequence == nextUsedSequence) | ||
2192 | { | ||
2193 | this.OnMessage(WixErrors.NoUniqueActionSequenceNumber(relativeActionRow.SourceLineNumbers, relativeActionRow.SequenceTable.ToString(), relativeActionRow.Action, absoluteActionRow.Action)); | ||
2194 | if (null != absoluteActionRow.SourceLineNumbers) | ||
2195 | { | ||
2196 | this.OnMessage(WixErrors.NoUniqueActionSequenceNumber2(absoluteActionRow.SourceLineNumbers)); | ||
2197 | } | ||
2198 | |||
2199 | unusedSequence--; | ||
2200 | } | ||
2201 | |||
2202 | relativeActionRow.Sequence = unusedSequence; | ||
2203 | relativeActionRows.Add(relativeActionRow); | ||
2204 | |||
2205 | unusedSequence++; | ||
2206 | } | ||
2207 | |||
2208 | // keep track of this sequence number as the previous used sequence number for the next iteration | ||
2209 | previousUsedSequence = absoluteActionRow.Sequence; | ||
2210 | } | ||
2211 | |||
2212 | // add the absolutely and relatively scheduled actions to the list of scheduled actions | ||
2213 | scheduledActionRows.AddRange(absoluteActionRows); | ||
2214 | scheduledActionRows.AddRange(relativeActionRows); | ||
2215 | } | ||
2216 | } | ||
2217 | |||
2218 | // create the action rows for sequences that are not suppressed | ||
2219 | foreach (WixActionRow actionRow in scheduledActionRows) | ||
2220 | { | ||
2221 | // get the table definition for the action (and ensure the proper table exists for a module) | ||
2222 | TableDefinition sequenceTableDefinition = null; | ||
2223 | switch (actionRow.SequenceTable) | ||
2224 | { | ||
2225 | case SequenceTable.AdminExecuteSequence: | ||
2226 | if (OutputType.Module == this.activeOutput.Type) | ||
2227 | { | ||
2228 | this.activeOutput.EnsureTable(this.tableDefinitions["AdminExecuteSequence"]); | ||
2229 | sequenceTableDefinition = this.tableDefinitions["ModuleAdminExecuteSequence"]; | ||
2230 | } | ||
2231 | else | ||
2232 | { | ||
2233 | sequenceTableDefinition = this.tableDefinitions["AdminExecuteSequence"]; | ||
2234 | } | ||
2235 | break; | ||
2236 | case SequenceTable.AdminUISequence: | ||
2237 | if (OutputType.Module == this.activeOutput.Type) | ||
2238 | { | ||
2239 | this.activeOutput.EnsureTable(this.tableDefinitions["AdminUISequence"]); | ||
2240 | sequenceTableDefinition = this.tableDefinitions["ModuleAdminUISequence"]; | ||
2241 | } | ||
2242 | else | ||
2243 | { | ||
2244 | sequenceTableDefinition = this.tableDefinitions["AdminUISequence"]; | ||
2245 | } | ||
2246 | break; | ||
2247 | case SequenceTable.AdvtExecuteSequence: | ||
2248 | if (OutputType.Module == this.activeOutput.Type) | ||
2249 | { | ||
2250 | this.activeOutput.EnsureTable(this.tableDefinitions["AdvtExecuteSequence"]); | ||
2251 | sequenceTableDefinition = this.tableDefinitions["ModuleAdvtExecuteSequence"]; | ||
2252 | } | ||
2253 | else | ||
2254 | { | ||
2255 | sequenceTableDefinition = this.tableDefinitions["AdvtExecuteSequence"]; | ||
2256 | } | ||
2257 | break; | ||
2258 | case SequenceTable.InstallExecuteSequence: | ||
2259 | if (OutputType.Module == this.activeOutput.Type) | ||
2260 | { | ||
2261 | this.activeOutput.EnsureTable(this.tableDefinitions["InstallExecuteSequence"]); | ||
2262 | sequenceTableDefinition = this.tableDefinitions["ModuleInstallExecuteSequence"]; | ||
2263 | } | ||
2264 | else | ||
2265 | { | ||
2266 | sequenceTableDefinition = this.tableDefinitions["InstallExecuteSequence"]; | ||
2267 | } | ||
2268 | break; | ||
2269 | case SequenceTable.InstallUISequence: | ||
2270 | if (OutputType.Module == this.activeOutput.Type) | ||
2271 | { | ||
2272 | this.activeOutput.EnsureTable(this.tableDefinitions["InstallUISequence"]); | ||
2273 | sequenceTableDefinition = this.tableDefinitions["ModuleInstallUISequence"]; | ||
2274 | } | ||
2275 | else | ||
2276 | { | ||
2277 | sequenceTableDefinition = this.tableDefinitions["InstallUISequence"]; | ||
2278 | } | ||
2279 | break; | ||
2280 | } | ||
2281 | |||
2282 | // create the action sequence row in the output | ||
2283 | Table sequenceTable = this.activeOutput.EnsureTable(sequenceTableDefinition); | ||
2284 | Row row = sequenceTable.CreateRow(actionRow.SourceLineNumbers); | ||
2285 | if (this.sectionIdOnRows) | ||
2286 | { | ||
2287 | row.SectionId = actionRow.SectionId; | ||
2288 | } | ||
2289 | |||
2290 | if (OutputType.Module == this.activeOutput.Type) | ||
2291 | { | ||
2292 | row[0] = actionRow.Action; | ||
2293 | if (0 != actionRow.Sequence) | ||
2294 | { | ||
2295 | row[1] = actionRow.Sequence; | ||
2296 | } | ||
2297 | else | ||
2298 | { | ||
2299 | bool after = (null == actionRow.Before); | ||
2300 | row[2] = after ? actionRow.After : actionRow.Before; | ||
2301 | row[3] = after ? 1 : 0; | ||
2302 | } | ||
2303 | row[4] = actionRow.Condition; | ||
2304 | } | ||
2305 | else | ||
2306 | { | ||
2307 | row[0] = actionRow.Action; | ||
2308 | row[1] = actionRow.Condition; | ||
2309 | row[2] = actionRow.Sequence; | ||
2310 | } | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2314 | /// <summary> | ||
2315 | /// Sequence an action before or after a standard action. | ||
2316 | /// </summary> | ||
2317 | /// <param name="actionRow">The action row to be sequenced.</param> | ||
2318 | /// <param name="requiredActionRows">Collection of actions which must be included.</param> | ||
2319 | [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")] | ||
2320 | private void SequenceActionRow(WixActionRow actionRow, WixActionRowCollection requiredActionRows) | ||
2321 | { | ||
2322 | bool after = false; | ||
2323 | if (actionRow.After != null) | ||
2324 | { | ||
2325 | after = true; | ||
2326 | } | ||
2327 | else if (actionRow.Before == null) | ||
2328 | { | ||
2329 | throw new InvalidOperationException(WixStrings.EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet); | ||
2330 | } | ||
2331 | |||
2332 | string parentActionName = (after ? actionRow.After : actionRow.Before); | ||
2333 | WixActionRow parentActionRow = requiredActionRows[actionRow.SequenceTable, parentActionName]; | ||
2334 | |||
2335 | if (null == parentActionRow) | ||
2336 | { | ||
2337 | parentActionRow = this.standardActions[actionRow.SequenceTable, parentActionName]; | ||
2338 | |||
2339 | // if the missing parent action is a standard action (with a suggested sequence number), add it | ||
2340 | if (null != parentActionRow) | ||
2341 | { | ||
2342 | // Create a clone to avoid modifying the static copy of the object. | ||
2343 | parentActionRow = parentActionRow.Clone(); | ||
2344 | requiredActionRows.Add(parentActionRow); | ||
2345 | } | ||
2346 | else | ||
2347 | { | ||
2348 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_FoundActionRowWinNonExistentAction, (after ? "After" : "Before"), parentActionName)); | ||
2349 | } | ||
2350 | } | ||
2351 | else if (actionRow == parentActionRow || actionRow.ContainsChildActionRow(parentActionRow)) // cycle detected | ||
2352 | { | ||
2353 | throw new WixException(WixErrors.ActionCircularDependency(actionRow.SourceLineNumbers, actionRow.SequenceTable.ToString(), actionRow.Action, parentActionRow.Action)); | ||
2354 | } | ||
2355 | |||
2356 | // Add this action to the appropriate list of dependent action rows. | ||
2357 | WixActionRowCollection relatedRows = (after ? parentActionRow.NextActionRows : parentActionRow.PreviousActionRows); | ||
2358 | relatedRows.Add(actionRow); | ||
2359 | } | ||
2360 | #endif | ||
2361 | 1695 | ||
2362 | /// <summary> | 1696 | /// <summary> |
2363 | /// Resolve features for columns that have null guid placeholders. | 1697 | /// Resolve features for columns that have null guid placeholders. |
diff --git a/src/WixToolset.Core/WindowsInstallerStandard.cs b/src/WixToolset.Core/WindowsInstallerStandard.cs deleted file mode 100644 index 90a53e6a..00000000 --- a/src/WixToolset.Core/WindowsInstallerStandard.cs +++ /dev/null | |||
@@ -1,260 +0,0 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | using WixToolset.Data; | ||
7 | using WixToolset.Data.Tuples; | ||
8 | |||
9 | internal class WindowsInstallerStandard | ||
10 | { | ||
11 | private static readonly HashSet<string> standardActionNames = new HashSet<string> | ||
12 | { | ||
13 | "AllocateRegistrySpace", | ||
14 | "AppSearch", | ||
15 | "BindImage", | ||
16 | "CCPSearch", | ||
17 | "CostFinalize", | ||
18 | "CostInitialize", | ||
19 | "CreateFolders", | ||
20 | "CreateShortcuts", | ||
21 | "DeleteServices", | ||
22 | "DisableRollback", | ||
23 | "DuplicateFiles", | ||
24 | "ExecuteAction", | ||
25 | "FileCost", | ||
26 | "FindRelatedProducts", | ||
27 | "ForceReboot", | ||
28 | "InstallAdminPackage", | ||
29 | "InstallExecute", | ||
30 | "InstallExecuteAgain", | ||
31 | "InstallFiles", | ||
32 | "InstallFinalize", | ||
33 | "InstallInitialize", | ||
34 | "InstallODBC", | ||
35 | "InstallServices", | ||
36 | "InstallSFPCatalogFile", | ||
37 | "InstallValidate", | ||
38 | "IsolateComponents", | ||
39 | "LaunchConditions", | ||
40 | "MigrateFeatureStates", | ||
41 | "MoveFiles", | ||
42 | "MsiConfigureServices", | ||
43 | "MsiPublishAssemblies", | ||
44 | "MsiUnpublishAssemblies", | ||
45 | "PatchFiles", | ||
46 | "ProcessComponents", | ||
47 | "PublishComponents", | ||
48 | "PublishFeatures", | ||
49 | "PublishProduct", | ||
50 | "RegisterClassInfo", | ||
51 | "RegisterComPlus", | ||
52 | "RegisterExtensionInfo", | ||
53 | "RegisterFonts", | ||
54 | "RegisterMIMEInfo", | ||
55 | "RegisterProduct", | ||
56 | "RegisterProgIdInfo", | ||
57 | "RegisterTypeLibraries", | ||
58 | "RegisterUser", | ||
59 | "RemoveDuplicateFiles", | ||
60 | "RemoveEnvironmentStrings", | ||
61 | "RemoveExistingProducts", | ||
62 | "RemoveFiles", | ||
63 | "RemoveFolders", | ||
64 | "RemoveIniValues", | ||
65 | "RemoveODBC", | ||
66 | "RemoveRegistryValues", | ||
67 | "RemoveShortcuts", | ||
68 | "ResolveSource", | ||
69 | "RMCCPSearch", | ||
70 | "ScheduleReboot", | ||
71 | "SelfRegModules", | ||
72 | "SelfUnregModules", | ||
73 | "SetODBCFolders", | ||
74 | "StartServices", | ||
75 | "StopServices", | ||
76 | "UnpublishComponents", | ||
77 | "UnpublishFeatures", | ||
78 | "UnregisterClassInfo", | ||
79 | "UnregisterComPlus", | ||
80 | "UnregisterExtensionInfo", | ||
81 | "UnregisterFonts", | ||
82 | "UnregisterMIMEInfo", | ||
83 | "UnregisterProgIdInfo", | ||
84 | "UnregisterTypeLibraries", | ||
85 | "ValidateProductID", | ||
86 | "WriteEnvironmentStrings", | ||
87 | "WriteIniValues", | ||
88 | "WriteRegistryValues", | ||
89 | }; | ||
90 | |||
91 | private static readonly WixActionTuple[] standardActions = new[] | ||
92 | { | ||
93 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
94 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
95 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallInitialize", AccessModifier.Public)) { Action="InstallInitialize", Sequence=1500, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
96 | |||
97 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallExecute", AccessModifier.Public)) { Action="InstallExecute", Sequence=6500, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, | ||
98 | |||
99 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallExecuteAgain", AccessModifier.Public)) { Action="InstallExecuteAgain", Sequence=6550, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, | ||
100 | |||
101 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
102 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
103 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallFinalize", AccessModifier.Public)) { Action="InstallFinalize", Sequence=6600, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
104 | |||
105 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallFiles", AccessModifier.Public)) { Action="InstallFiles", Sequence=4000, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
106 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallFiles", AccessModifier.Public)) { Action="InstallFiles", Sequence=4000, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
107 | |||
108 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallAdminPackage", AccessModifier.Public)) { Action="InstallAdminPackage", Sequence=3900, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
109 | |||
110 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
111 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
112 | new WixActionTuple(null, new Identifier("InstallUISequence/FileCost", AccessModifier.Public)) { Action="FileCost", Sequence=900, SequenceTable=SequenceTable.InstallUISequence }, | ||
113 | |||
114 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
115 | new WixActionTuple(null, new Identifier("AdminUISequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdminUISequence }, | ||
116 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
117 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
118 | new WixActionTuple(null, new Identifier("InstallUISequence/CostInitialize", AccessModifier.Public)) { Action="CostInitialize", Sequence=800, SequenceTable=SequenceTable.InstallUISequence }, | ||
119 | |||
120 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
121 | new WixActionTuple(null, new Identifier("AdminUISequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdminUISequence }, | ||
122 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
123 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
124 | new WixActionTuple(null, new Identifier("InstallUISequence/CostFinalize", AccessModifier.Public)) { Action="CostFinalize", Sequence=1000, SequenceTable=SequenceTable.InstallUISequence }, | ||
125 | |||
126 | new WixActionTuple(null, new Identifier("AdminExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.AdminExecuteSequence }, | ||
127 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
128 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/InstallValidate", AccessModifier.Public)) { Action="InstallValidate", Sequence=1400, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
129 | |||
130 | new WixActionTuple(null, new Identifier("AdminUISequence/ExecuteAction", AccessModifier.Public)) { Action="ExecuteAction", Sequence=1300, SequenceTable=SequenceTable.AdminUISequence }, | ||
131 | new WixActionTuple(null, new Identifier("InstallUISequence/ExecuteAction", AccessModifier.Public)) { Action="ExecuteAction", Sequence=1300, SequenceTable=SequenceTable.InstallUISequence }, | ||
132 | |||
133 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/CreateShortcuts", AccessModifier.Public)) { Action="CreateShortcuts", Sequence=4500, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
134 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/CreateShortcuts", AccessModifier.Public)) { Action="CreateShortcuts", Sequence=4500, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
135 | |||
136 | new WixActionTuple(null, new Identifier("AdvtExecuteSequence/MsiPublishAssemblies", AccessModifier.Public)) { Action="MsiPublishAssemblies", Sequence=6250, SequenceTable=SequenceTable.AdvtExecuteSequence }, | ||
137 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/MsiPublishAssemblies", AccessModifier.Public)) { Action="MsiPublishAssemblies", Sequence=6250, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
138 | |||
139 | //<action name="PublishComponents" sequence="6200" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
140 | //<action name="PublishFeatures" sequence="6300" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
141 | //<action name="PublishProduct" sequence="6400" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
142 | //<action name="RegisterClassInfo" sequence="4600" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
143 | //<action name="RegisterExtensionInfo" sequence="4700" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
144 | //<action name="RegisterMIMEInfo" sequence="4900" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
145 | //<action name="RegisterProgIdInfo" sequence="4800" AdvtExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
146 | //<action name="AllocateRegistrySpace" condition="NOT Installed" sequence="1550" InstallExecuteSequence="yes" /> | ||
147 | //<action name="AppSearch" sequence="50" InstallExecuteSequence="yes" InstallUISequence="yes" /> | ||
148 | //<action name="BindImage" sequence="4300" InstallExecuteSequence="yes" /> | ||
149 | //<action name="CreateFolders" sequence="3700" InstallExecuteSequence="yes" /> | ||
150 | //<action name="DuplicateFiles" sequence="4210" InstallExecuteSequence="yes" /> | ||
151 | //<action name="FindRelatedProducts" sequence="25" InstallExecuteSequence="yes" InstallUISequence="yes" /> | ||
152 | //<action name="InstallODBC" sequence="5400" InstallExecuteSequence="yes" /> | ||
153 | //<action name="InstallServices" condition="VersionNT" sequence="5800" InstallExecuteSequence="yes" /> | ||
154 | //<action name="MsiConfigureServices" condition="VersionNT>=600" sequence="5850" InstallExecuteSequence="yes" /> | ||
155 | //<action name="IsolateComponents" sequence="950" InstallExecuteSequence="yes" InstallUISequence="yes" /> | ||
156 | //<action name="LaunchConditions" sequence="100" AdminExecuteSequence="yes" AdminUISequence="yes" InstallExecuteSequence="yes" InstallUISequence="yes" /> | ||
157 | //<action name="MigrateFeatureStates" sequence="1200" InstallExecuteSequence="yes" InstallUISequence="yes" /> | ||
158 | //<action name="MoveFiles" sequence="3800" InstallExecuteSequence="yes" /> | ||
159 | //<action name="PatchFiles" sequence="4090" AdminExecuteSequence="yes" InstallExecuteSequence="yes" /> | ||
160 | //<action name="ProcessComponents" sequence="1600" InstallExecuteSequence="yes" /> | ||
161 | //<action name="RegisterComPlus" sequence="5700" InstallExecuteSequence="yes" /> | ||
162 | //<action name="RegisterFonts" sequence="5300" InstallExecuteSequence="yes" /> | ||
163 | //<action name="RegisterProduct" sequence="6100" InstallExecuteSequence="yes" /> | ||
164 | //<action name="RegisterTypeLibraries" sequence="5500" InstallExecuteSequence="yes" /> | ||
165 | //<action name="RegisterUser" sequence="6000" InstallExecuteSequence="yes" /> | ||
166 | //<action name="RemoveDuplicateFiles" sequence="3400" InstallExecuteSequence="yes" /> | ||
167 | //<action name="RemoveEnvironmentStrings" sequence="3300" InstallExecuteSequence="yes" /> | ||
168 | //<action name="RemoveFiles" sequence="3500" InstallExecuteSequence="yes" /> | ||
169 | //<action name="RemoveFolders" sequence="3600" InstallExecuteSequence="yes" /> | ||
170 | //<action name="RemoveIniValues" sequence="3100" InstallExecuteSequence="yes" /> | ||
171 | //<action name="RemoveODBC" sequence="2400" InstallExecuteSequence="yes" /> | ||
172 | //<action name="RemoveRegistryValues" sequence="2600" InstallExecuteSequence="yes" /> | ||
173 | //<action name="RemoveShortcuts" sequence="3200" InstallExecuteSequence="yes" /> | ||
174 | //<action name="SelfRegModules" sequence="5600" InstallExecuteSequence="yes" /> | ||
175 | //<action name="SelfUnregModules" sequence="2200" InstallExecuteSequence="yes" /> | ||
176 | //<action name="SetODBCFolders" sequence="1100" InstallExecuteSequence="yes" /> | ||
177 | |||
178 | |||
179 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/CCPSearch", AccessModifier.Public)) { Action="CCPSearch", Sequence=500, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, | ||
180 | new WixActionTuple(null, new Identifier("InstallUISequence/CCPSearch", AccessModifier.Public)) { Action="CCPSearch", Sequence=500, SequenceTable=SequenceTable.InstallUISequence, Condition="NOT Installed" }, | ||
181 | |||
182 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/DeleteServices", AccessModifier.Public)) { Action="DeleteServices", Sequence=2000, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" }, | ||
183 | |||
184 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/RMCCPSearch", AccessModifier.Public)) { Action="RMCCPSearch", Sequence=600, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="NOT Installed" }, | ||
185 | new WixActionTuple(null, new Identifier("InstallUISequence/RMCCPSearch", AccessModifier.Public)) { Action="RMCCPSearch", Sequence=600, SequenceTable=SequenceTable.InstallUISequence, Condition="NOT Installed" }, | ||
186 | |||
187 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/StartServices", AccessModifier.Public)) { Action="StartServices", Sequence=5900, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" }, | ||
188 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/StopServices", AccessModifier.Public)) { Action="StopServices", Sequence=1900, SequenceTable=SequenceTable.InstallExecuteSequence, Condition="VersionNT" }, | ||
189 | |||
190 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/MsiUnpublishAssemblies", AccessModifier.Public)) { Action="MsiUnpublishAssemblies", Sequence=1750, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
191 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnpublishComponents", AccessModifier.Public)) { Action="UnpublishComponents", Sequence=1700, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
192 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnpublishFeatures", AccessModifier.Public)) { Action="UnpublishFeatures", Sequence=1800, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
193 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterClassInfo", AccessModifier.Public)) { Action="UnregisterClassInfo", Sequence=2700, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
194 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterComPlus", AccessModifier.Public)) { Action="UnregisterComPlus", Sequence=2100, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
195 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterExtensionInfo", AccessModifier.Public)) { Action="UnregisterExtensionInfo", Sequence=2800, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
196 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterFonts", AccessModifier.Public)) { Action="UnregisterFonts", Sequence=2500, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
197 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterMIMEInfo", AccessModifier.Public)) { Action="UnregisterMIMEInfo", Sequence=3000, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
198 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterProgIdInfo", AccessModifier.Public)) { Action="UnregisterProgIdInfo", Sequence=2900, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
199 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/UnregisterTypeLibraries", AccessModifier.Public)) { Action="UnregisterTypeLibraries", Sequence=2300, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
200 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/ValidateProductID", AccessModifier.Public)) { Action="ValidateProductID", Sequence=700, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
201 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteEnvironmentStrings", AccessModifier.Public)) { Action="WriteEnvironmentStrings", Sequence=5200, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
202 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteIniValues", AccessModifier.Public)) { Action="WriteIniValues", Sequence=5100, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
203 | new WixActionTuple(null, new Identifier("InstallExecuteSequence/WriteRegistryValues", AccessModifier.Public)) { Action="WriteRegistryValues", Sequence=5000, SequenceTable=SequenceTable.InstallExecuteSequence }, | ||
204 | }; | ||
205 | |||
206 | private static readonly HashSet<string> standardDirectories = new HashSet<string> | ||
207 | { | ||
208 | "TARGETDIR", | ||
209 | "AdminToolsFolder", | ||
210 | "AppDataFolder", | ||
211 | "CommonAppDataFolder", | ||
212 | "CommonFilesFolder", | ||
213 | "DesktopFolder", | ||
214 | "FavoritesFolder", | ||
215 | "FontsFolder", | ||
216 | "LocalAppDataFolder", | ||
217 | "MyPicturesFolder", | ||
218 | "PersonalFolder", | ||
219 | "ProgramFilesFolder", | ||
220 | "ProgramMenuFolder", | ||
221 | "SendToFolder", | ||
222 | "StartMenuFolder", | ||
223 | "StartupFolder", | ||
224 | "System16Folder", | ||
225 | "SystemFolder", | ||
226 | "TempFolder", | ||
227 | "TemplateFolder", | ||
228 | "WindowsFolder", | ||
229 | "CommonFiles64Folder", | ||
230 | "ProgramFiles64Folder", | ||
231 | "System64Folder", | ||
232 | "NetHoodFolder", | ||
233 | "PrintHoodFolder", | ||
234 | "RecentFolder", | ||
235 | "WindowsVolume", | ||
236 | }; | ||
237 | |||
238 | /// <summary> | ||
239 | /// Find out if an action is a standard action. | ||
240 | /// </summary> | ||
241 | /// <param name="actionName">Name of the action.</param> | ||
242 | /// <returns>true if the action is standard, false otherwise.</returns> | ||
243 | public static bool IsStandardAction(string actionName) | ||
244 | { | ||
245 | return standardActionNames.Contains(actionName); | ||
246 | } | ||
247 | |||
248 | public static WixActionTuple[] StandardActions() => standardActions; | ||
249 | |||
250 | /// <summary> | ||
251 | /// Find out if a directory is a standard directory. | ||
252 | /// </summary> | ||
253 | /// <param name="directoryName">Name of the directory.</param> | ||
254 | /// <returns>true if the directory is standard, false otherwise.</returns> | ||
255 | public static bool IsStandardDirectory(string directoryName) | ||
256 | { | ||
257 | return standardDirectories.Contains(directoryName); | ||
258 | } | ||
259 | } | ||
260 | } | ||
diff --git a/src/WixToolset.Core/WixStrings.Designer.cs b/src/WixToolset.Core/WixStrings.Designer.cs index 75e2b908..36e64267 100644 --- a/src/WixToolset.Core/WixStrings.Designer.cs +++ b/src/WixToolset.Core/WixStrings.Designer.cs | |||
@@ -163,7 +163,7 @@ namespace WixToolset { | |||
163 | /// <summary> | 163 | /// <summary> |
164 | /// Looks up a localized string similar to Found an ActionRow with a non-existent {0} action: {1}.. | 164 | /// Looks up a localized string similar to Found an ActionRow with a non-existent {0} action: {1}.. |
165 | /// </summary> | 165 | /// </summary> |
166 | internal static string EXP_FoundActionRowWinNonExistentAction { | 166 | public static string EXP_FoundActionRowWinNonExistentAction { |
167 | get { | 167 | get { |
168 | return ResourceManager.GetString("EXP_FoundActionRowWinNonExistentAction", resourceCulture); | 168 | return ResourceManager.GetString("EXP_FoundActionRowWinNonExistentAction", resourceCulture); |
169 | } | 169 | } |
@@ -172,7 +172,7 @@ namespace WixToolset { | |||
172 | /// <summary> | 172 | /// <summary> |
173 | /// Looks up a localized string similar to Found an ActionRow with no Sequence, Before, or After column set.. | 173 | /// Looks up a localized string similar to Found an ActionRow with no Sequence, Before, or After column set.. |
174 | /// </summary> | 174 | /// </summary> |
175 | internal static string EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet { | 175 | public static string EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet { |
176 | get { | 176 | get { |
177 | return ResourceManager.GetString("EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet", resourceCulture); | 177 | return ResourceManager.GetString("EXP_FoundActionRowWithNoSequenceBeforeOrAfterColumnSet", resourceCulture); |
178 | } | 178 | } |
diff --git a/src/WixToolset.Data.WindowsInstaller/Data/tables.xml b/src/WixToolset.Data.WindowsInstaller/Data/tables.xml index 280d87a8..e4b5e954 100644 --- a/src/WixToolset.Data.WindowsInstaller/Data/tables.xml +++ b/src/WixToolset.Data.WindowsInstaller/Data/tables.xml | |||
@@ -1468,7 +1468,7 @@ | |||
1468 | <columnDefinition name="PatchGroup" type="number" length="4" /> | 1468 | <columnDefinition name="PatchGroup" type="number" length="4" /> |
1469 | <columnDefinition name="Attributes" type="number" length="4"/> | 1469 | <columnDefinition name="Attributes" type="number" length="4"/> |
1470 | <columnDefinition name="PatchAttributes" type="number" length="4" nullable="yes"/> | 1470 | <columnDefinition name="PatchAttributes" type="number" length="4" nullable="yes"/> |
1471 | <columnDefinition name="DeltaPatchHeaderSource" type="string" length="0"/> | 1471 | <columnDefinition name="DeltaPatchHeaderSource" type="string" length="0" nullable="yes"/> |
1472 | </tableDefinition> | 1472 | </tableDefinition> |
1473 | <tableDefinition name="WixBindUpdatedFiles" unreal="yes"> | 1473 | <tableDefinition name="WixBindUpdatedFiles" unreal="yes"> |
1474 | <columnDefinition name="File_" type="string" length="0" primaryKey="yes" modularize="column" keyTable="File" keyColumn="1" category="identifier" /> | 1474 | <columnDefinition name="File_" type="string" length="0" primaryKey="yes" modularize="column" keyTable="File" keyColumn="1" category="identifier" /> |
diff --git a/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs b/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs index a0cc5302..5756db71 100644 --- a/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs +++ b/src/WixToolset.Data.WindowsInstaller/RowDictionary.cs | |||
@@ -77,8 +77,7 @@ namespace WixToolset.Data | |||
77 | /// <returns>Row or null if key is not found.</returns> | 77 | /// <returns>Row or null if key is not found.</returns> |
78 | public T Get(string key) | 78 | public T Get(string key) |
79 | { | 79 | { |
80 | T result; | 80 | return this.TryGetValue(key, out var result) ? result : null; |
81 | return this.TryGetValue(key, out result) ? result : null; | ||
82 | } | 81 | } |
83 | } | 82 | } |
84 | } | 83 | } |
diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs b/src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs deleted file mode 100644 index 964e1caa..00000000 --- a/src/WixToolset.Data.WindowsInstaller/Rows/SymbolPathType.cs +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Data.Rows | ||
4 | { | ||
5 | /// <summary> | ||
6 | /// The types that the WixDeltaPatchSymbolPaths table can hold. | ||
7 | /// </summary> | ||
8 | /// <remarks>The order of these values is important since WixDeltaPatchSymbolPaths are sorted by this type.</remarks> | ||
9 | public enum SymbolPathType | ||
10 | { | ||
11 | File, | ||
12 | Component, | ||
13 | Directory, | ||
14 | Media, | ||
15 | Product | ||
16 | }; | ||
17 | } | ||
diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs index 3009e59d..d1be706e 100644 --- a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRow.cs | |||
@@ -8,27 +8,28 @@ namespace WixToolset.Data.Rows | |||
8 | using System.Globalization; | 8 | using System.Globalization; |
9 | using System.Xml; | 9 | using System.Xml; |
10 | using System.Xml.Schema; | 10 | using System.Xml.Schema; |
11 | using WixToolset.Data.Tuples; | ||
11 | 12 | ||
12 | /// <summary> | 13 | /// <summary> |
13 | /// The Sequence tables that actions may belong to. | 14 | /// The Sequence tables that actions may belong to. |
14 | /// </summary> | 15 | /// </summary> |
15 | public enum SequenceTable | 16 | //public enum SequenceTable |
16 | { | 17 | //{ |
17 | /// <summary>AdminUISequence</summary> | 18 | // /// <summary>AdminUISequence</summary> |
18 | AdminUISequence, | 19 | // AdminUISequence, |
19 | 20 | ||
20 | /// <summary>AdminExecuteSequence</summary> | 21 | // /// <summary>AdminExecuteSequence</summary> |
21 | AdminExecuteSequence, | 22 | // AdminExecuteSequence, |
22 | 23 | ||
23 | /// <summary>AdvtExecuteSequence</summary> | 24 | // /// <summary>AdvtExecuteSequence</summary> |
24 | AdvtExecuteSequence, | 25 | // AdvtExecuteSequence, |
25 | 26 | ||
26 | /// <summary>InstallUISequence</summary> | 27 | // /// <summary>InstallUISequence</summary> |
27 | InstallUISequence, | 28 | // InstallUISequence, |
28 | 29 | ||
29 | /// <summary>InstallExecuteSequence</summary> | 30 | // /// <summary>InstallExecuteSequence</summary> |
30 | InstallExecuteSequence | 31 | // InstallExecuteSequence |
31 | } | 32 | //} |
32 | 33 | ||
33 | /// <summary> | 34 | /// <summary> |
34 | /// Specialization of a row for the sequence tables. | 35 | /// Specialization of a row for the sequence tables. |
@@ -55,15 +56,15 @@ namespace WixToolset.Data.Rows | |||
55 | /// <param name="action">The name of the standard action.</param> | 56 | /// <param name="action">The name of the standard action.</param> |
56 | /// <param name="condition">The condition of the standard action.</param> | 57 | /// <param name="condition">The condition of the standard action.</param> |
57 | /// <param name="sequence">The suggested sequence number of the standard action.</param> | 58 | /// <param name="sequence">The suggested sequence number of the standard action.</param> |
58 | private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) : | 59 | //private WixActionRow(SequenceTable sequenceTable, string action, string condition, int sequence) : |
59 | base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"]) | 60 | // base(null, WindowsInstallerStandard.GetTableDefinitions()["WixAction"]) |
60 | { | 61 | //{ |
61 | this.SequenceTable = sequenceTable; | 62 | // this.SequenceTable = sequenceTable; |
62 | this.Action = action; | 63 | // this.Action = action; |
63 | this.Condition = condition; | 64 | // this.Condition = condition; |
64 | this.Sequence = sequence; | 65 | // this.Sequence = sequence; |
65 | this.Overridable = true; // all standard actions are overridable by default | 66 | // this.Overridable = true; // all standard actions are overridable by default |
66 | } | 67 | //} |
67 | 68 | ||
68 | /// <summary> | 69 | /// <summary> |
69 | /// Instantiates an ActionRow by copying data from another ActionRow. | 70 | /// Instantiates an ActionRow by copying data from another ActionRow. |
@@ -296,13 +297,15 @@ namespace WixToolset.Data.Rows | |||
296 | WixActionRow[] actionRows = new WixActionRow[sequenceCount]; | 297 | WixActionRow[] actionRows = new WixActionRow[sequenceCount]; |
297 | for (int i = 0; i < sequenceCount; i++) | 298 | for (int i = 0; i < sequenceCount; i++) |
298 | { | 299 | { |
299 | WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); | 300 | //WixActionRow actionRow = new WixActionRow(sequenceTables[i], id, condition, sequence); |
300 | actionRows[i] = actionRow; | 301 | //actionRows[i] = actionRow; |
302 | throw new NotImplementedException(); | ||
301 | } | 303 | } |
302 | 304 | ||
303 | return actionRows; | 305 | return actionRows; |
304 | } | 306 | } |
305 | 307 | ||
308 | #if DEAD_CODE | ||
306 | /// <summary> | 309 | /// <summary> |
307 | /// Determines whether this ActionRow contains the specified ActionRow as a child in its dependency tree. | 310 | /// Determines whether this ActionRow contains the specified ActionRow as a child in its dependency tree. |
308 | /// </summary> | 311 | /// </summary> |
@@ -370,5 +373,6 @@ namespace WixToolset.Data.Rows | |||
370 | } | 373 | } |
371 | } | 374 | } |
372 | } | 375 | } |
376 | #endif | ||
373 | } | 377 | } |
374 | } | 378 | } |
diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs index 513a104f..9fab6b5d 100644 --- a/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixActionRowCollection.cs | |||
@@ -6,6 +6,7 @@ namespace WixToolset.Data.Rows | |||
6 | using System.Collections; | 6 | using System.Collections; |
7 | using System.Diagnostics; | 7 | using System.Diagnostics; |
8 | using System.Xml; | 8 | using System.Xml; |
9 | using WixToolset.Data.Tuples; | ||
9 | 10 | ||
10 | /// <summary> | 11 | /// <summary> |
11 | /// A collection of action rows sorted by their sequence table and action name. | 12 | /// A collection of action rows sorted by their sequence table and action name. |
diff --git a/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs b/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs index b6c0b840..3be5a56d 100644 --- a/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs +++ b/src/WixToolset.Data.WindowsInstaller/Rows/WixDeltaPatchSymbolPathsRow.cs | |||
@@ -2,6 +2,8 @@ | |||
2 | 2 | ||
3 | namespace WixToolset.Data.Rows | 3 | namespace WixToolset.Data.Rows |
4 | { | 4 | { |
5 | using WixToolset.Data.Tuples; | ||
6 | |||
5 | /// <summary> | 7 | /// <summary> |
6 | /// Specialization of a row for the WixDeltaPatchSymbolPaths table. | 8 | /// Specialization of a row for the WixDeltaPatchSymbolPaths table. |
7 | /// </summary> | 9 | /// </summary> |
diff --git a/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs b/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs index 553f0eaa..26d56387 100644 --- a/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs +++ b/src/WixToolset.Data.WindowsInstaller/TableDefinitionCollection.cs | |||
@@ -69,6 +69,17 @@ namespace WixToolset.Data | |||
69 | } | 69 | } |
70 | 70 | ||
71 | /// <summary> | 71 | /// <summary> |
72 | /// Tries to get a table definition by name. | ||
73 | /// </summary> | ||
74 | /// <param name="tableName">Name of table to locate.</param> | ||
75 | /// <param name="table">Table definition if found.</param> | ||
76 | /// <returns>True if table definition was found otherwise false.</returns> | ||
77 | public bool TryGet(string tableName, out TableDefinition table) | ||
78 | { | ||
79 | return this.collection.TryGetValue(tableName, out table); | ||
80 | } | ||
81 | |||
82 | /// <summary> | ||
72 | /// Load a table definition collection from an XmlReader. | 83 | /// Load a table definition collection from an XmlReader. |
73 | /// </summary> | 84 | /// </summary> |
74 | /// <param name="reader">Reader to get data from.</param> | 85 | /// <param name="reader">Reader to get data from.</param> |
diff --git a/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs b/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs deleted file mode 100644 index ee4a5103..00000000 --- a/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandard.cs +++ /dev/null | |||
@@ -1,442 +0,0 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Data | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | using System.Reflection; | ||
7 | using System.Xml; | ||
8 | using WixToolset.Data.Rows; | ||
9 | |||
10 | /// <summary> | ||
11 | /// Represents the Windows Installer standard objects. | ||
12 | /// </summary> | ||
13 | public static class WindowsInstallerStandard | ||
14 | { | ||
15 | private static readonly object lockObject = new object(); | ||
16 | |||
17 | private static TableDefinitionCollection tableDefinitions; | ||
18 | private static WixActionRowCollection standardActions; | ||
19 | |||
20 | private static HashSet<string> standardActionNames; | ||
21 | private static HashSet<string> standardDirectories; | ||
22 | private static HashSet<string> standardProperties; | ||
23 | |||
24 | /// <summary> | ||
25 | /// Gets the table definitions stored in this assembly. | ||
26 | /// </summary> | ||
27 | /// <returns>Table definition collection for tables stored in this assembly.</returns> | ||
28 | public static TableDefinitionCollection GetTableDefinitions() | ||
29 | { | ||
30 | lock (lockObject) | ||
31 | { | ||
32 | if (null == WindowsInstallerStandard.tableDefinitions) | ||
33 | { | ||
34 | using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.tables.xml"))) | ||
35 | { | ||
36 | tableDefinitions = TableDefinitionCollection.Load(reader); | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | |||
41 | return WindowsInstallerStandard.tableDefinitions; | ||
42 | } | ||
43 | |||
44 | /// <summary> | ||
45 | /// Gets the standard actions stored in this assembly. | ||
46 | /// </summary> | ||
47 | /// <returns>Collection of standard actions in this assembly.</returns> | ||
48 | public static WixActionRowCollection GetStandardActions() | ||
49 | { | ||
50 | lock (lockObject) | ||
51 | { | ||
52 | if (null == standardActions) | ||
53 | { | ||
54 | using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.actions.xml"))) | ||
55 | { | ||
56 | standardActions = WixActionRowCollection.Load(reader); | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
61 | return standardActions; | ||
62 | } | ||
63 | |||
64 | /// <summary> | ||
65 | /// Gets (and loads if not yet loaded) the list of standard MSI directories. | ||
66 | /// </summary> | ||
67 | /// <value>The list of standard MSI directories.</value> | ||
68 | public static HashSet<string> GetStandardDirectories() | ||
69 | { | ||
70 | lock (lockObject) | ||
71 | { | ||
72 | if (null == standardDirectories) | ||
73 | { | ||
74 | LoadStandardDirectories(); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | return standardDirectories; | ||
79 | } | ||
80 | |||
81 | /// <summary> | ||
82 | /// Find out if an action is a standard action. | ||
83 | /// </summary> | ||
84 | /// <param name="actionName">Name of the action.</param> | ||
85 | /// <returns>true if the action is standard, false otherwise.</returns> | ||
86 | public static bool IsStandardAction(string actionName) | ||
87 | { | ||
88 | lock (lockObject) | ||
89 | { | ||
90 | if (null == standardActionNames) | ||
91 | { | ||
92 | standardActionNames = new HashSet<string>(); | ||
93 | standardActionNames.Add("AllocateRegistrySpace"); | ||
94 | standardActionNames.Add("AppSearch"); | ||
95 | standardActionNames.Add("BindImage"); | ||
96 | standardActionNames.Add("CCPSearch"); | ||
97 | standardActionNames.Add("CostFinalize"); | ||
98 | standardActionNames.Add("CostInitialize"); | ||
99 | standardActionNames.Add("CreateFolders"); | ||
100 | standardActionNames.Add("CreateShortcuts"); | ||
101 | standardActionNames.Add("DeleteServices"); | ||
102 | standardActionNames.Add("DisableRollback"); | ||
103 | standardActionNames.Add("DuplicateFiles"); | ||
104 | standardActionNames.Add("ExecuteAction"); | ||
105 | standardActionNames.Add("FileCost"); | ||
106 | standardActionNames.Add("FindRelatedProducts"); | ||
107 | standardActionNames.Add("ForceReboot"); | ||
108 | standardActionNames.Add("InstallAdminPackage"); | ||
109 | standardActionNames.Add("InstallExecute"); | ||
110 | standardActionNames.Add("InstallExecuteAgain"); | ||
111 | standardActionNames.Add("InstallFiles"); | ||
112 | standardActionNames.Add("InstallFinalize"); | ||
113 | standardActionNames.Add("InstallInitialize"); | ||
114 | standardActionNames.Add("InstallODBC"); | ||
115 | standardActionNames.Add("InstallServices"); | ||
116 | standardActionNames.Add("InstallSFPCatalogFile"); | ||
117 | standardActionNames.Add("InstallValidate"); | ||
118 | standardActionNames.Add("IsolateComponents"); | ||
119 | standardActionNames.Add("LaunchConditions"); | ||
120 | standardActionNames.Add("MigrateFeatureStates"); | ||
121 | standardActionNames.Add("MoveFiles"); | ||
122 | standardActionNames.Add("MsiConfigureServices"); | ||
123 | standardActionNames.Add("MsiPublishAssemblies"); | ||
124 | standardActionNames.Add("MsiUnpublishAssemblies"); | ||
125 | standardActionNames.Add("PatchFiles"); | ||
126 | standardActionNames.Add("ProcessComponents"); | ||
127 | standardActionNames.Add("PublishComponents"); | ||
128 | standardActionNames.Add("PublishFeatures"); | ||
129 | standardActionNames.Add("PublishProduct"); | ||
130 | standardActionNames.Add("RegisterClassInfo"); | ||
131 | standardActionNames.Add("RegisterComPlus"); | ||
132 | standardActionNames.Add("RegisterExtensionInfo"); | ||
133 | standardActionNames.Add("RegisterFonts"); | ||
134 | standardActionNames.Add("RegisterMIMEInfo"); | ||
135 | standardActionNames.Add("RegisterProduct"); | ||
136 | standardActionNames.Add("RegisterProgIdInfo"); | ||
137 | standardActionNames.Add("RegisterTypeLibraries"); | ||
138 | standardActionNames.Add("RegisterUser"); | ||
139 | standardActionNames.Add("RemoveDuplicateFiles"); | ||
140 | standardActionNames.Add("RemoveEnvironmentStrings"); | ||
141 | standardActionNames.Add("RemoveExistingProducts"); | ||
142 | standardActionNames.Add("RemoveFiles"); | ||
143 | standardActionNames.Add("RemoveFolders"); | ||
144 | standardActionNames.Add("RemoveIniValues"); | ||
145 | standardActionNames.Add("RemoveODBC"); | ||
146 | standardActionNames.Add("RemoveRegistryValues"); | ||
147 | standardActionNames.Add("RemoveShortcuts"); | ||
148 | standardActionNames.Add("ResolveSource"); | ||
149 | standardActionNames.Add("RMCCPSearch"); | ||
150 | standardActionNames.Add("ScheduleReboot"); | ||
151 | standardActionNames.Add("SelfRegModules"); | ||
152 | standardActionNames.Add("SelfUnregModules"); | ||
153 | standardActionNames.Add("SetODBCFolders"); | ||
154 | standardActionNames.Add("StartServices"); | ||
155 | standardActionNames.Add("StopServices"); | ||
156 | standardActionNames.Add("UnpublishComponents"); | ||
157 | standardActionNames.Add("UnpublishFeatures"); | ||
158 | standardActionNames.Add("UnregisterClassInfo"); | ||
159 | standardActionNames.Add("UnregisterComPlus"); | ||
160 | standardActionNames.Add("UnregisterExtensionInfo"); | ||
161 | standardActionNames.Add("UnregisterFonts"); | ||
162 | standardActionNames.Add("UnregisterMIMEInfo"); | ||
163 | standardActionNames.Add("UnregisterProgIdInfo"); | ||
164 | standardActionNames.Add("UnregisterTypeLibraries"); | ||
165 | standardActionNames.Add("ValidateProductID"); | ||
166 | standardActionNames.Add("WriteEnvironmentStrings"); | ||
167 | standardActionNames.Add("WriteIniValues"); | ||
168 | standardActionNames.Add("WriteRegistryValues"); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | return standardActionNames.Contains(actionName); | ||
173 | } | ||
174 | |||
175 | /// <summary> | ||
176 | /// Find out if a directory is a standard directory. | ||
177 | /// </summary> | ||
178 | /// <param name="directoryName">Name of the directory.</param> | ||
179 | /// <returns>true if the directory is standard, false otherwise.</returns> | ||
180 | public static bool IsStandardDirectory(string directoryName) | ||
181 | { | ||
182 | lock (lockObject) | ||
183 | { | ||
184 | if (null == standardDirectories) | ||
185 | { | ||
186 | LoadStandardDirectories(); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | return standardDirectories.Contains(directoryName); | ||
191 | } | ||
192 | |||
193 | /// <summary> | ||
194 | /// Find out if a property is a standard property. | ||
195 | /// References: | ||
196 | /// Title: Property Reference [Windows Installer]: | ||
197 | /// URL: http://msdn.microsoft.com/library/en-us/msi/setup/property_reference.asp | ||
198 | /// </summary> | ||
199 | /// <param name="propertyName">Name of the property.</param> | ||
200 | /// <returns>true if a property is standard, false otherwise.</returns> | ||
201 | public static bool IsStandardProperty(string propertyName) | ||
202 | { | ||
203 | lock (lockObject) | ||
204 | { | ||
205 | if (null == standardProperties) | ||
206 | { | ||
207 | standardProperties = new HashSet<string>(); | ||
208 | standardProperties.Add("~"); // REG_MULTI_SZ/NULL marker | ||
209 | standardProperties.Add("ACTION"); | ||
210 | standardProperties.Add("ADDDEFAULT"); | ||
211 | standardProperties.Add("ADDLOCAL"); | ||
212 | standardProperties.Add("ADDDSOURCE"); | ||
213 | standardProperties.Add("AdminProperties"); | ||
214 | standardProperties.Add("AdminUser"); | ||
215 | standardProperties.Add("ADVERTISE"); | ||
216 | standardProperties.Add("AFTERREBOOT"); | ||
217 | standardProperties.Add("AllowProductCodeMismatches"); | ||
218 | standardProperties.Add("AllowProductVersionMajorMismatches"); | ||
219 | standardProperties.Add("ALLUSERS"); | ||
220 | standardProperties.Add("Alpha"); | ||
221 | standardProperties.Add("ApiPatchingSymbolFlags"); | ||
222 | standardProperties.Add("ARPAUTHORIZEDCDFPREFIX"); | ||
223 | standardProperties.Add("ARPCOMMENTS"); | ||
224 | standardProperties.Add("ARPCONTACT"); | ||
225 | standardProperties.Add("ARPHELPLINK"); | ||
226 | standardProperties.Add("ARPHELPTELEPHONE"); | ||
227 | standardProperties.Add("ARPINSTALLLOCATION"); | ||
228 | standardProperties.Add("ARPNOMODIFY"); | ||
229 | standardProperties.Add("ARPNOREMOVE"); | ||
230 | standardProperties.Add("ARPNOREPAIR"); | ||
231 | standardProperties.Add("ARPPRODUCTIONICON"); | ||
232 | standardProperties.Add("ARPREADME"); | ||
233 | standardProperties.Add("ARPSIZE"); | ||
234 | standardProperties.Add("ARPSYSTEMCOMPONENT"); | ||
235 | standardProperties.Add("ARPULRINFOABOUT"); | ||
236 | standardProperties.Add("ARPURLUPDATEINFO"); | ||
237 | standardProperties.Add("AVAILABLEFREEREG"); | ||
238 | standardProperties.Add("BorderSize"); | ||
239 | standardProperties.Add("BorderTop"); | ||
240 | standardProperties.Add("CaptionHeight"); | ||
241 | standardProperties.Add("CCP_DRIVE"); | ||
242 | standardProperties.Add("ColorBits"); | ||
243 | standardProperties.Add("COMPADDLOCAL"); | ||
244 | standardProperties.Add("COMPADDSOURCE"); | ||
245 | standardProperties.Add("COMPANYNAME"); | ||
246 | standardProperties.Add("ComputerName"); | ||
247 | standardProperties.Add("CostingComplete"); | ||
248 | standardProperties.Add("Date"); | ||
249 | standardProperties.Add("DefaultUIFont"); | ||
250 | standardProperties.Add("DISABLEADVTSHORTCUTS"); | ||
251 | standardProperties.Add("DISABLEMEDIA"); | ||
252 | standardProperties.Add("DISABLEROLLBACK"); | ||
253 | standardProperties.Add("DiskPrompt"); | ||
254 | standardProperties.Add("DontRemoveTempFolderWhenFinished"); | ||
255 | standardProperties.Add("EnableUserControl"); | ||
256 | standardProperties.Add("EXECUTEACTION"); | ||
257 | standardProperties.Add("EXECUTEMODE"); | ||
258 | standardProperties.Add("FASTOEM"); | ||
259 | standardProperties.Add("FILEADDDEFAULT"); | ||
260 | standardProperties.Add("FILEADDLOCAL"); | ||
261 | standardProperties.Add("FILEADDSOURCE"); | ||
262 | standardProperties.Add("IncludeWholeFilesOnly"); | ||
263 | standardProperties.Add("Installed"); | ||
264 | standardProperties.Add("INSTALLLEVEL"); | ||
265 | standardProperties.Add("Intel"); | ||
266 | standardProperties.Add("Intel64"); | ||
267 | standardProperties.Add("IsAdminPackage"); | ||
268 | standardProperties.Add("LeftUnit"); | ||
269 | standardProperties.Add("LIMITUI"); | ||
270 | standardProperties.Add("ListOfPatchGUIDsToReplace"); | ||
271 | standardProperties.Add("ListOfTargetProductCode"); | ||
272 | standardProperties.Add("LOGACTION"); | ||
273 | standardProperties.Add("LogonUser"); | ||
274 | standardProperties.Add("Manufacturer"); | ||
275 | standardProperties.Add("MEDIAPACKAGEPATH"); | ||
276 | standardProperties.Add("MediaSourceDir"); | ||
277 | standardProperties.Add("MinimumRequiredMsiVersion"); | ||
278 | standardProperties.Add("MsiAMD64"); | ||
279 | standardProperties.Add("MSIAPRSETTINGSIDENTIFIER"); | ||
280 | standardProperties.Add("MSICHECKCRCS"); | ||
281 | standardProperties.Add("MSIDISABLERMRESTART"); | ||
282 | standardProperties.Add("MSIENFORCEUPGRADECOMPONENTRULES"); | ||
283 | standardProperties.Add("MSIFASTINSTALL"); | ||
284 | standardProperties.Add("MsiFileToUseToCreatePatchTables"); | ||
285 | standardProperties.Add("MsiHiddenProperties"); | ||
286 | standardProperties.Add("MSIINSTALLPERUSER"); | ||
287 | standardProperties.Add("MSIINSTANCEGUID"); | ||
288 | standardProperties.Add("MsiLogFileLocation"); | ||
289 | standardProperties.Add("MsiLogging"); | ||
290 | standardProperties.Add("MsiNetAssemblySupport"); | ||
291 | standardProperties.Add("MSINEWINSTANCE"); | ||
292 | standardProperties.Add("MSINODISABLEMEDIA"); | ||
293 | standardProperties.Add("MsiNTProductType"); | ||
294 | standardProperties.Add("MsiNTSuiteBackOffice"); | ||
295 | standardProperties.Add("MsiNTSuiteDataCenter"); | ||
296 | standardProperties.Add("MsiNTSuiteEnterprise"); | ||
297 | standardProperties.Add("MsiNTSuiteSmallBusiness"); | ||
298 | standardProperties.Add("MsiNTSuiteSmallBusinessRestricted"); | ||
299 | standardProperties.Add("MsiNTSuiteWebServer"); | ||
300 | standardProperties.Add("MsiNTSuitePersonal"); | ||
301 | standardProperties.Add("MsiPatchRemovalList"); | ||
302 | standardProperties.Add("MSIPATCHREMOVE"); | ||
303 | standardProperties.Add("MSIRESTARTMANAGERCONTROL"); | ||
304 | standardProperties.Add("MsiRestartManagerSessionKey"); | ||
305 | standardProperties.Add("MSIRMSHUTDOWN"); | ||
306 | standardProperties.Add("MsiRunningElevated"); | ||
307 | standardProperties.Add("MsiUIHideCancel"); | ||
308 | standardProperties.Add("MsiUIProgressOnly"); | ||
309 | standardProperties.Add("MsiUISourceResOnly"); | ||
310 | standardProperties.Add("MsiSystemRebootPending"); | ||
311 | standardProperties.Add("MsiWin32AssemblySupport"); | ||
312 | standardProperties.Add("NOCOMPANYNAME"); | ||
313 | standardProperties.Add("NOUSERNAME"); | ||
314 | standardProperties.Add("OLEAdvtSupport"); | ||
315 | standardProperties.Add("OptimizePatchSizeForLargeFiles"); | ||
316 | standardProperties.Add("OriginalDatabase"); | ||
317 | standardProperties.Add("OutOfDiskSpace"); | ||
318 | standardProperties.Add("OutOfNoRbDiskSpace"); | ||
319 | standardProperties.Add("ParentOriginalDatabase"); | ||
320 | standardProperties.Add("ParentProductCode"); | ||
321 | standardProperties.Add("PATCH"); | ||
322 | standardProperties.Add("PATCH_CACHE_DIR"); | ||
323 | standardProperties.Add("PATCH_CACHE_ENABLED"); | ||
324 | standardProperties.Add("PatchGUID"); | ||
325 | standardProperties.Add("PATCHNEWPACKAGECODE"); | ||
326 | standardProperties.Add("PATCHNEWSUMMARYCOMMENTS"); | ||
327 | standardProperties.Add("PATCHNEWSUMMARYSUBJECT"); | ||
328 | standardProperties.Add("PatchOutputPath"); | ||
329 | standardProperties.Add("PatchSourceList"); | ||
330 | standardProperties.Add("PhysicalMemory"); | ||
331 | standardProperties.Add("PIDKEY"); | ||
332 | standardProperties.Add("PIDTemplate"); | ||
333 | standardProperties.Add("Preselected"); | ||
334 | standardProperties.Add("PRIMARYFOLDER"); | ||
335 | standardProperties.Add("PrimaryVolumePath"); | ||
336 | standardProperties.Add("PrimaryVolumeSpaceAvailable"); | ||
337 | standardProperties.Add("PrimaryVolumeSpaceRemaining"); | ||
338 | standardProperties.Add("PrimaryVolumeSpaceRequired"); | ||
339 | standardProperties.Add("Privileged"); | ||
340 | standardProperties.Add("ProductCode"); | ||
341 | standardProperties.Add("ProductID"); | ||
342 | standardProperties.Add("ProductLanguage"); | ||
343 | standardProperties.Add("ProductName"); | ||
344 | standardProperties.Add("ProductState"); | ||
345 | standardProperties.Add("ProductVersion"); | ||
346 | standardProperties.Add("PROMPTROLLBACKCOST"); | ||
347 | standardProperties.Add("REBOOT"); | ||
348 | standardProperties.Add("REBOOTPROMPT"); | ||
349 | standardProperties.Add("RedirectedDllSupport"); | ||
350 | standardProperties.Add("REINSTALL"); | ||
351 | standardProperties.Add("REINSTALLMODE"); | ||
352 | standardProperties.Add("RemoveAdminTS"); | ||
353 | standardProperties.Add("REMOVE"); | ||
354 | standardProperties.Add("ReplacedInUseFiles"); | ||
355 | standardProperties.Add("RestrictedUserControl"); | ||
356 | standardProperties.Add("RESUME"); | ||
357 | standardProperties.Add("RollbackDisabled"); | ||
358 | standardProperties.Add("ROOTDRIVE"); | ||
359 | standardProperties.Add("ScreenX"); | ||
360 | standardProperties.Add("ScreenY"); | ||
361 | standardProperties.Add("SecureCustomProperties"); | ||
362 | standardProperties.Add("ServicePackLevel"); | ||
363 | standardProperties.Add("ServicePackLevelMinor"); | ||
364 | standardProperties.Add("SEQUENCE"); | ||
365 | standardProperties.Add("SharedWindows"); | ||
366 | standardProperties.Add("ShellAdvtSupport"); | ||
367 | standardProperties.Add("SHORTFILENAMES"); | ||
368 | standardProperties.Add("SourceDir"); | ||
369 | standardProperties.Add("SOURCELIST"); | ||
370 | standardProperties.Add("SystemLanguageID"); | ||
371 | standardProperties.Add("TARGETDIR"); | ||
372 | standardProperties.Add("TerminalServer"); | ||
373 | standardProperties.Add("TextHeight"); | ||
374 | standardProperties.Add("Time"); | ||
375 | standardProperties.Add("TRANSFORMS"); | ||
376 | standardProperties.Add("TRANSFORMSATSOURCE"); | ||
377 | standardProperties.Add("TRANSFORMSSECURE"); | ||
378 | standardProperties.Add("TTCSupport"); | ||
379 | standardProperties.Add("UILevel"); | ||
380 | standardProperties.Add("UpdateStarted"); | ||
381 | standardProperties.Add("UpgradeCode"); | ||
382 | standardProperties.Add("UPGRADINGPRODUCTCODE"); | ||
383 | standardProperties.Add("UserLanguageID"); | ||
384 | standardProperties.Add("USERNAME"); | ||
385 | standardProperties.Add("UserSID"); | ||
386 | standardProperties.Add("Version9X"); | ||
387 | standardProperties.Add("VersionDatabase"); | ||
388 | standardProperties.Add("VersionMsi"); | ||
389 | standardProperties.Add("VersionNT"); | ||
390 | standardProperties.Add("VersionNT64"); | ||
391 | standardProperties.Add("VirtualMemory"); | ||
392 | standardProperties.Add("WindowsBuild"); | ||
393 | standardProperties.Add("WindowsVolume"); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | return standardProperties.Contains(propertyName); | ||
398 | } | ||
399 | |||
400 | /// <summary> | ||
401 | /// Sets up a hashtable with the set of standard MSI directories | ||
402 | /// </summary> | ||
403 | private static void LoadStandardDirectories() | ||
404 | { | ||
405 | lock (lockObject) | ||
406 | { | ||
407 | if (null == standardDirectories) | ||
408 | { | ||
409 | standardDirectories = new HashSet<string>(); | ||
410 | standardDirectories.Add("TARGETDIR"); | ||
411 | standardDirectories.Add("AdminToolsFolder"); | ||
412 | standardDirectories.Add("AppDataFolder"); | ||
413 | standardDirectories.Add("CommonAppDataFolder"); | ||
414 | standardDirectories.Add("CommonFilesFolder"); | ||
415 | standardDirectories.Add("DesktopFolder"); | ||
416 | standardDirectories.Add("FavoritesFolder"); | ||
417 | standardDirectories.Add("FontsFolder"); | ||
418 | standardDirectories.Add("LocalAppDataFolder"); | ||
419 | standardDirectories.Add("MyPicturesFolder"); | ||
420 | standardDirectories.Add("PersonalFolder"); | ||
421 | standardDirectories.Add("ProgramFilesFolder"); | ||
422 | standardDirectories.Add("ProgramMenuFolder"); | ||
423 | standardDirectories.Add("SendToFolder"); | ||
424 | standardDirectories.Add("StartMenuFolder"); | ||
425 | standardDirectories.Add("StartupFolder"); | ||
426 | standardDirectories.Add("System16Folder"); | ||
427 | standardDirectories.Add("SystemFolder"); | ||
428 | standardDirectories.Add("TempFolder"); | ||
429 | standardDirectories.Add("TemplateFolder"); | ||
430 | standardDirectories.Add("WindowsFolder"); | ||
431 | standardDirectories.Add("CommonFiles64Folder"); | ||
432 | standardDirectories.Add("ProgramFiles64Folder"); | ||
433 | standardDirectories.Add("System64Folder"); | ||
434 | standardDirectories.Add("NetHoodFolder"); | ||
435 | standardDirectories.Add("PrintHoodFolder"); | ||
436 | standardDirectories.Add("RecentFolder"); | ||
437 | standardDirectories.Add("WindowsVolume"); | ||
438 | } | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | } | ||
diff --git a/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs b/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs new file mode 100644 index 00000000..cc6754c3 --- /dev/null +++ b/src/WixToolset.Data.WindowsInstaller/WindowsInstallerStandardInternal.cs | |||
@@ -0,0 +1,59 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Data | ||
4 | { | ||
5 | using System.Reflection; | ||
6 | using System.Xml; | ||
7 | using WixToolset.Data.Rows; | ||
8 | |||
9 | /// <summary> | ||
10 | /// Represents the Windows Installer standard objects. | ||
11 | /// </summary> | ||
12 | public static class WindowsInstallerStandardInternal | ||
13 | { | ||
14 | private static readonly object lockObject = new object(); | ||
15 | |||
16 | private static TableDefinitionCollection tableDefinitions; | ||
17 | private static WixActionRowCollection standardActions; | ||
18 | |||
19 | /// <summary> | ||
20 | /// Gets the table definitions stored in this assembly. | ||
21 | /// </summary> | ||
22 | /// <returns>Table definition collection for tables stored in this assembly.</returns> | ||
23 | public static TableDefinitionCollection GetTableDefinitions() | ||
24 | { | ||
25 | lock (lockObject) | ||
26 | { | ||
27 | if (null == WindowsInstallerStandardInternal.tableDefinitions) | ||
28 | { | ||
29 | using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.tables.xml"))) | ||
30 | { | ||
31 | WindowsInstallerStandardInternal.tableDefinitions = TableDefinitionCollection.Load(reader); | ||
32 | } | ||
33 | } | ||
34 | } | ||
35 | |||
36 | return WindowsInstallerStandardInternal.tableDefinitions; | ||
37 | } | ||
38 | |||
39 | /// <summary> | ||
40 | /// Gets the standard actions stored in this assembly. | ||
41 | /// </summary> | ||
42 | /// <returns>Collection of standard actions in this assembly.</returns> | ||
43 | public static WixActionRowCollection GetStandardActionRows() | ||
44 | { | ||
45 | lock (lockObject) | ||
46 | { | ||
47 | if (null == WindowsInstallerStandardInternal.standardActions) | ||
48 | { | ||
49 | using (XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("WixToolset.Data.WindowsInstaller.Data.actions.xml"))) | ||
50 | { | ||
51 | WindowsInstallerStandardInternal.standardActions = WixActionRowCollection.Load(reader); | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | return WindowsInstallerStandardInternal.standardActions; | ||
57 | } | ||
58 | } | ||
59 | } | ||
diff --git a/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs b/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs index 46d15ed8..4b4daeda 100644 --- a/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs +++ b/src/test/WixToolsetTest.CoreIntegrationFixture/ProgramFixture.cs | |||
@@ -26,18 +26,17 @@ namespace WixToolsetTest.CoreIntegrationFixture | |||
26 | var result = program.Run(new WixToolsetServiceProvider(), new[] { "build", "Package.wxs", "PackageComponents.wxs", "-loc", "Package.en-us.wxl", "-bindpath", "data", "-intermediateFolder", intermediateFolder, "-o", $@"{intermediateFolder}\bin\test.msi" }); | 26 | var result = program.Run(new WixToolsetServiceProvider(), new[] { "build", "Package.wxs", "PackageComponents.wxs", "-loc", "Package.en-us.wxl", "-bindpath", "data", "-intermediateFolder", intermediateFolder, "-o", $@"{intermediateFolder}\bin\test.msi" }); |
27 | 27 | ||
28 | Assert.Equal(0, result); | 28 | Assert.Equal(0, result); |
29 | #if FIXED_MSI_BACKEND | 29 | |
30 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); | 30 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); |
31 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); | 31 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); |
32 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt"))); | 32 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\MsiPackage\test.txt"))); |
33 | #else | 33 | |
34 | var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.msi")); | 34 | var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wir")); |
35 | Assert.Single(intermediate.Sections); | 35 | Assert.Single(intermediate.Sections); |
36 | 36 | ||
37 | var wixFile = intermediate.Sections.SelectMany(s => s.Tuples).OfType<WixFileTuple>().Single(); | 37 | var wixFile = intermediate.Sections.SelectMany(s => s.Tuples).OfType<WixFileTuple>().Single(); |
38 | Assert.Equal(@"data\test.txt", wixFile[WixFileTupleFields.Source].AsPath().Path); | 38 | Assert.Equal(@"data\test.txt", wixFile[WixFileTupleFields.Source].AsPath().Path); |
39 | Assert.Equal(@"test.txt", wixFile[WixFileTupleFields.Source].PreviousValue.AsPath().Path); | 39 | Assert.Equal(@"test.txt", wixFile[WixFileTupleFields.Source].PreviousValue.AsPath().Path); |
40 | #endif | ||
41 | } | 40 | } |
42 | } | 41 | } |
43 | } | 42 | } |