#pragma warning restore CA1303 static async Task <int> ProcessAndExecute(CommandLine commandLine) { var exitCode = 0; IEnumerable <string> remove = new List <string>(); IEnumerable <ProductInfo> uninstall = new List <ProductInfo>(), install = null; var products = await ProductCollection.ReadProducts(commandLine.Arguments.Select((uri, index) => { return(new Uri(uri)); })).ConfigureAwait(false); products.MapToLocal(commandLine.StagingFolder); if (commandLine.Verbose) { Console.WriteLine($"Products [{products.Count}]:"); foreach (var p in products) { Console.WriteLine($" {p.Name}: {p.Uri} => {p.LocalPath}"); foreach (var pp in p.Props) { Console.WriteLine($" {pp.Key} = {pp.Value}"); } } } // installed products (cached installer files) we don't need anymore remove = products.FindFilesToUninstall(Path.Combine(commandLine.StagingFolder, $"*{Installer.InstallerFileExtension}")); if (commandLine.Verbose) { if (remove.Any()) { Console.WriteLine($"Remove [{remove.Count()}]:"); foreach (var f in remove) { Console.WriteLine($" {f}"); } } } // Prepare a list of files to uninstall for downgrade or props change, and another list of products to install/upgrade if (commandLine.ClearStagingFolder) { commandLine.DeleteStagingFolder(); install = products; } else { (uninstall, install) = products.Separate(localMsiFile => { var localInfoFile = Path.ChangeExtension(localMsiFile, ProductInfo.LocalInfoFileExtension); var installedProduct = ProductInfo.FindInstalled(localInfoFile).Result; // some backward compatibility in case if was not serialized if (null != installedProduct) { if (string.IsNullOrEmpty(installedProduct.LocalPath)) { installedProduct.LocalPath = localMsiFile; } } return(installedProduct); }, commandLine.VersionPrefixes.Split(',')); } if (commandLine.Verbose) { if (uninstall.Any()) { Console.WriteLine($"Uninstall [{uninstall.Count()}]:"); foreach (var f in uninstall) { Console.WriteLine($" {f.Uri}"); } } if (install.Any()) { Console.WriteLine($"Install [{install.Count()}]:"); foreach (var f in install) { Console.WriteLine($" {f.Uri}"); } } } // Ok, now we can proceed with changes: if (0 == exitCode) { // 1) Uninstall what's not needed anymore... foreach (var f in remove) { var err = commandLine.Uninstall(f, !commandLine.DryRun); if (0 == exitCode && 0 != err) { exitCode = err; break; } } // 2) Uninstall whose to be changed foreach (var f in uninstall) { var err = commandLine.Uninstall(f.LocalPath, false); if (0 == exitCode && 0 != err) { exitCode = err; break; } } // 3) Download/cache existing and new if (install.Any()) { var err = commandLine.DownloadProducts(install, commandLine.Timeout); if (0 == err) { // 4) Install changed and new foreach (var p in install) { err = commandLine.Install(p); if (0 == exitCode && 0 != err) { exitCode = err; break; } } } } } return(exitCode); }