示例#1
0
        public void ChangeConfigTests()
        {
            var logger    = new TestLogger();
            var installer = new UnattendServiceControlInstaller(logger, DeploymentCache);

            logger.Info("Deleting instances");
            DeleteInstance();

            logger.Info("Removing the test queue instances");
            RemoveAltMSMQQueues();

            logger.Info("Recreating the MSMQ instance");
            CreateInstanceMSMQ();

            logger.Info("Changing the URLACL");
            var msmqTestInstance = InstanceFinder.ServiceControlInstances().First(p => p.Name.Equals("Test.ServiceControl.MSMQ", StringComparison.OrdinalIgnoreCase));

            msmqTestInstance.HostName = Environment.MachineName;
            msmqTestInstance.Port     = 33338;
            installer.Update(msmqTestInstance, true);
            Assert.IsTrue(msmqTestInstance.Service.Status == ServiceControllerStatus.Running, "Update URL change failed");

            logger.Info("Changing LogPath");
            msmqTestInstance         = InstanceFinder.ServiceControlInstances().First(p => p.Name.Equals("Test.ServiceControl.MSMQ", StringComparison.OrdinalIgnoreCase));
            msmqTestInstance.LogPath = @"c:\temp\testloggingchange";
            installer.Update(msmqTestInstance, true);
            Assert.IsTrue(msmqTestInstance.Service.Status == ServiceControllerStatus.Running, "Update Logging changed failed");

            logger.Info("Updating Queue paths");
            msmqTestInstance            = InstanceFinder.ServiceControlInstances().First(p => p.Name.Equals("Test.ServiceControl.MSMQ", StringComparison.OrdinalIgnoreCase));
            msmqTestInstance.AuditQueue = "alternateAudit";
            msmqTestInstance.ErrorQueue = "alternateError";
            installer.Update(msmqTestInstance, true);
            Assert.IsTrue(msmqTestInstance.Service.Status == ServiceControllerStatus.Running, "Update Queues changed failed");
        }
        protected override void ProcessRecord()
        {
            var psPath = SessionState.Path.GetUnresolvedProviderPathFromPSPath(UnattendFile, out _, out _);

            var details = ServiceControlNewInstance.Load(psPath);

            details.ServiceAccount    = ServiceAccount;
            details.ServiceAccountPwd = Password;
            var zipfolder = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
            var logger    = new PSLogger(Host);
            var installer = new UnattendServiceControlInstaller(logger, zipfolder);

            try
            {
                logger.Info("Installing Service Control instance...");
                if (installer.Add(details, PromptToProceed))
                {
                    var instance = InstanceFinder.FindServiceControlInstance(details.Name);
                    if (instance != null)
                    {
                        WriteObject(PsServiceControl.FromInstance(instance));
                    }
                    else
                    {
                        throw new Exception("Unknown error creating instance");
                    }
                }
            }
            catch (Exception ex)
            {
                ThrowTerminatingError(new ErrorRecord(ex, null, ErrorCategory.NotSpecified, null));
            }
        }
        protected override void ProcessRecord()
        {
            var logger = new PSLogger(Host);

            var zipFolder = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
            var installer = new UnattendServiceControlInstaller(logger, zipFolder);

            var instance = InstanceFinder.FindInstanceByName <ServiceControlInstance>(Name);

            if (instance == null)
            {
                WriteWarning($"No action taken. An instance called {Name} was not found");
                return;
            }

            var requiredUpgradeAction = instance.GetRequiredUpgradeAction(installer.ZipInfo.Version);

            switch (requiredUpgradeAction)
            {
            case RequiredUpgradeAction.Upgrade:
                PerformUpgrade(instance, installer);
                break;

            case RequiredUpgradeAction.SplitOutAudit:
                PerformSplit(instance, logger, zipFolder);
                break;

            default:
                ThrowTerminatingError(new ErrorRecord(new Exception($"Upgrade of {instance.Name} aborted. This instance cannot be upgraded."), "UpgradeFailure", ErrorCategory.InvalidResult, null));
                break;
            }
        }
示例#4
0
        public void DeleteInstance()
        {
            var installer = new UnattendServiceControlInstaller(new TestLogger(), DeploymentCache);

            foreach (var instance in InstanceFinder.ServiceControlInstances().Where(p => p.Name.StartsWith("Test.ServiceControl", StringComparison.OrdinalIgnoreCase)))
            {
                installer.Delete(instance.Name, true, true);
            }
        }
        protected override void ProcessRecord()
        {
            var details = new ServiceControlNewInstance
            {
                InstallPath             = InstallPath,
                LogPath                 = LogPath,
                DBPath                  = DBPath,
                Name                    = Name,
                DisplayName             = string.IsNullOrWhiteSpace(DisplayName) ? Name : DisplayName,
                ServiceDescription      = Description,
                ServiceAccount          = ServiceAccount,
                ServiceAccountPwd       = ServiceAccountPassword,
                HostName                = HostName,
                Port                    = Port,
                DatabaseMaintenancePort = DatabaseMaintenancePort,
                VirtualDirectory        = VirtualDirectory,
                AuditQueue              = AuditQueue,
                ErrorQueue              = ErrorQueue,
                AuditLogQueue           = string.IsNullOrWhiteSpace(AuditLogQueue) ? null : AuditLogQueue,
                ErrorLogQueue           = string.IsNullOrWhiteSpace(ErrorLogQueue) ? null : ErrorLogQueue,
                ForwardAuditMessages    = ForwardAuditMessages.ToBool(),
                ForwardErrorMessages    = ForwardErrorMessages.ToBool(),
                AuditRetentionPeriod    = AuditRetentionPeriod,
                ErrorRetentionPeriod    = ErrorRetentionPeriod,
                ConnectionString        = ConnectionString,
                TransportPackage        = ServiceControlCoreTransports.All.First(t => t.Matches(Transport)),
                SkipQueueCreation       = SkipQueueCreation
            };

            var zipfolder = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
            var logger    = new PSLogger(Host);

            var installer = new UnattendServiceControlInstaller(logger, zipfolder);

            try
            {
                logger.Info("Installing Service Control instance...");
                if (installer.Add(details, PromptToProceed))
                {
                    var instance = InstanceFinder.FindServiceControlInstance(details.Name);
                    if (instance != null)
                    {
                        WriteObject(PsServiceControl.FromInstance(instance));
                    }
                    else
                    {
                        throw new Exception("Unknown error creating instance");
                    }
                }
            }
            catch (Exception ex)
            {
                ThrowTerminatingError(new ErrorRecord(ex, null, ErrorCategory.NotSpecified, null));
            }
        }
示例#6
0
        protected override void ProcessRecord()
        {
            var logger = new PSLogger(Host);

            var zipFolder = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
            var installer = new UnattendServiceControlInstaller(logger, zipFolder);

            foreach (var name in Name)
            {
                var options = new ServiceControlUpgradeOptions {
                    AuditRetentionPeriod = AuditRetentionPeriod, ErrorRetentionPeriod = ErrorRetentionPeriod, OverrideEnableErrorForwarding = ForwardErrorMessages, SkipQueueCreation = SkipQueueCreation
                };
                var instance = InstanceFinder.FindServiceControlInstance(name);
                if (instance == null)
                {
                    WriteWarning($"No action taken. An instance called {name} was not found");
                    break;
                }

                options.OverrideEnableErrorForwarding = ForwardErrorMessages;

                // Migrate Value
                if (!options.AuditRetentionPeriod.HasValue)
                {
                    if (instance.AppConfig.AppSettingExists(SettingsList.HoursToKeepMessagesBeforeExpiring.Name))
                    {
                        var i = instance.AppConfig.Read(SettingsList.HoursToKeepMessagesBeforeExpiring.Name, -1);
                        if (i != -1)
                        {
                            options.AuditRetentionPeriod = TimeSpan.FromHours(i);
                        }
                    }
                }

                if (!options.OverrideEnableErrorForwarding.HasValue & !instance.AppConfig.AppSettingExists(SettingsList.ForwardErrorMessages.Name))
                {
                    ThrowTerminatingError(new ErrorRecord(new Exception($"Upgrade of {instance.Name} aborted. ForwardErrorMessages parameter must be set to true or false because the configuration file has no setting for ForwardErrorMessages. This setting is mandatory as of version 1.12"), "UpgradeFailure", ErrorCategory.InvalidArgument, null));
                }

                if (!options.ErrorRetentionPeriod.HasValue & !instance.AppConfig.AppSettingExists(SettingsList.ErrorRetentionPeriod.Name))
                {
                    ThrowTerminatingError(new ErrorRecord(new Exception($"Upgrade of {instance.Name} aborted. ErrorRetentionPeriod parameter must be set to timespan because the configuration file has no setting for ErrorRetentionPeriod. This setting is mandatory as of version 1.13"), "UpgradeFailure", ErrorCategory.InvalidArgument, null));
                }

                if (!options.AuditRetentionPeriod.HasValue & !instance.AppConfig.AppSettingExists(SettingsList.AuditRetentionPeriod.Name))
                {
                    ThrowTerminatingError(new ErrorRecord(new Exception($"Upgrade of {instance.Name} aborted. AuditRetentionPeriod parameter must be set to timespan because the configuration file has no setting for AuditRetentionPeriod. This setting is mandatory as of version 1.13"), "UpgradeFailure", ErrorCategory.InvalidArgument, null));
                }

                if (!installer.Upgrade(instance, options))
                {
                    ThrowTerminatingError(new ErrorRecord(new Exception($"Upgrade of {instance.Name} failed"), "UpgradeFailure", ErrorCategory.InvalidResult, null));
                }
            }
        }
示例#7
0
        public void UpgradeInstance()
        {
            var installer = new UnattendServiceControlInstaller(new TestLogger(), DeploymentCache);

            foreach (var instance in InstanceFinder.ServiceControlInstances().Where(p => p.Name.StartsWith("Test.ServiceControl", StringComparison.OrdinalIgnoreCase)))
            {
                installer.Upgrade(instance, new ServiceControlUpgradeOptions {
                    AuditRetentionPeriod = TimeSpan.FromDays(30), ErrorRetentionPeriod = TimeSpan.FromDays(15), OverrideEnableErrorForwarding = true
                });
            }
        }
        void PerformUpgrade(ServiceControlInstance instance, UnattendServiceControlInstaller installer)
        {
            var options = new ServiceControlUpgradeOptions
            {
                SkipQueueCreation = SkipQueueCreation
            };

            options.UpgradeInfo = UpgradeControl.GetUpgradeInfoForTargetVersion(installer.ZipInfo.Version, instance.Version);

            if (!installer.Upgrade(instance, options))
            {
                ThrowTerminatingError(new ErrorRecord(new Exception($"Upgrade of {instance.Name} failed"), "UpgradeFailure", ErrorCategory.InvalidResult, null));
            }
        }
        protected override void ProcessRecord()
        {
            var logger = new PSLogger(Host);

            var zipFolder = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
            var installer = new UnattendServiceControlInstaller(logger, zipFolder);

            var instance = InstanceFinder.FindInstanceByName <ServiceControlInstance>(Name);

            if (instance == null)
            {
                WriteWarning($"No action taken. An instance called {Name} was not found");
                return;
            }

            WriteObject(installer.AddRemoteInstance(instance, RemoteInstanceAddress, logger));
        }
        protected override void ProcessRecord()
        {
            var logger    = new PSLogger(Host);
            var zipfolder = Path.GetDirectoryName(MyInvocation.MyCommand.Module.Path);
            var installer = new UnattendServiceControlInstaller(logger, zipfolder);

            foreach (var name in Name)
            {
                var instance = InstanceFinder.FindServiceControlInstance(name);
                if (instance == null)
                {
                    WriteWarning($"No action taken. An instance called {name} was not found");
                    break;
                }
                WriteObject(installer.Delete(instance.Name, RemoveDB.ToBool(), RemoveLogs.ToBool()));
            }
        }
        public static ActionResult ServiceControlUnattendedInstall(Session session)
        {
            var logger = new MSILogger(session);

            var unattendedInstaller = new UnattendServiceControlInstaller(logger, session["APPDIR"]);
            var zipInfo             = ServiceControlZipInfo.Find(session["APPDIR"] ?? ".");

            if (!zipInfo.Present)
            {
                logger.Error("Zip file not found. Service Control service instances can not be upgraded or installed");
                return(ActionResult.Failure);
            }

            UpgradeInstances(session, zipInfo, logger, unattendedInstaller);
            UnattendedInstall(session, logger, unattendedInstaller);
            ImportLicenseInstall(session, logger);
            return(ActionResult.Success);
        }
示例#12
0
        public static ActionResult ServiceControlUnattendedRemoval(Session session)
        {
            var logger = new MSILogger(session);
            var removeInstancesPropertyValue = session["REMOVEALLINSTANCESANDDATA"];

            if (string.IsNullOrWhiteSpace(removeInstancesPropertyValue))
            {
                return(ActionResult.NotExecuted);
            }

            switch (removeInstancesPropertyValue.ToUpper())
            {
            case "YES":
            case "TRUE":
                break;

            default:
                return(ActionResult.NotExecuted);
            }

            if (InstanceFinder.ServiceControlInstances().Count == 0)
            {
                return(ActionResult.Success);
            }

            var unattendedInstaller = new UnattendServiceControlInstaller(logger, session["APPDIR"]);

            foreach (var instance in InstanceFinder.ServiceControlInstances())
            {
                try
                {
                    unattendedInstaller.Delete(instance.Name, true, true);
                }
                catch (Exception ex)
                {
                    logger.Error($"Error thrown when removing instance {instance.Name} - {ex}");
                }
            }

            return(ActionResult.Success);
        }
示例#13
0
        public void CreateInstanceMSMQ()
        {
            var installer    = new UnattendServiceControlInstaller(new TestLogger(), DeploymentCache);
            var instanceName = "Test.ServiceControl.Msmq";
            var root         = Path.Combine(@"c:\Test", instanceName);
            // ReSharper disable once UseObjectOrCollectionInitializer
            var details = new ServiceControlNewInstance
            {
                DisplayName             = instanceName.Replace(".", " "),
                Name                    = instanceName,
                ServiceDescription      = "Test SC Instance",
                DBPath                  = Path.Combine(root, "Database"),
                LogPath                 = Path.Combine(root, "Logs"),
                InstallPath             = Path.Combine(root, "Binaries"),
                HostName                = "localhost",
                Port                    = 33335,
                DatabaseMaintenancePort = 33336,
                VirtualDirectory        = null,
                AuditQueue              = "audittest",
                ForwardAuditMessages    = false,
                ForwardErrorMessages    = false,
                //TODO: Fix
                //AuditRetentionPeriod = TimeSpan.FromHours(SettingConstants.AuditRetentionPeriodDefaultInHoursForUI),
                ErrorRetentionPeriod = TimeSpan.FromDays(SettingConstants.ErrorRetentionPeriodDefaultInDaysForUI),
                ErrorQueue           = "testerror",
                TransportPackage     = ServiceControlCoreTransports.All.First(t => t.Name == TransportNames.MSMQ),
                ReportCard           = new ReportCard()
            };

            // constructer of ServiceControlInstanceMetadata extracts version from zip
            // but this fails for unit tests as the deploymentCache path is not used
            details.Version = installer.ZipInfo.Version;

            details.Validate(s => false);
            if (details.ReportCard.HasErrors)
            {
                throw new Exception($"Validation errors:  {string.Join("\r\n", details.ReportCard.Errors)}");
            }

            Assert.DoesNotThrow(() => installer.Add(details, s => false));
        }
        static void UnattendedInstall(Session session, MSILogger logger, UnattendServiceControlInstaller unattendedInstaller)
        {
            logger.Info("Checking for unattended file");

            var unattendedFilePropertyValue = session["UNATTENDEDFILE"];

            if (string.IsNullOrWhiteSpace(unattendedFilePropertyValue))
            {
                return;
            }

            var serviceAccount = session["SERVICEACCOUNT"];
            var password       = session["PASSWORD"];

            logger.Info($"UNATTENDEDFILE: {unattendedFilePropertyValue}");
            var currentDirectory   = session["CURRENTDIRECTORY"];
            var unattendedFilePath = Environment.ExpandEnvironmentVariables(Path.IsPathRooted(unattendedFilePropertyValue) ? unattendedFilePropertyValue : Path.Combine(currentDirectory, unattendedFilePropertyValue));

            logger.Info($"Expanded unattended filepath to : {unattendedFilePropertyValue}");

            if (File.Exists(unattendedFilePath))
            {
                logger.Info($"File Exists : {unattendedFilePropertyValue}");
                var instanceToInstallDetails = ServiceControlNewInstance.Load(unattendedFilePath);

                if (!string.IsNullOrWhiteSpace(serviceAccount))
                {
                    instanceToInstallDetails.ServiceAccount    = serviceAccount;
                    instanceToInstallDetails.ServiceAccountPwd = password;
                }

                unattendedInstaller.Add(instanceToInstallDetails, s => false);
            }
            else
            {
                logger.Error($"The specified unattended install file was not found : '{unattendedFilePath}'");
            }
        }
        static void UpgradeInstances(Session session, ServiceControlZipInfo zipInfo, MSILogger logger, UnattendServiceControlInstaller unattendedInstaller)
        {
            var options = new ServiceControlUpgradeOptions();

            var upgradeInstancesPropertyValue = session["UPGRADEINSTANCES"];

            if (string.IsNullOrWhiteSpace(upgradeInstancesPropertyValue))
            {
                return;
            }

            upgradeInstancesPropertyValue = upgradeInstancesPropertyValue.Trim();

            var forwardErrorMessagesPropertyValue = session["FORWARDERRORMESSAGES"];

            try
            {
                options.OverrideEnableErrorForwarding = bool.Parse(forwardErrorMessagesPropertyValue);
            }
            catch
            {
                options.OverrideEnableErrorForwarding = null;
            }

            var auditRetentionPeriodPropertyValue = session["AUDITRETENTIONPERIOD"];

            try
            {
                options.AuditRetentionPeriod = TimeSpan.Parse(auditRetentionPeriodPropertyValue);
            }
            catch
            {
                options.AuditRetentionPeriod = null;
            }

            var errorRetentionPeriodPropertyValue = session["ERRORRETENTIONPERIOD"];

            try
            {
                options.ErrorRetentionPeriod = TimeSpan.Parse(errorRetentionPeriodPropertyValue);
            }
            catch
            {
                options.ErrorRetentionPeriod = null;
            }

            var confirmDatabaseHasBeenBackedUpValue = session["CONFIRMDATABASEHASBEENBACKEDUP"];

            try
            {
                options.ConfirmDatabaseHasBeenBackedUp = bool.Parse(confirmDatabaseHasBeenBackedUpValue);
            }
            catch
            {
                options.ConfirmDatabaseHasBeenBackedUp = false;
            }

            var allowLargeDatabaseUpgradeValue = session["ALLOWLARGEDATABASEUPGRADE"];

            try
            {
                options.AllowLargeDatabaseUpdate = bool.Parse(allowLargeDatabaseUpgradeValue);
            }
            catch
            {
                options.ConfirmDatabaseHasBeenBackedUp = false;
            }

            //determine what to upgrade
            var instancesToUpgrade = new List <ServiceControlInstance>();

            if (upgradeInstancesPropertyValue.Equals("*", StringComparison.OrdinalIgnoreCase) || upgradeInstancesPropertyValue.Equals("ALL", StringComparison.OrdinalIgnoreCase))
            {
                instancesToUpgrade.AddRange(InstanceFinder.ServiceControlInstances());
            }
            else
            {
                var candidates = upgradeInstancesPropertyValue.Replace(" ", String.Empty).Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                instancesToUpgrade.AddRange(InstanceFinder.ServiceControlInstances().Where(instance => candidates.Contains(instance.Name, StringComparer.OrdinalIgnoreCase)));
            }

            // do upgrades
            foreach (var instance in instancesToUpgrade)
            {
                if (zipInfo.Version > instance.Version)
                {
                    var upgradeInfo = UpgradeControl.GetUpgradeInfoForTargetVersion(zipInfo.Version, instance.Version);

                    options.UpgradeInfo = upgradeInfo;

                    if (!instance.AppConfig.AppSettingExists(SettingsList.ForwardErrorMessages.Name) & !options.OverrideEnableErrorForwarding.Value)
                    {
                        logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. FORWARDERRORMESSAGES MSI parameter was required because appsettings needed a value for '{SettingsList.ForwardErrorMessages.Name}'");
                        continue;
                    }

                    if (!options.AuditRetentionPeriod.HasValue)
                    {
                        if (!instance.AppConfig.AppSettingExists(SettingsList.AuditRetentionPeriod.Name))
                        {
                            //Try migration first
                            if (instance.AppConfig.AppSettingExists(SettingsList.HoursToKeepMessagesBeforeExpiring.Name))
                            {
                                var i = instance.AppConfig.Read(SettingsList.HoursToKeepMessagesBeforeExpiring.Name, -1);
                                if (i > 0)
                                {
                                    options.AuditRetentionPeriod = TimeSpan.FromHours(i);
                                }
                            }
                            else
                            {
                                logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. AUDITRETENTIONPERIOD MSI parameter was required because appsettings needed a value for '{SettingsList.AuditRetentionPeriod.Name}'");
                                continue;
                            }
                        }
                    }

                    if (!instance.AppConfig.AppSettingExists(SettingsList.ErrorRetentionPeriod.Name) & !options.ErrorRetentionPeriod.HasValue)
                    {
                        logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. ERRORRETENTIONPERIOD MSI parameter was required because appsettings needed a value for '{SettingsList.ErrorRetentionPeriod.Name}'");
                        continue;
                    }

                    if (upgradeInfo.DataBaseUpdate) //Database is being updated -> recommend DB backup
                    {
                        if (!options.ConfirmDatabaseHasBeenBackedUp)
                        {
                            logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. This upgrade requires a database update and the database should be backed up prior to updating. CONFIRMDATABASEHASBEENBACKEDUP MSI parameter was required to allow the database upgrade.'");
                            continue;
                        }

                        var dbSize = instance.GetDatabaseSizeInGb();
                        if (dbSize >= 100) // 100GB
                        {
                            logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. Upgrade requires a database update and the database being upgraded is {dbSize:N0} GB. " +
                                        "Migrating this much data could take a long time and ServiceControl will be stopped for that entire duration. It is recommended that you consider one of the other upgrade approaches instead. " +
                                        "ALLOWLARGEDATABASEUPGRADE MSI parameter can be used to allow an unattended database upgrade.'");
                            continue;
                        }
                    }

                    if (!unattendedInstaller.Upgrade(instance, options))
                    {
                        logger.Warn($"Failed to upgrade {instance.Name} to {zipInfo.Version}");
                    }
                }
            }
        }
示例#16
0
        static void UpgradeInstances(Session session, ServiceControlZipInfo zipInfo, MSILogger logger, UnattendServiceControlInstaller unattendedInstaller)
        {
            var options = new ServiceControlUpgradeOptions();

            var upgradeInstancesPropertyValue = session["UPGRADEINSTANCES"];

            if (string.IsNullOrWhiteSpace(upgradeInstancesPropertyValue))
            {
                return;
            }
            upgradeInstancesPropertyValue = upgradeInstancesPropertyValue.Trim();

            var forwardErrorMessagesPropertyValue = session["FORWARDERRORMESSAGES"];

            try
            {
                options.OverrideEnableErrorForwarding = bool.Parse(forwardErrorMessagesPropertyValue);
            }
            catch
            {
                options.OverrideEnableErrorForwarding = null;
            }

            var auditRetentionPeriodPropertyValue = session["AUDITRETENTIONPERIOD"];

            try
            {
                options.AuditRetentionPeriod = TimeSpan.Parse(auditRetentionPeriodPropertyValue);
            }
            catch
            {
                options.AuditRetentionPeriod = null;
            }

            var errorRetentionPeriodPropertyValue = session["ERRORRETENTIONPERIOD"];

            try
            {
                options.ErrorRetentionPeriod = TimeSpan.Parse(errorRetentionPeriodPropertyValue);
            }
            catch
            {
                options.ErrorRetentionPeriod = null;
            }

            //determine what to upgrade
            var instancesToUpgrade = new List <ServiceControlInstance>();

            if (upgradeInstancesPropertyValue.Equals("*", StringComparison.OrdinalIgnoreCase) || upgradeInstancesPropertyValue.Equals("ALL", StringComparison.OrdinalIgnoreCase))
            {
                instancesToUpgrade.AddRange(InstanceFinder.ServiceControlInstances());
            }
            else
            {
                var candidates = upgradeInstancesPropertyValue.Replace(" ", String.Empty).Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                instancesToUpgrade.AddRange(InstanceFinder.ServiceControlInstances().Where(instance => candidates.Contains(instance.Name, StringComparer.OrdinalIgnoreCase)));
            }

            // do upgrades
            foreach (var instance in instancesToUpgrade)
            {
                if (zipInfo.Version > instance.Version)
                {
                    if (!instance.AppConfig.AppSettingExists(SettingsList.ForwardErrorMessages.Name) & !options.OverrideEnableErrorForwarding.Value)
                    {
                        logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. FORWARDERRORMESSAGES MSI parameter was required because appsettings needed a value for '{SettingsList.ForwardErrorMessages.Name}'");
                        continue;
                    }

                    if (!options.AuditRetentionPeriod.HasValue)
                    {
                        if (!instance.AppConfig.AppSettingExists(SettingsList.AuditRetentionPeriod.Name))
                        {
                            //Try migration first
                            if (instance.AppConfig.AppSettingExists(SettingsList.HoursToKeepMessagesBeforeExpiring.Name))
                            {
                                var i = instance.AppConfig.Read(SettingsList.HoursToKeepMessagesBeforeExpiring.Name, -1);
                                if (i > 0)
                                {
                                    options.AuditRetentionPeriod = TimeSpan.FromHours(i);
                                }
                            }
                            else
                            {
                                logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. AUDITRETENTIONPERIOD MSI parameter was required because appsettings needed a value for '{SettingsList.AuditRetentionPeriod.Name}'");
                                continue;
                            }
                        }
                    }

                    if (!instance.AppConfig.AppSettingExists(SettingsList.ErrorRetentionPeriod.Name) & !options.ErrorRetentionPeriod.HasValue)
                    {
                        logger.Warn($"Unattend upgrade {instance.Name} to {zipInfo.Version} not attempted. ERRORRETENTIONPERIOD MSI parameter was required because appsettings needed a value for '{SettingsList.ErrorRetentionPeriod.Name}'");
                        continue;
                    }

                    if (!unattendedInstaller.Upgrade(instance, options))
                    {
                        logger.Warn($"Failed to upgrade {instance.Name} to {zipInfo.Version}");
                    }
                }
            }
        }