public virtual ExecuteAsyncResponse ImportSolutionAsync(Guid importJobId, byte[] content, bool holdingSolution, bool overwriteUnmanagedCustomizations, bool publishWorkflows, bool skipProductUpdateDependencies) { Logger.Trace(CultureInfo.InvariantCulture, TraceMessageHelper.EnteredMethod, SystemTypeName, MethodBase.GetCurrentMethod().Name); if (Guid.Empty.Equals(importJobId)) { throw new ArgumentNullException(nameof(importJobId)); } if (content == null) { throw new ArgumentNullException(nameof(content)); } ExecuteAsyncRequest req = new ExecuteAsyncRequest { Request = new ImportSolutionRequest { CustomizationFile = content, HoldingSolution = holdingSolution, ImportJobId = importJobId, OverwriteUnmanagedCustomizations = overwriteUnmanagedCustomizations, PublishWorkflows = publishWorkflows, SkipProductUpdateDependencies = skipProductUpdateDependencies } }; ExecuteAsyncResponse res = (ExecuteAsyncResponse)OrganizationService.Execute(req); Logger.Trace(CultureInfo.InvariantCulture, TraceMessageHelper.ExitingMethod, SystemTypeName, MethodBase.GetCurrentMethod().Name); return(res); }
static void Main(string[] args) { System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; Console.WriteLine("Please check the app.config to add credentials and organization url"); string connectionString = ConfigurationManager.ConnectionStrings["CrmDefaultConnection"].ToString(); var serviceClient = new CrmServiceClient(connectionString); serviceClient.OrganizationServiceProxy.Timeout = new TimeSpan(1, 30, 0); if (!serviceClient.IsReady) { throw new Exception("Cannot connect to organization!, Please check the app.config to add credentials and organization url"); } Console.WriteLine("Connected to {0}", serviceClient.ConnectedOrgFriendlyName); Console.WriteLine("Do you want to import the solution Synchronously or Asynchronously ?\n 1 - Sync \n 2 - Async"); string input = Console.ReadLine(); double d; if (Double.TryParse(input, out d)) { if (d == 1)//Synchronous { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); var importSolutionResponse = (ImportSolutionResponse)serviceClient.Execute(ImportSolution(serviceClient)); var est = importSolutionResponse.Results; stopWatch.Stop(); Console.WriteLine("RunTime " + stopWatch.Elapsed); Console.ReadKey(); } else if (d == 2)//Asynchronous { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); ExecuteAsyncRequest request = new ExecuteAsyncRequest(); request.Request = ImportSolution(serviceClient); ExecuteAsyncResponse response = (ExecuteAsyncResponse)serviceClient.Execute(request); stopWatch.Stop(); Console.WriteLine("RunTime " + stopWatch.Elapsed); Console.ReadKey(); } else { Console.WriteLine("Invalid option - bye"); Console.ReadKey(); } } }
public virtual ExecuteAsyncResponse DeleteAndPromoteSolutionAsync(string uniqueName) { Logger.Trace(CultureInfo.InvariantCulture, TraceMessageHelper.EnteredMethod, SystemTypeName, MethodBase.GetCurrentMethod().Name); if (string.IsNullOrWhiteSpace(uniqueName)) { throw new ArgumentNullException(nameof(uniqueName)); } ExecuteAsyncRequest req = new ExecuteAsyncRequest { Request = new DeleteAndPromoteRequest { UniqueName = uniqueName } }; ExecuteAsyncResponse res = (ExecuteAsyncResponse)OrganizationServiceContext.Execute(req); Logger.Trace(CultureInfo.InvariantCulture, TraceMessageHelper.ExitingMethod, SystemTypeName, MethodBase.GetCurrentMethod().Name); return(res); }
/// <summary> /// Method import master solution to deployment instance /// </summary> /// <param name="serviceProxy">organization service proxy</param> /// <param name="solutionFile">solution file</param> /// <param name="uri">URL of Instance</param> public void ImportSolution(OrganizationServiceProxy serviceProxy, SolutionFileInfo solutionFile, Uri uri) { string solutionImportPath = solutionFile.SolutionFilePathManaged ?? solutionFile.SolutionFilePath; Singleton.SolutionFileInfoInstance.WebJobsLog.AppendLine(" Started importing solution to Organization " + uri + "<br>"); Console.WriteLine("Started importing solution to Organization " + uri); byte[] fileBytes = File.ReadAllBytes(solutionImportPath); ImportSolutionRequest impSolReq = new ImportSolutionRequest() { CustomizationFile = fileBytes, ImportJobId = Guid.NewGuid(), OverwriteUnmanagedCustomizations = true, SkipProductUpdateDependencies = true, PublishWorkflows = false, }; ExecuteAsyncRequest importRequest = new ExecuteAsyncRequest() { Request = impSolReq }; ExecuteAsyncResponse importRequestResponse = (ExecuteAsyncResponse)serviceProxy.Execute(importRequest); string solutionImportResult = string.Empty; while (solutionImportResult == string.Empty) { Guid asyncJobId = importRequestResponse.AsyncJobId; Entity job = (Entity)serviceProxy.Retrieve("asyncoperation", asyncJobId, new ColumnSet(new string[] { "asyncoperationid", "statuscode", "message" })); int jobStatusCode = ((OptionSetValue)job["statuscode"]).Value; switch (jobStatusCode) { ////Success case 30: solutionImportResult = "success"; Singleton.SolutionFileInfoInstance.WebJobsLog.AppendLine(" Solution imported successfully to the Organization " + uri + "<br>"); Console.WriteLine("Solution imported successfully to the Organization " + uri); solutionFile.Solution[Constants.SourceControlQueueAttributeNameForStatus] = Constants.SourceControlQueueImportSuccessfulStatus; solutionFile.Solution["syed_webjobs"] = Singleton.SolutionFileInfoInstance.WebJobs(); solutionFile.Update(); break; ////Pausing case 21: solutionImportResult = "pausing"; Singleton.SolutionFileInfoInstance.WebJobsLog.AppendLine(string.Format(" Solution Import Pausing: {0}{1}", jobStatusCode, job["message"]) + "<br>"); Console.WriteLine(string.Format("Solution Import Pausing: {0} {1}", jobStatusCode, job["message"])); break; ////Cancelling case 22: solutionImportResult = "cancelling"; Singleton.SolutionFileInfoInstance.WebJobsLog.AppendLine(string.Format("Solution Import Cancelling: {0}{1}", jobStatusCode, job["message"]) + "<br>"); Console.WriteLine(string.Format("Solution Import Cancelling: {0}{1}", jobStatusCode, job["message"])); break; ////Failed case 31: solutionImportResult = "failed"; Singleton.SolutionFileInfoInstance.WebJobsLog.AppendLine(string.Format("Solution Import Failed: {0}{1}", jobStatusCode, job["message"]) + "<br>"); Console.WriteLine(string.Format("Solution Import Failed: {0}{1}", jobStatusCode, job["message"])); break; ////Cancelled case 32: Console.WriteLine(string.Format("Solution Import Cancelled: {0}{1}", jobStatusCode, job["message"])); Singleton.SolutionFileInfoInstance.WebJobsLog.AppendLine(string.Format("Solution Import Cancelled: {0}{1}", jobStatusCode, job["message"])); throw new Exception(string.Format("Solution Import Cancelled: {0}{1}", jobStatusCode, job["message"])); default: break; } } if (solutionImportResult == "success") { this.PublishAllCustomizationChanges(serviceProxy, solutionFile); solutionFile.Solution[Constants.SourceControlQueueAttributeNameForStatus] = Constants.SourceControlQueuePublishSuccessfulStatus; } solutionFile.Solution.Attributes["syed_webjobs"] = Singleton.SolutionFileInfoInstance.WebJobs(); solutionFile.Update(); }
protected override void ProcessRecord() { base.ProcessRecord(); base.WriteVerbose(string.Format("Importing Solution: {0}", SolutionFilePath)); CrmConnection connection = CrmConnection.Parse(connectionString); if (importJobId == Guid.Empty) { ImportJobId = Guid.NewGuid(); } base.WriteVerbose(string.Format("ImportJobId {0}", ImportJobId)); using (OrganizationService service = new OrganizationService(connection)) { byte[] solutionBytes = File.ReadAllBytes(solutionFilePath); ImportSolutionRequest importSolutionRequest = new ImportSolutionRequest() { CustomizationFile = solutionBytes, PublishWorkflows = publishWorkflows, ConvertToManaged = convertToManaged, OverwriteUnmanagedCustomizations = overwriteUnmanagedCustomizations, SkipProductUpdateDependencies = skipProductUpdateDependencies, ImportJobId = ImportJobId, RequestId = ImportJobId }; if (importAsync) { Guid asyncJobId; ExecuteAsyncRequest asyncRequest = new ExecuteAsyncRequest() { Request = importSolutionRequest, RequestId = ImportJobId }; ExecuteAsyncResponse asyncResponse = service.Execute(asyncRequest) as ExecuteAsyncResponse; asyncJobId = asyncResponse.AsyncJobId; WriteObject(asyncJobId); if (waitForCompletion) { DateTime end = DateTime.Now.AddSeconds(asyncWaitTimeout); bool completed = false; while (!completed) { if (end < DateTime.Now) { throw new Exception(string.Format("Import Timeout Exceeded: {0}", asyncWaitTimeout)); } Thread.Sleep(SleepInterval * 1000); AsyncOperation asyncOperation; try { asyncOperation = service.Retrieve("asyncoperation", asyncJobId, new ColumnSet("asyncoperationid", "statuscode", "message")).ToEntity <AsyncOperation>(); } catch (Exception ex) { base.WriteWarning(ex.Message); continue; } switch (asyncOperation.StatusCode.Value) { //Succeeded case 30: completed = true; break; //Pausing //Canceling //Failed //Canceled case 21: case 22: case 31: case 32: throw new Exception(string.Format("Solution Import Failed: {0} {1}", asyncOperation.StatusCode.Value, asyncOperation.Message)); default: break; } } } } else { ImportSolutionResponse importSolutionResponse = service.Execute(importSolutionRequest) as ImportSolutionResponse; } base.WriteVerbose(string.Format("{0} Imported Completed {1}", SolutionFilePath, importJobId)); } }
/// <summary> /// Imports a Dynamics CRM solution to a Dynamics CRM organization. /// </summary> /// <returns>An <seealso cref="ImportSolutionResult"/> object</returns> public override Result Execute() { if (this.SolutionFileStream == null) { throw new ArgumentNullException(nameof(this.SolutionFileStream)); } var buffer = new byte[(int)this.SolutionFileStream.Length]; this.SolutionFileStream.Read(buffer, 0, buffer.Length); Solution zipSolution = this.ReadSolutionXmlFromZip(this.SolutionFileStream); bool startImport = this.CompareSolutionVersion(zipSolution.GetVersion(), zipSolution.UniqueName); if (!startImport) { return(new Result() { Success = false }); } Entity job; try { var importSolutionRequest = new ImportSolutionRequest { HoldingSolution = this.HoldingSolution, ConvertToManaged = this.ConvertToManaged, CustomizationFile = buffer, ImportJobId = this.ImportJobId, OverwriteUnmanagedCustomizations = this.OverwriteUnmanagedCustomizations, PublishWorkflows = this.PublishWorkflows, SkipProductUpdateDependencies = this.SkipProductUpdateDependencies }; ExecuteAsyncRequest asyncRequest = new ExecuteAsyncRequest() { Request = importSolutionRequest }; ExecuteAsyncResponse asyncResponse = this.CrmOrganization.Execute <ExecuteAsyncResponse>(asyncRequest); this.AsyncJobId = asyncResponse.AsyncJobId; DateTime end = DateTime.Now.AddSeconds(10); while (end >= DateTime.Now) { Entity asyncOperation = this.CrmOrganization.Retrieve("asyncoperation", this.AsyncJobId, new ColumnSet("asyncoperationid", "statuscode", "message")); switch (asyncOperation.GetAttributeValue <OptionSetValue>("statuscode").Value) { // 30: Succeeded // 0: Ready case 0: case 30: break; // 21: Pausing // 22: Canceling // 31: Failed // 32: Canceled case 21: case 22: case 31: case 32: throw new Exception(string.Format("Solution Import Failed: {0} {1}", asyncOperation["statuscode"], asyncOperation["message"])); default: break; } } } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Detail.ErrorCode == CrmErrorCodes.ImportSolutionError) { // Todo: Log this to a file. CreateImportStatus(this.CrmOrganization.GetEntityByField("importjob", "importjobid", this.ImportJobId)); } throw; } ImportSolutionProgress(this.ImportJobId); job = this.CrmOrganization.GetEntityByField("importjob", "importjobid", this.ImportJobId); ImportSolutionResult status = CreateImportStatus(job); Logger.Log($"Solution {this.FileName} was imported with status {status.Status.ToString()}", LogLevel.Info); return(status); }
private bool DoImportSolutionAsync(ImportSolutionRequest impSolReq, ref Exception ex) { log.StartSection(MethodBase.GetCurrentMethod().Name); // Code cred to Wael Hamze // http://waelhamze.com/2013/11/17/asynchronous-solution-import-dynamics-crm-2013/ var result = false; ExecuteAsyncRequest asyncRequest = new ExecuteAsyncRequest() { Request = impSolReq }; ExecuteAsyncResponse asyncResponse = crmsvc.Execute(asyncRequest) as ExecuteAsyncResponse; var asyncJobId = asyncResponse.AsyncJobId; DateTime end = timeout > 0 ? DateTime.Now.AddMinutes(timeout) : DateTime.Now.AddMinutes(2); log.Log("Timout until: {0}", end.ToString("HH:mm:ss.fff")); var importStatus = -1; var progress = 0; var statustext = "Submitting job"; SendLineUpdate("Import status: {0}", statustext); while (end >= DateTime.Now) { CintDynEntity cdAsyncOperation = null; try { cdAsyncOperation = CintDynEntity.Retrieve("asyncoperation", asyncJobId, new ColumnSet("asyncoperationid", "statecode", "statuscode", "message", "friendlymessage"), crmsvc, log); } catch (Exception asyncex) { cdAsyncOperation = null; log.Log(asyncex); log.EndSection(); // Ending section started by Retrieve above to prevent indentation inflation } if (cdAsyncOperation != null) { statustext = cdAsyncOperation.PropertyAsString("statuscode", "?", false, false); var newStatus = cdAsyncOperation.Property("statuscode", new OptionSetValue()).Value; if (newStatus != importStatus) { importStatus = newStatus; SendLineUpdate("Import status: {0}", statustext); log.Log("Import message:\n{0}", cdAsyncOperation.Property("message", "<none>")); if (importStatus == 30) { // Succeeded result = true; break; } else if (importStatus == 21 || importStatus == 22 || importStatus == 31 || importStatus == 32) { // Error statuses var friendlymessage = cdAsyncOperation.Property("friendlymessage", ""); SendLine("Message: {0}", friendlymessage); if (friendlymessage == "Access is denied.") { SendLine("When importing to onprem environment, the async service user must be granted read/write permission to folder:"); SendLine(" C:\\Program Files\\Microsoft Dynamics CRM\\CustomizationImport"); } else { var message = cdAsyncOperation.Property("message", "<none>"); message = ExtractErrorMessage(message); if (!string.IsNullOrWhiteSpace(message) && !message.Equals(friendlymessage, StringComparison.InvariantCultureIgnoreCase)) { SendLine("Detailed message: \n{0}", message); } else { SendLine("See log file for technical details."); } } ex = new Exception(string.Format("Solution Import Failed: {0} - {1}", cdAsyncOperation.PropertyAsString("statecode", "?", false, false), cdAsyncOperation.PropertyAsString("statuscode", "?", false, false))); break; } } } System.Threading.Thread.Sleep(1000); if (importStatus == 20) { // In progress, read percent try { var job = CintDynEntity.Retrieve("importjob", impSolReq.ImportJobId, new ColumnSet("progress"), crmsvc, log); if (job != null) { var newProgress = job.Property("progress", 0D); if (newProgress > progress + 5) { progress = Convert.ToInt32(Math.Round(newProgress)); SendStatus(-1, -1, 100, progress); SendLineUpdate("Import status: {0} - {1}%", statustext, progress); } } } catch (Exception jobex) { // We probably tried before the job was created if (jobex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { log.Log("Importjob not created yet or already deleted"); } else { log.Log(jobex); } log.EndSection(); // Ending section started by Retrieve above to prevent indentation inflation } } } if (end < DateTime.Now) { SendLine("Import timed out."); } SendStatus(-1, -1, 100, 0); log.EndSection(); return(result); }