public void Execute() { RowDictionary <WixBundleExePackageRow> exePackages = new RowDictionary <WixBundleExePackageRow>(this.ExePackageTable); RowDictionary <WixBundleMsiPackageRow> msiPackages = new RowDictionary <WixBundleMsiPackageRow>(this.MsiPackageTable); RowDictionary <WixBundleMspPackageRow> mspPackages = new RowDictionary <WixBundleMspPackageRow>(this.MspPackageTable); RowDictionary <WixBundleMsuPackageRow> msuPackages = new RowDictionary <WixBundleMsuPackageRow>(this.MsuPackageTable); Dictionary <string, PackageFacade> facades = new Dictionary <string, PackageFacade>(this.PackageTable.Rows.Count); foreach (WixBundlePackageRow package in this.PackageTable.Rows) { string id = package.WixChainItemId; PackageFacade facade = null; switch (package.Type) { case WixBundlePackageType.Exe: facade = new PackageFacade(package, exePackages.Get(id)); break; case WixBundlePackageType.Msi: facade = new PackageFacade(package, msiPackages.Get(id)); break; case WixBundlePackageType.Msp: facade = new PackageFacade(package, mspPackages.Get(id)); break; case WixBundlePackageType.Msu: facade = new PackageFacade(package, msuPackages.Get(id)); break; } facades.Add(id, facade); } this.PackageFacades = facades; }
public ProcessMsuPackageCommand(PackageFacade facade, Dictionary <string, WixBundlePayloadSymbol> payloadSymbols) { this.AuthoredPayloads = payloadSymbols; this.Facade = facade; }
public ProcessMspPackageCommand(IMessaging messaging, IntermediateSection section, PackageFacade facade, Dictionary <string, WixBundlePayloadSymbol> payloadSymbols) { this.Messaging = messaging; this.AuthoredPayloads = payloadSymbols; this.Section = section; this.Facade = facade; }
public ProcessMsiPackageCommand(IWixToolsetServiceProvider serviceProvider, IEnumerable <IBurnBackendBinderExtension> backendExtensions, IntermediateSection section, PackageFacade facade, Dictionary <string, WixBundlePayloadSymbol> payloadSymbols) { this.Messaging = serviceProvider.GetService <IMessaging>(); this.BackendHelper = serviceProvider.GetService <IBackendHelper>(); this.PathResolver = serviceProvider.GetService <IPathResolver>(); this.BackendExtensions = backendExtensions; this.AuthoredPayloads = payloadSymbols; this.Section = section; this.Facade = facade; }
public void Execute() { List <PackageFacade> orderedFacades = new List <PackageFacade>(); List <WixBundleRollbackBoundaryRow> usedBoundaries = new List <WixBundleRollbackBoundaryRow>(); // Process the chain of packages to add them in the correct order // and assign the forward rollback boundaries as appropriate. Remember // rollback boundaries are authored as elements in the chain which // we re-interpret here to add them as attributes on the next available // package in the chain. Essentially we mark some packages as being // the start of a rollback boundary when installing and repairing. // We handle uninstall (aka: backwards) rollback boundaries after // we get these install/repair (aka: forward) rollback boundaries // defined. WixBundleRollbackBoundaryRow previousRollbackBoundary = null; WixBundleRollbackBoundaryRow lastRollbackBoundary = null; bool boundaryHadX86Package = false; foreach (WixGroupRow row in this.WixGroupTable.Rows) { if (ComplexReferenceChildType.Package == row.ChildType && ComplexReferenceParentType.PackageGroup == row.ParentType && "WixChain" == row.ParentId) { PackageFacade facade = null; if (PackageFacades.TryGetValue(row.ChildId, out facade)) { if (null != previousRollbackBoundary) { usedBoundaries.Add(previousRollbackBoundary); facade.Package.RollbackBoundary = previousRollbackBoundary.ChainPackageId; previousRollbackBoundary = null; boundaryHadX86Package = (facade.Package.x64 == YesNoType.Yes); } // Error if MSI transaction has x86 package preceding x64 packages if ((lastRollbackBoundary != null) && (lastRollbackBoundary.Transaction == YesNoType.Yes) && boundaryHadX86Package && (facade.Package.x64 == YesNoType.Yes)) { Messaging.Instance.OnMessage(WixErrors.MsiTransactionX86BeforeX64(lastRollbackBoundary.SourceLineNumbers)); } boundaryHadX86Package = boundaryHadX86Package || (facade.Package.x64 == YesNoType.No); orderedFacades.Add(facade); } else // must be a rollback boundary. { // Discard the next rollback boundary if we have a previously defined boundary. WixBundleRollbackBoundaryRow nextRollbackBoundary = Boundaries.Get(row.ChildId); if (null != previousRollbackBoundary) { Messaging.Instance.OnMessage(WixWarnings.DiscardedRollbackBoundary(nextRollbackBoundary.SourceLineNumbers, nextRollbackBoundary.ChainPackageId)); } else { previousRollbackBoundary = nextRollbackBoundary; lastRollbackBoundary = nextRollbackBoundary; } } } } if (null != previousRollbackBoundary) { Messaging.Instance.OnMessage(WixWarnings.DiscardedRollbackBoundary(previousRollbackBoundary.SourceLineNumbers, previousRollbackBoundary.ChainPackageId)); } // With the forward rollback boundaries assigned, we can now go // through the packages with rollback boundaries and assign backward // rollback boundaries. Backward rollback boundaries are used when // the chain is going "backwards" which (AFAIK) only happens during // uninstall. // // Consider the scenario with three packages: A, B and C. Packages A // and C are marked as rollback boundary packages and package B is // not. The naive implementation would execute the chain like this // (numbers indicate where rollback boundaries would end up): // install: 1 A B 2 C // uninstall: 2 C B 1 A // // The uninstall chain is wrong, A and B should be grouped together // not C and B. The fix is to label packages with a "backwards" // rollback boundary used during uninstall. The backwards rollback // boundaries are assigned to the package *before* the next rollback // boundary. Using our example from above again, I'll mark the // backwards rollback boundaries prime (aka: with '). // install: 1 A B 1' 2 C 2' // uninstall: 2' C 2 1' B A 1 // // If the marked boundaries are ignored during install you get the // same thing as above (good) and if the non-marked boundaries are // ignored during uninstall then A and B are correctly grouped. // Here's what it looks like without all the markers: // install: 1 A B 2 C // uninstall: 2 C 1 B A // Woot! string previousRollbackBoundaryId = null; PackageFacade previousFacade = null; foreach (PackageFacade package in orderedFacades) { if (null != package.Package.RollbackBoundary) { if (null != previousFacade) { previousFacade.Package.RollbackBoundaryBackward = previousRollbackBoundaryId; } previousRollbackBoundaryId = package.Package.RollbackBoundary; } previousFacade = package; } if (!String.IsNullOrEmpty(previousRollbackBoundaryId) && null != previousFacade) { previousFacade.Package.RollbackBoundaryBackward = previousRollbackBoundaryId; } this.OrderedPackageFacades = orderedFacades; this.UsedRollbackBoundaries = usedBoundaries; }
public void Execute() { var groupSymbols = this.Section.Symbols.OfType <WixGroupSymbol>().ToList(); var boundariesById = this.Section.Symbols.OfType <WixBundleRollbackBoundarySymbol>().ToDictionary(b => b.Id.Id); var orderedFacades = new List <PackageFacade>(); var usedBoundaries = new List <WixBundleRollbackBoundarySymbol>(); // Process the chain of packages to add them in the correct order // and assign the forward rollback boundaries as appropriate. Remember // rollback boundaries are authored as elements in the chain which // we re-interpret here to add them as attributes on the next available // package in the chain. Essentially we mark some packages as being // the start of a rollback boundary when installing and repairing. // We handle uninstall (aka: backwards) rollback boundaries after // we get these install/repair (aka: forward) rollback boundaries // defined. var pendingRollbackBoundary = new WixBundleRollbackBoundarySymbol(null, new Identifier(AccessModifier.Section, DefaultBoundaryId)) { Vital = true }; var lastRollbackBoundary = pendingRollbackBoundary; var boundaryHadX86Package = false; var warnedMsiTransaction = false; foreach (var groupSymbol in groupSymbols) { if (ComplexReferenceChildType.Package == groupSymbol.ChildType && ComplexReferenceParentType.PackageGroup == groupSymbol.ParentType && "WixChain" == groupSymbol.ParentId) { if (this.PackageFacades.TryGetValue(groupSymbol.ChildId, out var facade)) { var insideMsiTransaction = lastRollbackBoundary?.Transaction ?? false; if (null != pendingRollbackBoundary) { // If we used the default boundary, ensure the symbol is added to the section. if (pendingRollbackBoundary.Id.Id == DefaultBoundaryId) { this.Section.AddSymbol(pendingRollbackBoundary); } if (insideMsiTransaction && !warnedMsiTransaction) { warnedMsiTransaction = true; this.Messaging.Write(WarningMessages.MsiTransactionLimitations(pendingRollbackBoundary.SourceLineNumbers)); } usedBoundaries.Add(pendingRollbackBoundary); facade.PackageSymbol.RollbackBoundaryRef = pendingRollbackBoundary.Id.Id; pendingRollbackBoundary = null; boundaryHadX86Package = !facade.PackageSymbol.Win64; } // Error if MSI transaction has x86 package preceding x64 packages if (insideMsiTransaction && boundaryHadX86Package && facade.PackageSymbol.Win64) { this.Messaging.Write(ErrorMessages.MsiTransactionX86BeforeX64(facade.PackageSymbol.SourceLineNumbers)); } boundaryHadX86Package |= !facade.PackageSymbol.Win64; orderedFacades.Add(facade); } else // must be a rollback boundary. { // Discard the next rollback boundary if we have a previously defined boundary. var nextRollbackBoundary = boundariesById[groupSymbol.ChildId]; if (null != pendingRollbackBoundary) { if (pendingRollbackBoundary.Id.Id != DefaultBoundaryId) { this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(nextRollbackBoundary.SourceLineNumbers, nextRollbackBoundary.Id.Id)); } } lastRollbackBoundary = pendingRollbackBoundary = nextRollbackBoundary; } } } if (null != pendingRollbackBoundary) { this.Messaging.Write(WarningMessages.DiscardedRollbackBoundary(pendingRollbackBoundary.SourceLineNumbers, pendingRollbackBoundary.Id.Id)); } // With the forward rollback boundaries assigned, we can now go // through the packages with rollback boundaries and assign backward // rollback boundaries. Backward rollback boundaries are used when // the chain is going "backwards" which (AFAIK) only happens during // uninstall. // // Consider the scenario with three packages: A, B and C. Packages A // and C are marked as rollback boundary packages and package B is // not. The naive implementation would execute the chain like this // (numbers indicate where rollback boundaries would end up): // install: 1 A B 2 C // uninstall: 2 C B 1 A // // The uninstall chain is wrong, A and B should be grouped together // not C and B. The fix is to label packages with a "backwards" // rollback boundary used during uninstall. The backwards rollback // boundaries are assigned to the package *before* the next rollback // boundary. Using our example from above again, I'll mark the // backwards rollback boundaries prime (aka: with '). // install: 1 A B 1' 2 C 2' // uninstall: 2' C 2 1' B A 1 // // If the marked boundaries are ignored during install you get the // same thing as above (good) and if the non-marked boundaries are // ignored during uninstall then A and B are correctly grouped. // Here's what it looks like without all the markers: // install: 1 A B 2 C // uninstall: 2 C 1 B A // Woot! string previousRollbackBoundaryId = null; PackageFacade previousFacade = null; foreach (var package in orderedFacades) { if (null != package.PackageSymbol.RollbackBoundaryRef) { if (null != previousFacade) { previousFacade.PackageSymbol.RollbackBoundaryBackwardRef = previousRollbackBoundaryId; } previousRollbackBoundaryId = package.PackageSymbol.RollbackBoundaryRef; } previousFacade = package; } if (!String.IsNullOrEmpty(previousRollbackBoundaryId) && null != previousFacade) { previousFacade.PackageSymbol.RollbackBoundaryBackwardRef = previousRollbackBoundaryId; } this.OrderedPackageFacades = orderedFacades; this.UsedRollbackBoundaries = usedBoundaries; }