private static async Task <InstallationResultViewModel> PerformOperation(IViewModelService viewModelService, IInstallService installService, INotificationService notificationService, InstallerViewModel installerViewModel, InstallationViewModel currentInstallationViewModel, string installerFilePath, bool enableSilentInstallation, bool disableReboot, bool enableInstallationLogging, string?logFolderPath = null) { string?installLogFilePath = null; string?uninstallLogFilePath = null; if (enableInstallationLogging) { if (String.IsNullOrEmpty(logFolderPath)) { Log.Warn("Installation logging is enabled but the logFolderPath is null or empty."); } else if (!Directory.Exists(logFolderPath)) { Log.Warn("logFolderPath is set but the directory doesn't exist."); } else { installLogFilePath = GetLogFilePathForInstaller(logFolderPath !, installerViewModel.Name ?? "unkown", "install"); uninstallLogFilePath = GetLogFilePathForInstaller(logFolderPath !, installerViewModel.Name ?? "unkown", "uninstall"); } } var installArguments = GetArguments( enableSilentInstallation, disableReboot, enableInstallationLogging, installLogFilePath).ToArray(); var uninstallArguments = GetArguments( enableSilentInstallation, disableReboot, enableInstallationLogging, uninstallLogFilePath).ToArray(); var installationResultViewModel = viewModelService.CreateViewModel <InstallationResultViewModel>(installerViewModel); try { switch (installerViewModel.SelectedOperation) { case InstallerOperation.Install: if (installerViewModel.IsInstalled != false) { if (installerViewModel.IsInstalled == null) { Log.Warn($"Installation status of file \"{installerViewModel.FileName}\" is unavailable, trying to uninstall."); } else { Log.Info($"The application \"{installerViewModel.Name}\" with ProductCode \"{installerViewModel.ProductCode}\" is already installed. It will now be uninstalled first."); } if (String.IsNullOrWhiteSpace(installerViewModel.ProductCode)) { var exception = new Exception($"Uninstalling \"{installerViewModel.FileName}\" failed: ProductCode is not set."); Log.Error(exception); if (installerViewModel.IsInstalled == true) { return(CreateInstallationFailedResult(viewModelService, installerViewModel, exception)); } } else { Log.Info($"Uninstalling application of installer \"{installerViewModel.FileName}\" now."); currentInstallationViewModel.CurrentOperation = InstallationOperation.Uninstall; if (enableInstallationLogging && uninstallLogFilePath is string) { installationResultViewModel.InstallationLogFilePaths.Add(uninstallLogFilePath); } try { await installService.PerformAsync(new Operation(installerViewModel.ProductCode, OperationType.Uninstall, uninstallArguments)); Log.Info($"Finished uninstalling."); } catch (Exception exception) { // suppress exception if installation status is unknown if (installerViewModel.IsInstalled == true) { throw; } Log.Warn("Uninstalling failed, but since the installation state is unavailable, the operation will continue", exception); } } } Log.Info($"Installing \"{installerViewModel.FileName}\" now."); currentInstallationViewModel.CurrentOperation = InstallationOperation.Install; if (enableInstallationLogging && installLogFilePath is string) { installationResultViewModel.InstallationLogFilePaths.Add(installLogFilePath); } await installService.PerformAsync(new Operation(installerFilePath, OperationType.Install, installArguments)); Log.Info($"Finished installing."); installationResultViewModel.State = InstallationResultState.Success; break; case InstallerOperation.Uninstall: if (installerViewModel.IsInstalled == null) { Log.Warn($"Installation status of file \"{installerViewModel.FileName}\" is unavailable, trying to uninstall."); } else if (installerViewModel.IsInstalled == false) { Log.Warn($"The application \"{installerViewModel.Name}\" with ProductCode \"{installerViewModel.ProductCode}\" is not installed. Trying to uninstall anyways but it will likely fail."); } else { Log.Info($"The application \"{installerViewModel.Name}\" with ProductCode \"{installerViewModel.ProductCode}\" will now be uninstalled."); } if (String.IsNullOrWhiteSpace(installerViewModel.ProductCode)) { var exception = new Exception($"Uninstalling \"{installerViewModel.FileName}\" failed: ProductCode is not set."); Log.Error(exception); return(CreateInstallationFailedResult(viewModelService, installerViewModel, exception)); } Log.Info($"Uninstalling application of installer \"{installerViewModel.FileName}\" now."); currentInstallationViewModel.CurrentOperation = InstallationOperation.Uninstall; if (enableInstallationLogging && uninstallLogFilePath is string) { installationResultViewModel.InstallationLogFilePaths.Add(uninstallLogFilePath); } await installService.PerformAsync(new Operation(installerViewModel.ProductCode, OperationType.Uninstall, uninstallArguments)); Log.Info($"Finished uninstalling."); installationResultViewModel.State = InstallationResultState.Success; break; default: installationResultViewModel.State = InstallationResultState.Skipped; break; } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception exception) { Log.Error(exception); var errorMessage = installerViewModel.SelectedOperation switch { InstallerOperation.Install => Strings.InstallationOfXFailed, InstallerOperation.Uninstall => Strings.UninstallationOfXFailed, _ => Strings.OperationOfXFailed, }; notificationService.ShowError(String.Format(errorMessage, installerViewModel.Name)); return(CreateInstallationFailedResult(viewModelService, installerViewModel, exception)); } #pragma warning restore CA1031 // Do not catch general exception types return(installationResultViewModel); }