關注本人微信和易信公眾號: 微軟動態CRM專家羅勇 ,回復258或者20170627可方便獲取本文,同時可以在第一間得到我發布的最新的博文信息,follow me!我的網站是 www.luoyong.me 。
在我們做項目的過程中,一般會涉及到多個Dynamics 365環境,一般包括一個開發環境、一個SIT環境,一個UAT環境和一個生產環境,經常涉及到解決方案從開發環境遷移到SIT環境,從開發環境遷移到UAT環境,從開發環境遷移到生產環境等等。一般手工操作是先更改解決方案版本,保存后發布解決方案,再導出解決方案,再導入解決方案到目標環境。一個解決方案還好,解決方案多了麻煩,容易手誤或者漏操作,可以寫個程序來做這些繁雜的事情嗎?Follow me。
直接上代碼,代碼中有注釋說明,注意我這里是導入到同一個環境,你使用我的代碼的時候要改動到其他CRM環境,我這里的示例是遷移一個解決方案包,項目中很一般是遷移多個。我這里導出解決方案是放在電腦的下載文件夾中:
1 public static IServiceManagement<IOrganizationService> sm; 2 static void Main(string[] args) 3 { 4 try 5 { 6 sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri("https://demo.luoyong.me/XRMServices/2011/Organization.svc")); 7 ClientCredentials credentials = new ClientCredentials(); 8 credentials.UserName.UserName = "crmadmin@luoyong.me"; 9 credentials.UserName.Password = "Pass"; 10 using (var _serviceProxy = new OrganizationServiceProxy(sm, credentials)) 11 { 12 _serviceProxy.Timeout = new TimeSpan(0, 20, 0);//默認為兩分鍾,這里設置為20分鍾 13 _serviceProxy.EnableProxyTypes(); 14 Console.WriteLine("Dynamics 365中可見的解決方案列表:" + DateTime.Now.ToLongTimeString()); 15 QueryExpression qe = new QueryExpression("solution"); 16 qe.ColumnSet = new ColumnSet("uniquename", "friendlyname", "version", "solutionpackageversion", "ismanaged"); 17 qe.Criteria.AddCondition("isvisible", ConditionOperator.Equal, true); 18 qe.AddOrder("uniquename", OrderType.Ascending); 19 var solutions = _serviceProxy.RetrieveMultiple(qe); 20 foreach(var item in solutions.Entities) 21 { 22 Console.WriteLine(string.Format("uniquename={0};friendlyname={1};version={2};solutionpackageversion={3};ismanaged={4}", 23 item.GetAttributeValue<string>("uniquename"), 24 item.GetAttributeValue<string>("friendlyname"), 25 item.GetAttributeValue<string>("version"), 26 item.GetAttributeValue<string>("solutionpackageversion"), 27 item.GetAttributeValue<bool>("ismanaged"))); 28 Console.WriteLine(new String('-',80)); 29 } 30 Console.WriteLine("開始查詢要導出的解決方案並更改版本信息" + DateTime.Now.ToLongTimeString()); 31 var toExpSolutionUniqueName = "DemoSolution"; 32 qe = new QueryExpression("solution"); 33 qe.ColumnSet = new ColumnSet("version"); 34 qe.Criteria.AddCondition("uniquename", ConditionOperator.Equal, toExpSolutionUniqueName); 35 qe.TopCount = 1; 36 solutions = _serviceProxy.RetrieveMultiple(qe); 37 if(solutions.Entities.Count >= 1) 38 { 39 var solution = solutions.Entities[0]; 40 solution["version"] = string.Format("8.2.{0}.{1}", DateTime.Now.Month, DateTime.Now.Day); 41 _serviceProxy.Update(solution); 42 } 43 Console.WriteLine("開始發布所有自定義項" + DateTime.Now.ToLongTimeString()); 44 PublishAllXmlRequest pubReq = new PublishAllXmlRequest(); 45 _serviceProxy.Execute(pubReq); 46 Console.WriteLine("開始導出" + DateTime.Now.ToLongTimeString()); 47 ExportSolutionRequest exportSolutionRequest = new ExportSolutionRequest(); 48 exportSolutionRequest.Managed = false; 49 exportSolutionRequest.SolutionName = toExpSolutionUniqueName; 50 exportSolutionRequest.TargetVersion = "8.2";//Dynamics 365導出時候可以選擇目標環境用什么版本 51 ExportSolutionResponse exportSolutionResponse = (ExportSolutionResponse)_serviceProxy.Execute(exportSolutionRequest); 52 byte[] exportXml = exportSolutionResponse.ExportSolutionFile; 53 string filename = string.Format("{0}_{1}.zip", toExpSolutionUniqueName, solutions.Entities[0].GetAttributeValue<string>("version").Replace('.','_')); 54 File.WriteAllBytes(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments).Replace("Documents", "Downloads") + "\\" + filename, exportXml); 55 Console.WriteLine("開始導入" + DateTime.Now.ToLongTimeString()); 56 byte[] fileBytes = File.ReadAllBytes(System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments).Replace("Documents", "Downloads") + "\\" + filename); 57 ImportSolutionRequest impReq = new ImportSolutionRequest() 58 { 59 CustomizationFile = fileBytes, 60 PublishWorkflows = true 61 }; 62 _serviceProxy.Execute(impReq); 63 Console.WriteLine("開始發布所有自定義項" + DateTime.Now.ToLongTimeString()); 64 pubReq = new PublishAllXmlRequest(); 65 _serviceProxy.Execute(pubReq); 66 Console.WriteLine("程序運行成功!"); 67 Console.ReadKey(); 68 } 69 } 70 catch (FaultException ex) 71 { 72 Console.WriteLine("程序出現異常:ex.Message=" + ex.Message); 73 Console.ReadKey(); 74 } 75 }
展示效果如下圖:展示效果如下圖:
可能你會對PublishAllXmlRequest這個消息產生疑問,這個是發布哪個解決方案的所有自定義項,實驗證明應該是發布所有解決方案的所有自定義項。在導出解決方案之前請執行下這個消息確保所有的自定義項都發布了,在導入解決方案之后也執行下這個消息導入后的解決方案生效。
Dynamics 365的一個新增功能是導出解決方案時候可以指定解決方案的版本,可以選擇 8.0, 8.1或者8.2,我這個導出程序使用了默認的 8.2.
值得說明的是高級查找並不能查詢解決方案這個實體,所以我這里用的是QueryExpression這種查詢方法,而不是使用FetchXml來查詢。當然兩者是可以互相轉換的。查看這個實體的元數據還是使用Dynamics 365提供的Metadata Browser這個解決方案吧。
導入解決方案可以使用異步操作,請參考:
Use ExecuteAsync to execute messages asynchronously 。示例如下:
string ManagedSolutionLocation = @"C:\temp\ManagedSolutionForImportExample.zip"; byte[] fileBytes = File.ReadAllBytes(ManagedSolutionLocation); ImportSolutionRequest impSolReq = new ImportSolutionRequest() { CustomizationFile = fileBytes }; ExecuteAsyncRequest asyncReq = new ExecuteAsyncRequest() { Request = impSolReq }; var asyncResp = (ExecuteAsyncResponse)svc.Execute(asyncReq); Guid asyncOperationId = asyncResp.AsyncJobId;