internal void UndoPackageComposition() { var rulesThatISuperceed = InstalledPackageFeed.Instance.FindPackages(CanonicalName.AllPackages) .Except(this.SingleItemAsEnumerable()) .OrderBy(each => each, new Toolkit.Extensions.Comparer <Package>((packageA, packageB) => GeneralPackageSettings.Instance.WhoWins(packageA, packageB))) .Where(WinsVersus) .SelectMany(package => package.ResolvedRules.Select(rule => new { package, rule })) .WhereDistinct(each => each.rule.Destination) .ToArray(); var rulesThatSuperceedMine = InstalledPackageFeed.Instance.FindPackages(CanonicalName.AllPackages).Where(package => !WinsVersus(package)).SelectMany(package => package.ResolvedRules).ToArray(); foreach (var rule in ResolvedRules) { // there are three possibilities if (rule.Action == CompositionAction.DownloadFile || rule.Action == CompositionAction.InstallCommand) { //skip these types of rules. continue; } // never supercede RemoveCommand. if (rule.Action != CompositionAction.RemoveCommand) { // 1. my rule was already superceded by another rule: do nothing. if (rulesThatSuperceedMine.Any(each => each.Destination.Equals(rule.Destination, StringComparison.CurrentCultureIgnoreCase))) { continue; } // 2. my rule was superceding another: run that rule. var runRule = rulesThatISuperceed.FirstOrDefault(each => each.rule.Destination.Equals(rule.Destination, StringComparison.CurrentCultureIgnoreCase)); if (runRule != null) { runRule.package.ApplyRule(runRule.rule); continue; } } // 3. my rule should be the current rule, let's undo it. switch (rule.Action) { case CompositionAction.Shortcut: if (ShellLink.PointsTo(rule.Destination, rule.Source)) { rule.Destination.TryHardToDelete(); } break; case CompositionAction.SymlinkFile: if (File.Exists(rule.Destination) && Symlink.IsSymlink(rule.Destination) && Symlink.GetActualPath(rule.Destination).Equals(rule.Source)) { Symlink.DeleteSymlink(rule.Destination); } break; case CompositionAction.SymlinkFolder: if (Symlink.IsSymlink(rule.Destination) && Symlink.GetActualPath(rule.Destination).Equals(rule.Source)) { Symlink.DeleteSymlink(rule.Destination); } break; case CompositionAction.Registry: if (CanonicalName.Architecture == Architecture.x64 && Environment.Is64BitOperatingSystem) { RegistryView.System["SOFTWARE"][rule.Key].StringValue = null; } else { RegistryView.System["SOFTWARE\\Wow6432Node"][rule.Key].StringValue = null; } break; case CompositionAction.EnvironmentVariable: // not implemented yet. break; case CompositionAction.RemoveCommand: ExecuteCommand(rule.Source, rule.Destination); break; } } }