public void InstallWorkloadPacks(IEnumerable <PackInfo> packInfos, SdkFeatureBand sdkFeatureBand, ITransactionContext transactionContext, DirectoryPath?offlineCache = null) { ReportPendingReboot(); var msisToInstall = GetMsisToInstall(packInfos); foreach (var msiToInstall in msisToInstall) { transactionContext.Run(action: () => { try { // Retrieve the payload from the MSI package cache. MsiPayload msi = GetCachedMsiPayload(msiToInstall.NuGetPackageId, msiToInstall.NuGetPackageVersion, offlineCache); VerifyPackage(msi); DetectState state = DetectPackage(msi, out Version installedVersion); InstallAction plannedAction = PlanPackage(msi, state, InstallAction.Install, installedVersion, out _); ExecutePackage(msi, plannedAction); // Update the reference count against the MSI. UpdateDependent(InstallRequestType.AddDependent, msi.Manifest.ProviderKeyName, _dependent); } catch (Exception e) { LogException(e); throw; } }, rollback: () => { RollBackMsiInstall(msiToInstall); }); } }
/// <summary> /// Executes an MSI package. The type of execution is determined by the requested action. /// </summary> /// <param name="msi">The MSI package to execute.</param> /// <param name="action">The action to perform.</param> private void ExecutePackage(MsiPayload msi, InstallAction action) { uint error = Error.SUCCESS; string logFile = GetMsiLogName(msi, action); switch (action) { case InstallAction.MinorUpdate: case InstallAction.Install: case InstallAction.MajorUpgrade: error = ExecuteWithProgress(String.Format(LocalizableStrings.MsiProgressInstall, msi.Payload), () => InstallMsi(msi.MsiPath, logFile)); ExitOnError(error, $"Failed to install {msi.Payload}."); break; case InstallAction.Repair: error = ExecuteWithProgress(String.Format(LocalizableStrings.MsiProgressRepair, msi.Payload), () => RepairMsi(msi.ProductCode, logFile)); ExitOnError(error, $"Failed to repair {msi.Payload}."); break; case InstallAction.Uninstall: error = ExecuteWithProgress(String.Format(LocalizableStrings.MsiProgressUninstall, msi.Payload), () => UninstallMsi(msi.ProductCode, logFile)); ExitOnError(error, $"Failed to remove {msi.Payload}."); break; case InstallAction.None: case InstallAction.Downgrade: default: break; } }
static int Main(string[] args) { bool shouldContinue = WaitForApplications(); if (!shouldContinue) { Message("Configuration canceled."); return(-1); } ShowMessages = args.Contains <string>("/msg"); var toInstall = new InstallAction[] { Certificates, TrustedSites }; int succeeded = 0; foreach (InstallAction action in toInstall) { if (action(args)) { succeeded++; } } bool success = (succeeded == toInstall.Length); // Try this regardless of success; WpfPlugin(args); Message(success ? "All system configurations were completed successfully." : "Some configurations failed to complete. See application event log for details."); return(success ? 1 : -1); }
public Result <int> InstallUtil( [RequiredCommandParameter(Description = "Install action. Valid values are Install|UnInstall", ExampleValue = InstallAction.Install, AlternativeName = "a")] InstallAction installAction, [RequiredCommandParameter(Description = "Directory with .NET components to process.", ExampleValue = @"c:\Program Fils (x86)\SomeCompany\SomeApplication\1.0.0.0", AlternativeName = "d")] string directory, [RequiredCommandParameter(Description = "Array of file specifications to include, i.e all files matching the include file specfication will be processed.", AlternativeName = "if", ExampleValue = new string[] { "SomeCompany.SomeApplication*.dll", "SomeCompany.SomeApplication*.exe" })] string[] includeFileSpecs, [RequiredCommandParameter(Description = "Array of file specifications to exclude, i.e all files matching the exclude file specfication will not be processed.", AlternativeName = "ef", ExampleValue = new string[] { "Microsoft.*.dll", "Microsoft.*.exe" })] string[] excludeFileSpecs ) { var installUtilCommandProvider = _installUtilCommandProviderFactory.GetInstallUtilCommandProvider(); int returnValue = 0; try { _logger.Info("Start InstallUtil..."); installUtilCommandProvider.InstallUtil(installAction, directory, includeFileSpecs.ToList(), excludeFileSpecs.ToList()); } catch (Exception e) { return(Result.Fail <int>(e)); } finally { _installUtilCommandProviderFactory.Release(installUtilCommandProvider); _logger.Info("Stop InstallUtil."); } return(Result.Ok(returnValue)); }
public void InstallWorkloadPack(PackInfo packInfo, SdkFeatureBand sdkFeatureBand, DirectoryPath?offlineCache = null) { try { ReportPendingReboot(); // Determine the MSI payload package ID based on the host architecture, pack ID and pack version. string msiPackageId = GetMsiPackageId(packInfo); // Retrieve the payload from the MSI package cache. MsiPayload msi = GetCachedMsiPayload(msiPackageId, packInfo.Version, offlineCache); VerifyPackage(msi); DetectState state = DetectPackage(msi, out Version installedVersion); InstallAction plannedAction = PlanPackage(msi, state, InstallAction.Install, installedVersion, out _); ExecutePackage(msi, plannedAction); // Update the reference count against the MSI. UpdateDependent(InstallRequestType.AddDependent, msi.Manifest.ProviderKeyName, _dependent); } catch (Exception e) { LogException(e); RollBackWorkloadPackInstall(packInfo, sdkFeatureBand, offlineCache); } }
public override List <AssetOp> GetInstallOps(ModContext context) { Log.LogMsg($"Installing HookMod component"); if (InstallAction == null) { throw new InvalidOperationException("HookMod is being installed, but has no install action!"); } return(InstallAction.GetInstallOps(context)); }
public PackageAction( PackageKey packageKey, InstallAction instAction, InstallTarget instTarget = InstallTarget.System ) { PackageKey = packageKey; Action = instAction; Target = instTarget; }
public Package AddPostUninstallAction(string item, string global) { var action = new InstallAction() { Action = item, Global = global }; PostUninstallActions.Add(action); return(this); }
private void InstallAction_ProgressChagned(InstallAction sender, int?progress) { if (progress.HasValue) { Progress = progress.Value; IsProgressIndeterminate = false; } else { IsProgressIndeterminate = true; } }
/// <summary> /// Creates the new custom action with the given parameters /// </summary> public override void Execute() { try { IVsdDeployable deployable = (IVsdDeployable)SetupProject.Object; IVsdCollectionSubset plugins = deployable.GetPlugIns(); IVsdCustomActionPlugIn customActionPlugin = plugins.Item("CustomAction") as IVsdCustomActionPlugIn; if (customActionPlugin != null) { customAction = (IVsdCustomAction)DteHelper.CoCreateInstance( this.Site, typeof(VsdCustomActionClass), typeof(IVsdCustomAction)); customAction.Name = this.ActionName; customAction.InstallerClass = true; customAction.Object = this.Assembly; customAction.FileType = vsdCustomActionFileTypes.vsdcaDll; if (InstallAction.Equals("Install")) { customAction.InstallAction = vsdCustomActionInstallActions.vsdcaInstall; } else if (InstallAction.Equals("Uninstall")) { customAction.InstallAction = vsdCustomActionInstallActions.vsdcaUninstall; } else if (InstallAction.Equals("Commit")) { customAction.InstallAction = vsdCustomActionInstallActions.vsdcaCommit; } else if (InstallAction.Equals("Rollback")) { customAction.InstallAction = vsdCustomActionInstallActions.vsdcaRollback; } else { throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, Properties.Resources.AddCustomAction_InvalidInstallAction, InstallAction)); } customAction.CustomActionData = this.CustomActionData; customActionPlugin.Items.Add(customAction); } } catch (Exception) { if (CustomAction != null) { CustomAction = null; } throw; } }
private void btnPreInstalar_Instalar_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtPreInstalar_DiretorioDestino.Text)) { MessageBox.Show(this, "Selecione um diretório para instalação primeiro.", "Atenção!", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } var config = CriarInstalacao(txtPreInstalar_DiretorioDestino.Text); InstallAction.DoAction(config, this); }
public static string NativeName(this InstallAction installAction) { switch (installAction) { case InstallAction.Install: return(Strings.Install); case InstallAction.Uninstall: return(Strings.Uninstall); default: return("??"); } }
public int Execute(InstallAction installAction, string directory, List <string> includeFileSpecs, List <string> excludeFileSpecs) { var returnValue = 0; try { if (!Directory.Exists(directory)) { throw new DirectoryNotFoundException("Directory not found: " + directory); } if (includeFileSpecs.Count == 0) { throw new ArgumentOutOfRangeException("includeFileSpecs", "No files are included"); } _logger.InfoFormat("Action: {0}, Directory: {1}, Include files: '{2}', Exclude files: '{3}'", installAction, directory, string.Join(";", includeFileSpecs), string.Join(";", excludeFileSpecs)); var excludedFiles = _folderFileSearcher.GetFiles(directory, excludeFileSpecs); var includedFiles = _folderFileSearcher.GetFiles(directory, includeFileSpecs); foreach (var includedFile in includedFiles.Values) { if (excludedFiles.ContainsKey(includedFile.Name)) { _logger.InfoFormat("Excluding from install '{0}'", includedFile.FullName); continue; } if (installAction == InstallAction.UnInstall || installAction == InstallAction.UnInstallInstall) { _logger.InfoFormat("UnInstalling '{0}'...", includedFile.FullName); var arguments = GetUnInstallArguments(includedFile); _logger.InfoFormat("Calling the managed installer with the arguments:{0}{1}", Environment.NewLine, string.Join(" ", arguments)); ManagedInstallerClass.InstallHelper(arguments); } if (installAction == InstallAction.Install || installAction == InstallAction.UnInstallInstall) { _logger.InfoFormat("Installing '{0}'...", includedFile.FullName); var arguments = GetInstallArguments(includedFile); _logger.InfoFormat("Calling the managed installer with the arguments:{0}{1}", Environment.NewLine, string.Join(" ", arguments)); ManagedInstallerClass.InstallHelper(arguments); } } } catch (Exception ex) { _logger.ErrorFormat("Failed to execute install action '{0}' on directory '{1}'. {2}", installAction, directory, ex.ToString()); returnValue = 1; } return(returnValue); }
public void RollBackWorkloadPackInstall(PackInfo packInfo, SdkFeatureBand sdkFeatureBand, DirectoryPath?offlineCache = null) { try { ReportPendingReboot(); Log?.LogMessage($"Rolling back workload pack installation for {packInfo.ResolvedPackageId}."); // Determine the MSI payload package ID based on the host architecture, pack ID and pack version. string msiPackageId = GetMsiPackageId(packInfo); // Retrieve the payload from the MSI package cache. MsiPayload msi = GetCachedMsiPayload(msiPackageId, packInfo.Version, offlineCache); VerifyPackage(msi); // Check the provider key first in case we were installed and we only need to remove // a dependent. DependencyProvider depProvider = new DependencyProvider(msi.Manifest.ProviderKeyName); // Try and remove the dependent against this SDK. If any remain we'll simply exit. UpdateDependent(InstallRequestType.RemoveDependent, msi.Manifest.ProviderKeyName, _dependent); if (depProvider.Dependents.Any()) { Log?.LogMessage($"Cannot remove pack, other dependents remain: {string.Join(", ", depProvider.Dependents)}."); return; } // Make sure the MSI is actually installed. DetectState state = DetectPackage(msi, out Version installedVersion); InstallAction plannedAction = PlanPackage(msi, state, InstallAction.Uninstall, installedVersion, out _); // The previous steps would have logged the final action. If the verdict is not to uninstall we can exit. if (plannedAction == InstallAction.Uninstall) { ExecutePackage(msi, plannedAction); } Log?.LogMessage("Rollback completed."); } catch (Exception e) { LogException(e); throw; } }
public int Execute(InstallAction installAction, string directory, List<string> includeFileSpecs, List<string> excludeFileSpecs) { var returnValue = 0; try { if (!Directory.Exists(directory)) throw new DirectoryNotFoundException("Directory not found: " + directory); if (includeFileSpecs.Count == 0) throw new ArgumentOutOfRangeException("includeFileSpecs", "No files are included"); _logger.InfoFormat("Action: {0}, Directory: {1}, Include files: '{2}', Exclude files: '{3}'", installAction, directory, string.Join(";", includeFileSpecs), string.Join(";", excludeFileSpecs)); var excludedFiles = _folderFileSearcher.GetFiles(directory, excludeFileSpecs); var includedFiles = _folderFileSearcher.GetFiles(directory, includeFileSpecs); foreach (var includedFile in includedFiles.Values) { if (excludedFiles.ContainsKey(includedFile.Name)) { _logger.InfoFormat("Excluding from install '{0}'", includedFile.FullName); continue; } if (installAction == InstallAction.UnInstall || installAction == InstallAction.UnInstallInstall) { _logger.InfoFormat("UnInstalling '{0}'...", includedFile.FullName); var arguments = GetUnInstallArguments(includedFile); _logger.InfoFormat("Calling the managed installer with the arguments:{0}{1}", Environment.NewLine, string.Join(" ", arguments)); ManagedInstallerClass.InstallHelper(arguments); } if (installAction == InstallAction.Install || installAction == InstallAction.UnInstallInstall) { _logger.InfoFormat("Installing '{0}'...", includedFile.FullName); var arguments = GetInstallArguments(includedFile); _logger.InfoFormat("Calling the managed installer with the arguments:{0}{1}", Environment.NewLine, string.Join(" ", arguments)); ManagedInstallerClass.InstallHelper(arguments); } } } catch (Exception ex) { _logger.ErrorFormat("Failed to execute install action '{0}' on directory '{1}'. {2}",installAction, directory, ex.ToString()); returnValue = 1; } return returnValue; }
protected override void Uninstall() { Context.ComponentId = GetComponentID(Context); AppConfig.LoadComponentSettings(Context); SetupScript Script = null; switch (ModeExtension) { case ModeExtension.Normal: { Script = new UninstallScript(Context); var Act = new InstallAction(ActionTypes.DeleteShortcuts); Act.Description = "Deleting shortcuts..."; Act.Log = "- Delete shortcuts"; Act.Name = "Login to WebsitePanel.url"; Script.Actions.Add(Act); } break; case ModeExtension.Backup: Script = new BackupScript(Context); break; default: throw new NotImplementedException("Uninstall " + ModeExtension.ToString()); } Script.Run(); }
protected override List<InstallAction> GetActions(string ComponentID) { var Scenario = base.GetActions(ComponentID); var Act = new InstallAction(ActionTypes.StopApplicationPool); Act.Description = "Stopping IIS Application Pool..."; Scenario.Add(Act); Act = new InstallAction(ActionTypes.Backup); Act.Description = "Backing up..."; Scenario.Add(Act); return Scenario; }
public void InstallWorkloadManifest(ManifestId manifestId, ManifestVersion manifestVersion, SdkFeatureBand sdkFeatureBand, DirectoryPath?offlineCache = null, bool isRollback = false) { try { ReportPendingReboot(); // Rolling back a manifest update after a successful install is essentially a downgrade, which is blocked so we have to // treat it as a special case and is different from the install failing and rolling that back, though depending where the install // failed, it may have removed the old product already. Log?.LogMessage($"Installing manifest: Id: {manifestId}, version: {manifestVersion}, feature band: {sdkFeatureBand}, rollback: {isRollback}."); // Resolve the package ID for the manifest payload package string msiPackageId = WorkloadManifestUpdater.GetManifestPackageId(sdkFeatureBand, manifestId, InstallType.Msi).ToString(); string msiPackageVersion = $"{manifestVersion}"; Log?.LogMessage($"Resolving {manifestId} ({manifestVersion}) to {msiPackageId} ({msiPackageVersion})."); // Retrieve the payload from the MSI package cache. MsiPayload msi = GetCachedMsiPayload(msiPackageId, msiPackageVersion, offlineCache); VerifyPackage(msi); DetectState state = DetectPackage(msi.ProductCode, out Version installedVersion); InstallAction plannedAction = PlanPackage(msi, state, InstallAction.Install, installedVersion, out IEnumerable <string> relatedProducts); // If we've detected a downgrade, it's possible we might be doing a rollback after the manifests were updated, // but another error occurred. In this case we need to try and uninstall the upgrade and then install the lower // version of the MSI. The downgrade can also be a deliberate rollback. if (plannedAction == InstallAction.Downgrade && isRollback && state == DetectState.Absent) { Log?.LogMessage($"Rolling back manifest update."); // The provider keys for manifest packages are stable across feature bands so we retain dependents during upgrades. DependencyProvider depProvider = new DependencyProvider(msi.Manifest.ProviderKeyName); // Try and remove the SDK dependency, but ignore any remaining dependencies since // we want to force the removal of the old version. The remaining dependencies and the provider // key won't be removed. UpdateDependent(InstallRequestType.RemoveDependent, msi.Manifest.ProviderKeyName, _dependent); // Since we don't have records for manifests, we need to try and retrieve the ProductCode of // the newer MSI that's installed that we want to remove using its dependency provider. string productCode = depProvider.ProductCode; if (string.IsNullOrWhiteSpace(productCode)) { // We don't know the MSI package that wrote this provider key, so if the ProductCode is missing // we can't do anything else. Log?.LogMessage($"Failed to retrieve the ProductCode for provider: {depProvider.ProviderKeyName}."); return; } Log?.LogMessage($"Found ProductCode {productCode} registered against provider, {depProvider.ProviderKeyName}."); // This is a best effort. If for some reason the manifest installers were fixed, for example, manually // adding additional upgrade paths to work around previous faulty authoring, we may have multiple related // products. The best we can do is to check for at least one match and remove it and then try the rollback. if (!relatedProducts.Contains(productCode, StringComparer.OrdinalIgnoreCase)) { Log?.LogMessage($"Cannot rollback manifest. ProductCode does not match any detected related products."); return; } string logFile = GetMsiLogName(productCode, InstallAction.Uninstall); uint error = UninstallMsi(productCode, logFile, ignoreDependencies: true); ExitOnError(error, "Failed to uninstall manifest package."); // Detect the package again and fall through to the original execution. If that fails, then there's nothing // we could have done. Log?.LogMessage("Replanning manifest package."); state = DetectPackage(msi, out Version _); plannedAction = PlanPackage(msi, state, InstallAction.Install, installedVersion, out IEnumerable <string> _); } ExecutePackage(msi, plannedAction); // Update the reference count against the MSI. UpdateDependent(InstallRequestType.AddDependent, msi.Manifest.ProviderKeyName, _dependent); } catch (Exception e) { LogException(e); throw; } }
/// <summary> /// Creates the log filename to use when executing an MSI. The name is based on the primary log, ProductCode and <see cref="InstallAction"/>. /// </summary> /// <param name="packInfo">The workload pack to use when generating the log name.</param> /// <param name="action">The install action that will be performed.</param> /// <returns>The full path of the log file.</returns> protected string GetMsiLogName(string productCode, InstallAction action) { return(Path.Combine(Path.GetDirectoryName(Log.LogPath), Path.GetFileNameWithoutExtension(Log.LogPath) + $"_{productCode}_{action}.log")); }
protected override List<InstallAction> GenerateBackupActions(string componentId) { List<InstallAction> list = new List<InstallAction>(); InstallAction action = null; string path = Directory.GetParent(Context.ServiceFile).FullName; if (!string.IsNullOrEmpty(path)) { action = new InstallAction(ActionTypes.BackupDirectory); action.Path = path; action.Description = string.Format("Backing up directory {0}...", path); list.Add(action); } return list; }
/// <summary> /// Creates the log filename to use when executing an MSI. The name is based on the primary log, workload pack and <see cref="InstallAction"/>. /// </summary> /// <param name="packInfo">The workload pack to use when generating the log name.</param> /// <param name="action">The install action that will be performed.</param> /// <returns>The full path of the log file.</returns> protected string GetMsiLogName(PackInfo packInfo, InstallAction action) { return(Path.Combine(Path.GetDirectoryName(Log.LogPath), Path.GetFileNameWithoutExtension(Log.LogPath) + $"_{packInfo.ResolvedPackageId}-{packInfo.Version}_{action}.log")); }
/// <summary> /// Creates the log filename to use when executing an MSI. The name is based on the primary log, payload name and <see cref="InstallAction"/>. /// </summary> /// <param name="packInfo">The workload pack to use when generating the log name.</param> /// <param name="action">The install action that will be performed.</param> /// <returns>The full path of the log file.</returns> protected string GetMsiLogName(MsiPayload msi, InstallAction action) { return(Path.Combine(Path.GetDirectoryName(Log.LogPath), Path.GetFileNameWithoutExtension(Log.LogPath) + $"_{msi.Manifest.Payload}_{action}.log")); }
private void InstallAction_MessageChanged(InstallAction sender, string message) { Message = message; }
/// <summary> /// Creates the log filename to use when executing an MSI. The name is based on the primary log, workload pack record and <see cref="InstallAction"/>. /// </summary> /// <param name="record">The workload record to use when generating the log name.</param> /// <param name="action">The install action that will be performed.</param> /// <returns>The full path of the log file.</returns> protected string GetMsiLogName(WorkloadPackRecord record, InstallAction action) { return(Path.Combine(Path.GetDirectoryName(Log.LogPath), Path.GetFileNameWithoutExtension(Log.LogPath) + $"_{record.PackId}-{record.PackVersion}_{action}.log")); }
public Package AddPreUninstallAction(string item, string global) { var action = new InstallAction() { Action = item, Global = global }; PreUninstallActions.Add(action); return this; }
public Result <int> InstallUtil(InstallAction installAction, string directory, List <string> includeFileSpecs, List <string> excludeFileSpecs) { return(Result.Ok(_installUtil.Execute(installAction, directory, includeFileSpecs, excludeFileSpecs))); }
protected override List<InstallAction> GetActions(string componentId) { var list = base.GetActions(componentId); InstallAction action = null; //windows service string serviceName = AppConfig.GetComponentSettingStringValue(componentId, "ServiceName"); string serviceFile = AppConfig.GetComponentSettingStringValue(componentId, "ServiceFile"); string installFolder = AppConfig.GetComponentSettingStringValue(componentId, "InstallFolder"); if (!string.IsNullOrEmpty(serviceName) && !string.IsNullOrEmpty(serviceFile)) { action = new InstallAction(ActionTypes.UnregisterWindowsService); action.Path = serviceFile; // FullFileName. action.Name = serviceName; action.Description = "Removing Windows service..."; action.Log = string.Format("- Remove {0} Windows service", serviceName); list.Add(action); } //database bool deleteDatabase = AppConfig.GetComponentSettingBooleanValue(componentId, "NewDatabase"); bool allowDelete = true; if (Context.InstallerType.ToLowerInvariant().Equals("msi")) // DB handled by MSI (WiX) by default. allowDelete = false; if (deleteDatabase && allowDelete) { string connectionString = AppConfig.GetComponentSettingStringValue(componentId, "InstallConnectionString"); string database = AppConfig.GetComponentSettingStringValue(componentId, "Database"); action = new InstallAction(ActionTypes.DeleteDatabase); action.ConnectionString = connectionString; action.Name = database; action.Description = "Deleting database..."; action.Log = string.Format("- Delete {0} database", database); list.Add(action); } //database user bool deleteDatabaseUser = AppConfig.GetComponentSettingBooleanValue(componentId, "NewDatabaseUser"); if (deleteDatabaseUser) { string connectionString = AppConfig.GetComponentSettingStringValue(componentId, "InstallConnectionString"); string username = AppConfig.GetComponentSettingStringValue(componentId, "DatabaseUser"); action = new InstallAction(ActionTypes.DeleteDatabaseUser); action.ConnectionString = connectionString; action.UserName = username; action.Description = "Deleting database user..."; action.Log = string.Format("- Delete {0} database user", username); list.Add(action); } //database login (from standalone setup) string loginName = AppConfig.GetComponentSettingStringValue(componentId, "DatabaseLogin"); if (!string.IsNullOrEmpty(loginName)) { string connectionString = AppConfig.GetComponentSettingStringValue(componentId, "InstallConnectionString"); action = new InstallAction(ActionTypes.DeleteDatabaseLogin); action.ConnectionString = connectionString; action.UserName = loginName; action.Description = "Deleting database login..."; action.Log = string.Format("- Delete {0} database login", loginName); list.Add(action); } //virtual directory bool deleteVirtualDirectory = AppConfig.GetComponentSettingBooleanValue(componentId, "NewVirtualDirectory"); if (deleteVirtualDirectory) { string virtualDirectory = AppConfig.GetComponentSettingStringValue(componentId, "VirtualDirectory"); string virtualDirectorySiteId = AppConfig.GetComponentSettingStringValue(componentId, "WebSiteId"); action = new InstallAction(ActionTypes.DeleteVirtualDirectory); action.SiteId = virtualDirectorySiteId; action.Name = virtualDirectory; action.Description = "Deleting virtual directory..."; action.Log = string.Format("- Delete {0} virtual directory...", virtualDirectory); list.Add(action); } //web site bool deleteWebSite = AppConfig.GetComponentSettingBooleanValue(componentId, "NewWebSite"); if (deleteWebSite) { string siteId = AppConfig.GetComponentSettingStringValue(componentId, "WebSiteId"); action = new InstallAction(ActionTypes.DeleteWebSite); action.SiteId = siteId; action.Description = "Deleting web site..."; action.Log = string.Format("- Delete {0} web site", siteId); list.Add(action); } //application pool bool deleteAppPool = AppConfig.GetComponentSettingBooleanValue(componentId, "NewApplicationPool"); if (deleteAppPool) { string appPoolName = AppConfig.GetComponentSettingStringValue(componentId, "ApplicationPool"); if (string.IsNullOrEmpty(appPoolName)) appPoolName = WebUtils.WEBSITEPANEL_ADMIN_POOL; action = new InstallAction(ActionTypes.DeleteApplicationPool); action.Name = appPoolName; action.Description = "Deleting application pool..."; action.Log = string.Format("- Delete {0} application pool", appPoolName); list.Add(action); } //user account bool deleteUserAccount = AppConfig.GetComponentSettingBooleanValue(componentId, "NewUserAccount"); if (deleteUserAccount) { string username = AppConfig.GetComponentSettingStringValue(componentId, "UserAccount"); string domain = AppConfig.GetComponentSettingStringValue(componentId, "Domain"); //membership if (Context.UserMembership != null && Context.UserMembership.Length > 0) { action = new InstallAction(ActionTypes.DeleteUserMembership); action.Name = username; action.Domain = domain; action.Membership = Context.UserMembership; action.Description = "Removing user account membership..."; action.Log = string.Format("- Remove {0} user account membership", username); list.Add(action); } action = new InstallAction(ActionTypes.DeleteUserAccount); action.Name = username; action.Domain = domain; action.Description = "Deleting user account..."; action.Log = string.Format("- Delete {0} user account", username); list.Add(action); } // TODO: WiX does not need it by default. //directory //string path = AppConfig.GetComponentSettingStringValue(componentId, "InstallFolder"); //if (!string.IsNullOrEmpty(path)) //{ // action = new InstallAction(ActionTypes.DeleteDirectory); // action.Path = path; // action.Description = "Deleting application folder..."; // action.Log = string.Format("- Delete {0} folder", path); // list.Add(action); //} //config action = new InstallAction(ActionTypes.UpdateConfig); action.Key = componentId; action.Description = "Updating configuration settings..."; action.Log = "- Update configuration settings"; list.Add(action); return list; }
private void SwitchWebPortal2AspNet40(InstallAction action, Setup.SetupVariables setupVariables) { var sam = new WebPortalActionManager(setupVariables); sam.AddAction(new RegisterAspNet40Action()); sam.AddAction(new EnableAspNetWebExtensionAction()); sam.AddAction(new MigrateWebPortalWebConfigAction()); sam.AddAction(new SwitchAppPoolAspNetVersion()); sam.AddAction(new CleanupWebsitePanelModulesListAction()); // sam.ActionError += new EventHandler<ActionErrorEventArgs>((object sender, ActionErrorEventArgs e) => { throw e.OriginalException; }); // sam.Start(); }
/// <summary> /// Executes the specified install action. /// </summary> /// <param name="action">The action.</param> public void ExecuteInstallAction(InstallAction action) { Application.DoEvents(); LoggingUtils.WriteInfo(string.Format(CultureInfo.InvariantCulture, "[----- Executing Action {0} -----]", action.ToString()), ConsoleColor.Cyan); string adminServicesAddress = string.Format("net.tcp://{0}:{1}/Agatha.Common.WCF.IWcfRequestProcessor.svc", Environment.MachineName, AppSettings.NettcpPort); string defaultServicesInstanceAddress = string.Format("net.tcp://{0}:{1}/{2}/Agatha.Common.WCF.IWcfRequestProcessor.svc", Environment.MachineName, AppSettings.NettcpPort, AppSettings.VirtualApplicationName); // Execute action switch (action) { case InstallAction.ClearNetTempFiles: IOUtils.ClearDotNetTempFiles(); break; case InstallAction.StopAuditingService: WindowsServiceUtils.StopService(WindowsService.MEDSEEKAuditingService); break; case InstallAction.StartAuditingService: WindowsServiceUtils.StartService(WindowsService.MEDSEEKAuditingService); break; case InstallAction.CopyApplicationFiles: { var adminServiceInstancePath = Path.Combine(AppSettings.ApplicationFilePath, Constants.BusinessFolder); IISUtils.StopAppPool(adminServiceInstancePath); if (AppSettings.ApplicationMode == ApplicationMode.Install) IOUtils.BuildDirectoryStructure(); IOUtils.CopyFiles(); IISUtils.StartAppPool(adminServiceInstancePath); break; } case InstallAction.CreateAdminServicesInstance: { IISUtils.BuildIISEntities(); break; } case InstallAction.TestAdminServicesInstance: { if (!ServiceUtils.TestServices(adminServicesAddress, 3)) throw new InvalidOperationException("Admin services test failed."); break; } case InstallAction.InstallAuditingService: { var installAuditRequest = new InstallAuditingServiceRequest() { AuditDatabaseInstanceName = AppSettings.AuditDatabaseInstanceName }; SimpleRequestDispatcher.Get<InstallAuditingServiceResponse>(installAuditRequest, adminServicesAddress); break; } case InstallAction.CreateDefaultServicesInstance: { var createServiceInstanceRequest = new CreateServiceInstanceRequest() { ServicesName = AppSettings.VirtualApplicationName, AppPoolUserName = AppSettings.VirtualApplicationPoolIdentity, AppPoolUserPassword = AppSettings.VirtualApplicationPoolIdentityPassword, DefaultAdminUserName = AppSettings.ServicesAdminUserName, DefaultAdminUserPassword = AppSettings.ServicesAdminUserPassword, DefaultPublicUserName = AppSettings.ServicesPublicUserName, DefaultPublicUserPassword = AppSettings.ServicesPublicUserPassword, DatabaseInstanceName = AppSettings.DatabaseInstanceName, DatabaseName = AppSettings.DatabaseName, SampleDataScript = AppSettings.LoadSampleData ? AppSettings.SampleDataScript : null, AuditSiteSubscriptionId = AppSettings.VirtualApplicationAuditSiteSubscriptionId, AllowServiceInstanceOverwrite = CommandLineArgs.Dev, DatabaseBehavior = CommandLineArgs.Dev ? CreateDatabaseBehavior.DestroyExistingAndCreate : CreateDatabaseBehavior.ReuseExistingOrCreate }; SimpleRequestDispatcher.Get<CreateServiceInstanceResponse>(createServiceInstanceRequest, adminServicesAddress); break; } case InstallAction.UpgradeServicesInstances: { var upgradeServiceInstancesRequest = new UpgradeServiceInstancesRequest() { DatabaseBehavior = AppSettings.CreateDatabaseBehavior, SampleDataScript = AppSettings.LoadSampleData ? AppSettings.SampleDataScript : null, UpgradeAllInstances = AppSettings.UpgradeAllInstances, InstanceNames = AppSettings.UpgradeInstances.Split(",".ToCharArray()) }; SimpleRequestDispatcher.Get<UpgradeServiceInstancesResponse>(upgradeServiceInstancesRequest, adminServicesAddress); break; } case InstallAction.TestDefaultServicesInstance: { if (!string.IsNullOrEmpty(AppSettings.VirtualApplicationName)) { if (!ServiceUtils.TestServices(defaultServicesInstanceAddress, 3)) throw new InvalidOperationException("Default services test failed."); } break; } } }
/// <summary> /// Plans the specified MSI payload based on its state and the requested install action. /// </summary> /// <param name="msi">The MSI package to plan.</param> /// <param name="state">The detected state of the package.</param> /// <param name="requestedAction">The requested action to perform.</param> /// <returns>The action that will be performed.</returns> private InstallAction PlanPackage(MsiPayload msi, DetectState state, InstallAction requestedAction, Version installedVersion, out IEnumerable <string> relatedProductCodes) { InstallAction plannedAction = InstallAction.None; HashSet <string> relatedProducts = new(); Log?.LogMessage($"PlanPackage: Begin, name: {msi.Name}, version: {msi.ProductVersion}, state: {state}, installed version: {installedVersion?.ToString() ?? "n/a"}, requested: {requestedAction}."); // Manifest packages should support major upgrades (both the ProductCode and ProductVersion should be different) while // workload packs should always be SxS (ProductCode and Upgrade should be different for each version). // // We cannot discount someone generating a minor update (ProductCode remains unchanged, but ProductVersion changes), // so we'll detect downgrades and minor updates. For more details, see https://docs.microsoft.com/en-us/windows/win32/msi/minor-upgrades. if (state == DetectState.Present) { if (msi.ProductVersion < installedVersion) { Log?.LogMessage($"PlanPackage: Downgrade detected, installed version: {installedVersion}, requested version: {msi.ProductVersion}."); plannedAction = InstallAction.Downgrade; state = DetectState.Superseded; } else if (msi.ProductVersion > installedVersion) { Log?.LogMessage($"PlanPackage: Minor update detected, installed version: {installedVersion}, requested version: {msi.ProductVersion}."); plannedAction = InstallAction.MinorUpdate; state = DetectState.Obsolete; } else { // If the package is installed, then we can uninstall and repair it. plannedAction = (requestedAction != InstallAction.Repair) && (requestedAction != InstallAction.Uninstall) ? InstallAction.None : requestedAction; } } else if (state == DetectState.Absent) { // If we're absent, convert repair to install or keep install. plannedAction = (requestedAction == InstallAction.Repair) ? InstallAction.Install : (requestedAction == InstallAction.Install) ? InstallAction.Install : InstallAction.None; } // At this point we know the MSI is absent so there are only three outcomes when executing the package: // 1. We'll just do a clean install if we don't find related products so we're either brand new or SxS. // 2. We'll perform a major upgrade. // 3. We'll trigger a downgrade and likely an error since most MSIs detect and block downgrades. // // We'll process the related product information to make a determination. This is similar to what the FindRelatedProducts // action does when an MSI is executed. foreach (RelatedProduct relatedProduct in msi.RelatedProducts) { foreach (string relatedProductCode in WindowsInstaller.FindRelatedProducts(relatedProduct.UpgradeCode)) { // Ignore potentially detecting ourselves. if (string.Equals(relatedProductCode, msi.ProductCode, StringComparison.OrdinalIgnoreCase)) { continue; } // Check whether the related product is installed and retrieve its version to determine // how we're related. uint error = WindowsInstaller.GetProductInfo(relatedProductCode, InstallProperty.VERSIONSTRING, out string relatedVersionValue); // Continue searching if the related product is not installed. if (error == Error.UNKNOWN_PRODUCT || error == Error.UNKNOWN_PROPERTY) { continue; } ExitOnError(error, $"PlanPackage: Failed to retrieve version for related product: ProductCode: {relatedProductCode}."); // Parse the version, but don't try to catch any errors. If the version is invalid we want to fail // because we can't compare invalid versions to see whether it's excluded by the VersionMin and VersionMax // columns from the Upgrade table. Version relatedVersion = Version.Parse(relatedVersionValue); if (relatedProduct.ExcludesMinVersion(relatedVersion) || relatedProduct.ExcludesMaxVersion(relatedVersion)) { continue; } // Check if the related product contains a matching language code (LCID). If we don't have any languages, // all languages are detectable as related and we can ignore the msidbUpgradeAttributesLanguagesExclusive flag. if (relatedProduct.Languages.Any()) { string relatedLanguage = "0"; error = WindowsInstaller.GetProductInfo(relatedProductCode, InstallProperty.LANGUAGE, out relatedLanguage); if (int.TryParse(relatedLanguage, out int lcid)) { if (relatedProduct.ExcludesLanguage(lcid)) { continue; } } else { Log?.LogMessage($"PlanPackage: Failed to read Language property for related product, ProductCode: {relatedProductCode}. The related product will be skipped."); continue; } } relatedProducts.Add(relatedProductCode); plannedAction = InstallAction.MajorUpgrade; if (relatedProduct.Attributes.HasFlag(UpgradeAttributes.OnlyDetect) && (state == DetectState.Absent)) { // If we're not installed, but detect-only related, it's very likely that // that we'd trigger a downgrade launch condition. We can't know for sure, but // generally that's the most common use for detect-only entries. plannedAction = InstallAction.Downgrade; } Log?.LogMessage($"PlanPackage: Detected related product, ProductCode: {relatedProductCode}, version: {relatedVersion}, attributes: {relatedProduct.Attributes}, planned action: {plannedAction}."); } } Log?.LogMessage($"PlanPackage: Completed, name: {msi.Name}, version: {msi.ProductVersion}, state: {state}, installed version: {installedVersion?.ToString() ?? "n/a"}, requested: {requestedAction}, planned: {plannedAction}."); relatedProductCodes = relatedProducts.Select(p => p); return(plannedAction); }
private void SwitchServer2AspNet40(InstallAction action, Setup.SetupVariables setupVariables) { var sam = new ServerActionManager(setupVariables); sam.AddAction(new RegisterAspNet40Action()); sam.AddAction(new EnableAspNetWebExtensionAction()); sam.AddAction(new MigrateServerWebConfigAction()); sam.AddAction(new AdjustHttpRuntimeRequestLengthAction()); sam.AddAction(new SwitchAppPoolAspNetVersion()); // sam.ActionError += new EventHandler<ActionErrorEventArgs>((object sender, ActionErrorEventArgs e) => { throw e.OriginalException; }); // sam.Start(); }
/// <summary> /// Cleans up and removes stale workload packs. /// </summary> public void GarbageCollectInstalledWorkloadPacks() { try { Log?.LogMessage("Starting garbage collection."); IEnumerable <SdkFeatureBand> installedFeatureBands = GetInstalledFeatureBands(); IEnumerable <WorkloadId> installedWorkloads = RecordRepository.GetInstalledWorkloads(_sdkFeatureBand); IEnumerable <PackInfo> expectedWorkloadPacks = installedWorkloads .SelectMany(workload => _workloadResolver.GetPacksInWorkload(workload)) .Select(pack => _workloadResolver.TryGetPackInfo(pack)) .Where(pack => pack != null); IEnumerable <WorkloadPackId> expectedPackIds = expectedWorkloadPacks.Select(p => p.Id); foreach (PackInfo expectedPack in expectedWorkloadPacks) { Log?.LogMessage($"Expected workload pack, ID: {expectedPack.ResolvedPackageId}, version: {expectedPack.Version}."); } foreach (SdkFeatureBand installedFeatureBand in installedFeatureBands) { Log?.LogMessage($"Installed feature band: {installedFeatureBand}"); } IEnumerable <WorkloadPackRecord> installedWorkloadPacks = WorkloadPackRecords.Values.SelectMany(r => r); List <WorkloadPackRecord> packsToRemove = new List <WorkloadPackRecord>(); // We first need to clean up the dependents and then do a pass at removing them. Querying the installed packs // is effectively a table scan of the registry to make sure we have accurate information and there's a // potential perf hit for both memory and speed when enumerating large sets of registry entries. foreach (WorkloadPackRecord packRecord in installedWorkloadPacks) { DependencyProvider depProvider = new DependencyProvider(packRecord.ProviderKeyName); // Find all the dependents that look like they belong to SDKs. We only care // about dependents that match the SDK host we're running under. For example, an x86 SDK should not be // modifying the x64 MSI dependents. IEnumerable <string> sdkDependents = depProvider.Dependents .Where(d => d.StartsWith($"{DependentPrefix}")) .Where(d => d.EndsWith($",{HostArchitecture}")); foreach (string dependent in sdkDependents) { Log?.LogMessage($"Evaluating dependent for workload pack, dependent: {dependent}, pack ID: {packRecord.PackId}, pack version: {packRecord.PackVersion}"); // Dependents created by the SDK should have 3 parts, for example, "Microsoft.NET.Sdk,6.0.100,x86". string[] dependentParts = dependent.Split(','); if (dependentParts.Length != 3) { Log?.LogMessage($"Skipping dependent: {dependent}"); continue; } try { SdkFeatureBand dependentFeatureBand = new SdkFeatureBand(dependentParts[1]); if (!installedFeatureBands.Contains(dependentFeatureBand)) { Log?.LogMessage($"Removing dependent '{dependent}' from provider key '{depProvider.ProviderKeyName}' because its SDK feature band does not match any installed feature bands."); UpdateDependent(InstallRequestType.RemoveDependent, depProvider.ProviderKeyName, dependent); } if (dependentFeatureBand.Equals(_sdkFeatureBand)) { // If the current SDK feature band is listed as a dependent, we can validate // the workload pack against the expected pack IDs and versions to potentially remove it. if (!expectedWorkloadPacks.Where(p => packRecord.PackId.Equals(p.ResolvedPackageId)) .Where(p => p.Version.Equals(packRecord.PackVersion.ToString())).Any()) { Log?.LogMessage($"Removing dependent '{dependent}' because the pack record does not match any expected packs."); UpdateDependent(InstallRequestType.RemoveDependent, depProvider.ProviderKeyName, dependent); } } } catch (Exception e) { Log?.LogMessage($"{e.Message}"); Log?.LogMessage($"{e.StackTrace}"); continue; } } // Recheck the registry to see if there are any remaining dependents. If not, we can // remove the workload pack. We'll add it to the list and remove the packs at the end. IEnumerable <string> remainingDependents = depProvider.Dependents; if (remainingDependents.Any()) { Log?.LogMessage($"{packRecord.PackId} ({packRecord.PackVersion}) will not be removed because other dependents remain: {string.Join(", ", remainingDependents)}."); } else { packsToRemove.Add(packRecord); } } foreach (WorkloadPackRecord record in packsToRemove) { // We need to make sure the product is actually installed and that we're not dealing with an orphaned record, e.g. // if a previous removal was interrupted. We can't safely clean up orphaned records because it's too expensive // to query all installed components and determine the product codes associated with the component that // created the record. DetectState state = Detect(record.ProductCode, out string _); if (state == DetectState.Present) { // We don't have package information and can't construct it accurately. string id = $"{record.PackId}.Msi.{HostArchitecture}"; MsiPayload msiPayload = GetCachedMsiPayload(id, record.PackVersion.ToString()); VerifyPackage(msiPayload); InstallAction plannedAction = GetPlannedAction(state, InstallAction.Uninstall); string logFile = GetMsiLogName(record, plannedAction); uint error = ExecuteWithProgress($"Removing {id} ", () => UninstallMsi(record.ProductCode, logFile)); ExitOnError(error, $"Failed to uninstall {msiPayload.MsiPath}."); } } } catch (Exception e) { LogException(e); throw; } }
private List<InstallAction> GenerateBackupActions(string componentId) { List<InstallAction> list = new List<InstallAction>(); InstallAction action = null; //database string connectionString = AppConfig.GetComponentSettingStringValue(componentId, "InstallConnectionString"); if (!String.IsNullOrEmpty(connectionString)) { string database = AppConfig.GetComponentSettingStringValue(componentId, "Database"); action = new InstallAction(ActionTypes.BackupDatabase); action.ConnectionString = connectionString; action.Name = database; action.Description = string.Format("Backing up database {0}...", database); list.Add(action); } //directory string path = AppConfig.GetComponentSettingStringValue(componentId, "InstallFolder"); if (!string.IsNullOrEmpty(path)) { action = new InstallAction(ActionTypes.BackupDirectory); action.Path = path; action.Description = string.Format("Backing up directory {0}...", path); list.Add(action); } //config action = new InstallAction(ActionTypes.BackupConfig); action.Path = Context.BaseDirectory; action.Description = "Backing up configuration settings..."; if (!string.IsNullOrWhiteSpace(Context.SpecialBaseDirectory) ) { action.Path = Context.SpecialBaseDirectory; action.SetupVariables = Context; } list.Add(action); return list; }