internal void DoPackageComposition() { // GS01: if package composition fails, and we're in the middle of installing a package // we should roll back the package install. var rulesThatSuperceedMine = InstalledPackageFeed.Instance.FindPackages(CanonicalName.AllPackages).Where(package => !WinsVersus(package)).SelectMany(package => package.ResolvedRules.Where(each => each.Action != CompositionAction.DownloadFile && each.Action != CompositionAction.InstallCommand && each.Action != CompositionAction.RemoveCommand)).ToArray(); foreach (var rule in ResolvedRules.Where(rule => !rulesThatSuperceedMine.Any(each => each.Destination.Equals(rule.Destination, StringComparison.CurrentCultureIgnoreCase))).OrderBy(rule => rule.Action)) { // if we've past the downloads, we need to block on them finishing. No downloads is a quick skip. if (rule.Action > CompositionAction.DownloadFile) { if (!PackageSessionData.WaitForFileDownloads()) { throw new CoAppException("Failed to download one or more dependent files."); } } if (!ApplyRule(rule)) { // throw if not successful? // think on this. GS01 } } }
private bool ApplyRule(CompositionRule rule) { switch (rule.Action) { case CompositionAction.DownloadFile: if (!File.Exists(rule.Destination)) { PackageSessionData.DownloadFile(rule.Source, rule.Destination); } return(true); case CompositionAction.InstallCommand: return(ExecuteCommand(rule.Source, rule.Destination)); case CompositionAction.RemoveCommand: // we never 'apply' remove commands. Just remove em' return(true); case CompositionAction.FileCopy: // file copy operations may only manipulate files in the package directory. if (string.IsNullOrEmpty(rule.Source)) { Logger.Error("ERROR: Illegal file copy rule. Source must be in package directory [{0}] => [{1}]", rule.Source, rule.Destination); return(false); } if (string.IsNullOrEmpty(rule.Destination)) { Logger.Error("ERROR: Illegal file copy rule. Destination must be in package directory [{0}] => [{1}]", rule.Source, rule.Destination); return(false); } if (!File.Exists(rule.Source)) { Logger.Error("ERROR: Illegal file copy rule. Source file does not exist [{0}] => [{1}]", rule.Source, rule.Destination); return(false); } try { var destParent = Path.GetDirectoryName(rule.Destination); if (!string.IsNullOrEmpty(destParent)) { if (!Directory.Exists(destParent)) { Directory.CreateDirectory(destParent); } File.Copy(rule.Source, rule.Destination, true); } } catch (Exception e) { Logger.Error(e); } return(true); case CompositionAction.FileRewrite: // file copy operations may only manipulate files in the package directory. if (string.IsNullOrEmpty(rule.Source)) { Logger.Error("ERROR: Illegal file rewrite rule. Source must be in package directory [{0}] => [{1}]", rule.Source, rule.Destination); return(false); } if (string.IsNullOrEmpty(rule.Destination)) { Logger.Error("ERROR: Illegal file rewrite rule. Destination must be in package directory [{0}] => [{1}]", rule.Source, rule.Destination); return(false); } if (!File.Exists(rule.Source)) { Logger.Error("ERROR: Illegal file rewrite rule. Source file does not exist [{0}] => [{1}]", rule.Source, rule.Destination); return(false); } File.WriteAllText(rule.Destination, ResolveVariables(File.ReadAllText(rule.Source))); return(true); case CompositionAction.SymlinkFile: if (string.IsNullOrEmpty(rule.Destination)) { Logger.Error("ERROR: Illegal file symlink rule. Destination location '{0}' must be a subpath of apps dir", rule.Destination); return(false); } if (string.IsNullOrEmpty(rule.Source)) { Logger.Error("ERROR: Illegal file symlink rule. Source file '{0}' must be a subpath of package directory", rule.Source); return(false); } if (!File.Exists(rule.Source)) { Logger.Error("ERROR: Illegal folder symlink rule. Source file '{0}' does not exist.", rule.Source); return(false); } var parentDir = Path.GetDirectoryName(rule.Destination); if (!string.IsNullOrEmpty(parentDir)) { if (!Directory.Exists(parentDir)) { Directory.CreateDirectory(parentDir); } try { // Logger.Message("Creating file Symlink [{0}] => [{1}]", rule.Destination, rule.Source); Symlink.MakeFileLink(rule.Destination, rule.Source); } catch (Exception) { Logger.Error("Warning: File Symlink Link Failed. [{0}] => [{1}]", rule.Destination, rule.Source); } } return(true); case CompositionAction.SymlinkFolder: if (string.IsNullOrEmpty(rule.Destination)) { Logger.Error("ERROR: Illegal folder symlink rule. Destination location '{0}' must be a subpath of appsdir", rule.Destination); return(false); } if (string.IsNullOrEmpty(rule.Source)) { Logger.Error("ERROR: Illegal folder symlink rule. Source folder '{0}' must be a subpath of package directory{1}", rule.Source); return(false); } if (!Directory.Exists(rule.Source)) { Logger.Error("ERROR: Illegal folder symlink rule. Source folder '{0}' does not exist.", rule.Source); return(false); } try { // Logger.Message("Creatign Directory Symlink [{0}] => [{1}]", rule.Destination, rule.Source); Symlink.MakeDirectoryLink(rule.Destination, rule.Source); } catch (Exception) { Logger.Error("Warning: Directory Symlink Link Failed. [{0}] => [{1}]", rule.Destination, rule.Source); return(false); } return(true); case CompositionAction.Shortcut: if (string.IsNullOrEmpty(rule.Source)) { Logger.Error("ERROR: Illegal shortcut rule. Source file '{0}' must be a subpath of package directory", rule.Source); return(false); } if (!File.Exists(rule.Source)) { Logger.Error("ERROR: Illegal shortcut rule. Source file '{0}' does not exist.", rule.Source); return(false); } var pDir = Path.GetDirectoryName(rule.Destination); if (!string.IsNullOrEmpty(pDir)) { if (!Directory.Exists(pDir)) { Directory.CreateDirectory(pDir); } // Logger.Message("Creating Shortcut [{0}] => [{1}]", rule.Destination, rule.Source); ShellLink.CreateShortcut(rule.Destination, rule.Source, workingDirectory: ""); } return(true); case CompositionAction.EnvironmentVariable: switch (rule.Key.ToLower()) { case "path": case "pathext": case "psmodulepath": case "comspec": case "temp": case "tmp": case "username": case "windir": case "allusersprofile": case "appdata": case "commonprogramfiles": case "commonprogramfiles(x86)": case "commonprogramw6432": case "computername": case "current_cpu": case "FrameworkVersion": case "homedrive": case "homepath": case "logonserver": case "number_of_processors": case "os": case "processor_architecture": case "processor_identifier": case "processor_level": case "processor_revision": case "programdata": case "programfiles": case "programfiles(x86)": case "programw6432": case "prompt": case "public": case "systemdrive": case "systemroot": case "userdomain": case "userprofile": Logger.Warning("Package may not set environment variable '{0}'", rule.Key); return(true); default: EnvironmentUtility.SetSystemEnvironmentVariable(rule.Key, rule.Value); return(true); } case CompositionAction.Registry: if (CanonicalName.Architecture == Architecture.x64 && Environment.Is64BitOperatingSystem) { RegistryView.System["SOFTWARE"][rule.Key].StringValue = rule.Value; } else { RegistryView.System["SOFTWARE\\Wow6432Node"][rule.Key].StringValue = rule.Value; } return(true); } return(true); }