public List <SolutionImportResult> ImportSolutions( string importFolder, string logsFolder, SolutionImportConfig config) { List <SolutionImportResult> results = new List <SolutionImportResult>(); foreach (SolutionImportOptions option in config.Solutions) { SolutionImportResult result = ImportSolution( importFolder, logsFolder, option); results.Add(result); if (!result.Success) { break; } } return(results); }
public SolutionImportResult ImportSolution( string importFolder, string logsFolder, SolutionImportOptions options) { SolutionImportResult importResult = ImportSolution( $"{importFolder}\\{options.SolutionFilePath}", options.PublishWorkflows, options.ConvertToManaged, options.OverwriteUnmanagedCustomizations, options.SkipProductUpdateDependencies, options.HoldingSolution, options.OverrideSameVersion, options.ImportAsync, options.SleepInterval, options.AsyncWaitTimeout, Guid.NewGuid(), true, logsFolder, string.Empty); if (importResult.Success && options.ApplySolution) { SolutionApplyResult applyResult = ApplySolution( importResult.SolutionName, options.ApplyAsync, options.SleepInterval, options.AsyncWaitTimeout); importResult.Success = applyResult.Success; importResult.ErrorMessage = applyResult.ErrorMessage; } return(importResult); }
private SolutionImportResult VerifySolutionImport( bool importAsync, Guid importJobId, AsyncOperation asyncOperation, Exception syncImportException) { SolutionImportResult result = new SolutionImportResult(); Logger.LogVerbose("Verifying Solution Import"); ImportJobManager jobManager = new ImportJobManager(Logger, OrganizationService); ImportJob importJob = jobManager.GetImportJob( importJobId, new ColumnSet("importjobid", "completedon", "progress", "data")); if (importJob == null) { result.ImportJobAvailable = false; if (importAsync) { result.ErrorMessage = asyncOperation != null ? asyncOperation.Message : ""; } else { result.ErrorMessage = syncImportException != null ? syncImportException.Message : ""; } Logger.LogError("Can't verify as import job couldn't be found. Error Message: {0}", result.ErrorMessage); return(result); } else { result.ImportJobAvailable = true; } if (importJob.Progress == 100) { Logger.LogInformation("Completed Progress: {0}", importJob.Progress); } else { Logger.LogWarning("Completed Progress: {0}", importJob.Progress); } Logger.LogInformation("Completed On: {0}", importJob.CompletedOn); XmlDocument doc = new XmlDocument(); doc.LoadXml(importJob.Data); XmlNode resultNode = doc.SelectSingleNode("//solutionManifest/result/@result"); String solutionImportResult = resultNode != null ? resultNode.Value : null; Logger.LogInformation("Import Result: {0}", solutionImportResult); XmlNode errorNode = doc.SelectSingleNode("//solutionManifest/result/@errortext"); String solutionImportError = errorNode != null ? errorNode.Value : null; Logger.LogInformation("Import Error: {0}", solutionImportError); result.ErrorMessage = solutionImportError; XmlNodeList unprocessedNodes = doc.SelectNodes("//*[@processed=\"false\"]"); result.UnprocessedComponents = unprocessedNodes.Count; if (unprocessedNodes.Count > 0) { Logger.LogWarning("Total number of unprocessed components: {0}", unprocessedNodes.Count); } else { Logger.LogInformation("Total number of unprocessed components: {0}", unprocessedNodes.Count); } if (solutionImportResult == ImportSuccess) { result.Success = true; } return(result); }
public SolutionImportResult ImportSolution( string solutionFilePath, bool publishWorkflows, bool convertToManaged, bool overwriteUnmanagedCustomizations, bool skipProductUpdateDependencies, bool holdingSolution, bool overrideSameVersion, bool importAsync, int sleepInterval, int asyncWaitTimeout, Guid?importJobId, bool downloadFormattedLog, string logDirectory, string logFileName ) { Logger.LogInformation("Importing Solution: {0}", solutionFilePath); if (!importJobId.HasValue || importJobId.Value == Guid.Empty) { importJobId = Guid.NewGuid(); } Logger.LogVerbose("ImportJobId {0}", importJobId); if (asyncWaitTimeout == 0) { asyncWaitTimeout = 15 * 60; } Logger.LogVerbose("AsyncWaitTimeout: {0}", asyncWaitTimeout); if (sleepInterval == 0) { sleepInterval = 15; } Logger.LogVerbose("SleepInterval: {0}", sleepInterval); if (!File.Exists(solutionFilePath)) { Logger.LogError("Solution File does not exist: {0}", solutionFilePath); throw new FileNotFoundException("Solution File does not exist", solutionFilePath); } SolutionImportResult result = null; XrmSolutionInfo info = GetSolutionInfo(solutionFilePath); if (info == null) { result = new SolutionImportResult() { ErrorMessage = "Invalid Solution File" }; return(result); } else { Logger.LogInformation("Solution Unique Name: {0}, Version: {1}", info.UniqueName, info.Version); } bool skipImport = SkipImport(info, holdingSolution, overrideSameVersion); if (skipImport) { Logger.LogInformation("Solution Import Skipped"); result = new SolutionImportResult() { Success = true, ImportSkipped = true }; return(result); } if (downloadFormattedLog) { if (string.IsNullOrEmpty(logFileName)) { logFileName = $"{info.UniqueName}_{(info.Version).Replace('.', '_')}_{DateTime.Now.ToString("yyyy_MM_dd__HH_mm")}.xml"; Logger.LogVerbose("Settings logFileName to {0}", logFileName); } if (string.IsNullOrEmpty(logDirectory)) { logDirectory = Path.GetDirectoryName(solutionFilePath); Logger.LogVerbose("Settings logDirectory to {0}", logDirectory); } if (!Directory.Exists(logDirectory)) { Logger.LogError("logDirectory not exist: {0}", logDirectory); throw new DirectoryNotFoundException("logDirectory does not exist"); } } byte[] solutionBytes = File.ReadAllBytes(solutionFilePath); var importSolutionRequest = new ImportSolutionRequest { CustomizationFile = solutionBytes, PublishWorkflows = publishWorkflows, ConvertToManaged = convertToManaged, OverwriteUnmanagedCustomizations = overwriteUnmanagedCustomizations, SkipProductUpdateDependencies = skipProductUpdateDependencies, ImportJobId = importJobId.Value, RequestId = importJobId, HoldingSolution = holdingSolution }; if (importAsync) { Logger.LogVerbose(string.Format("Importing solution in Async Mode")); var asyncRequest = new ExecuteAsyncRequest { Request = importSolutionRequest }; var asyncResponse = OrganizationService.Execute(asyncRequest) as ExecuteAsyncResponse; Guid asyncJobId = asyncResponse.AsyncJobId; Logger.LogVerbose("Awaiting for Async Operation Completion"); AsyncUpdateHandler updateHandler = new AsyncUpdateHandler( Logger, PollingOrganizationService, importJobId.Value); AsyncOperationManager operationManager = new AsyncOperationManager(Logger, PollingOrganizationService); AsyncOperation asyncOperation = operationManager.AwaitCompletion( asyncJobId, asyncWaitTimeout, sleepInterval, updateHandler); Logger.LogInformation("Async Operation completed with status: {0}", ((AsyncOperation_StatusCode)asyncOperation.StatusCode.Value).ToString()); Logger.LogInformation("Async Operation completed with message: {0}", asyncOperation.Message); result = VerifySolutionImport(importAsync, importJobId.Value, asyncOperation, null); } else { Logger.LogVerbose("Importing solution in Sync Mode"); SyncImportHandler importHandler = new SyncImportHandler( Logger, OrganizationService, importSolutionRequest); ImportJobHandler jobHandler = new ImportJobHandler( Logger, OrganizationService, importHandler); Logger.LogVerbose("Creating Import Task"); Action importAction = () => importHandler.ImportSolution(); Task importTask = new Task(importAction); Logger.LogVerbose("Starting Import Task"); importTask.Start(); Logger.LogVerbose("Thread Started. Starting to Query Import Status"); ImportJobManager jobManager = new ImportJobManager(Logger, PollingOrganizationService); jobManager.AwaitImportJob(importJobId.Value, asyncWaitTimeout, sleepInterval, true, jobHandler); importTask.Wait(); result = VerifySolutionImport(importAsync, importJobId.Value, null, importHandler.Error); } if (result.ImportJobAvailable && downloadFormattedLog) { ImportJobManager jobManager = new ImportJobManager(Logger, OrganizationService); jobManager.SaveFormattedLog(importJobId.Value, logDirectory, logFileName); } if (result.Success) { Logger.LogInformation("Solution Import Completed Successfully"); } else { Logger.LogInformation("Solution Import Failed"); } return(result); }
public void VerifySolutionImport_PrettyPrintErrorMessage(XmlDocument importJobDoc, SolutionImportResult result) { try { Logger.LogVerbose("Check for missing dependencies"); // Find solution import error details var missingDependencies = importJobDoc.SelectSingleNode("//solutionManifest/result/parameters/parameter/text()[starts-with(., '<MissingDependencies><MissingDependency>')]"); if (missingDependencies != null) { Logger.LogVerbose("Logging missing dependencies"); var errorDoc = new XmlDocument(); errorDoc.LoadXml(missingDependencies.Value); //Add information to 'MissingDependencies' { var errorTypeAttributes = errorDoc.SelectNodes("//@type"); foreach (XmlAttribute errorTypeAttribute in errorTypeAttributes) { if (Enum.TryParse <ComponentType>(errorTypeAttribute.Value, out var type)) { var typeAttribute = errorDoc.CreateAttribute("typeName"); typeAttribute.Value = type.ToString(); errorTypeAttribute.OwnerElement.Attributes.Append(typeAttribute); } } } var sb = new StringBuilder(); var settings = new XmlWriterSettings { Indent = true, IndentChars = " ", NewLineChars = Environment.NewLine, NewLineHandling = NewLineHandling.Replace }; using (XmlWriter writer = XmlWriter.Create(sb, settings)) { errorDoc.Save(writer); } result.ErrorMessage += Environment.NewLine; result.ErrorMessage += sb.ToString(); } else { Logger.LogVerbose("No missing dependencies detected"); } } catch (Exception ex) { Logger.LogWarning(ex.Message); } }