private void AddOrUpdateMapping(CrmSolution solution) { try { var path = Path.GetDirectoryName(ConnPane.SelectedProject.FullName); if (!SharedConfigFile.ConfigFileExists(ConnPane.SelectedProject)) { _logger.WriteToOutputWindow("Error Updating Mappings In Config File: Missing CRMDeveloperExtensions.config File", Logger.MessageType.Error); return; } XmlDocument doc = new XmlDocument(); doc.Load(path + "\\CRMDeveloperExtensions.config"); //Update or delete existing mapping XmlNodeList solutionNodes = doc.GetElementsByTagName("Solution"); if (solutionNodes.Count > 0) { foreach (XmlNode node in solutionNodes) { bool changed = false; XmlNode orgId = node["OrgId"]; if (orgId != null && orgId.InnerText.ToUpper() != ConnPane.SelectedConnection.OrgId.ToUpper()) continue; XmlNode projectNameNode = node["ProjectName"]; if (projectNameNode != null && projectNameNode.InnerText.ToUpper() != solution.BoundProject.ToUpper()) continue; if (string.IsNullOrEmpty(solution.BoundProject) || solution.SolutionId == Guid.Empty) { //Delete var parentNode = node.ParentNode; if (parentNode != null) { parentNode.RemoveChild(node); changed = true; } } else { //Update XmlNode solutionIdNode = node["SolutionId"]; if (solutionIdNode != null) { string oldSolutionId = solutionIdNode.InnerText; if (oldSolutionId != solution.SolutionId.ToString()) { solutionIdNode.InnerText = solution.SolutionId.ToString(); changed = true; } } XmlNode downloadManagedNode = node["DownloadManaged"]; if (downloadManagedNode != null) { string oldDownloadManaged = downloadManagedNode.InnerText; string downloadManagedValue = (solution.DownloadManagedSolution) ? "true" : "false"; if (oldDownloadManaged != downloadManagedValue) { downloadManagedNode.InnerText = downloadManagedValue; changed = true; } } } if (!changed) return; if (SharedConfigFile.IsConfigReadOnly(path + "\\CRMDeveloperExtensions.config")) { FileInfo file = new FileInfo(path + "\\CRMDeveloperExtensions.config") { IsReadOnly = false }; } doc.Save(path + "\\CRMDeveloperExtensions.config"); return; } } //Create new mapping XmlNodeList projects = doc.GetElementsByTagName("Solutions"); if (projects.Count <= 0) return; XmlNode solutionNode = doc.CreateElement("Solution"); XmlNode org = doc.CreateElement("OrgId"); org.InnerText = ConnPane.SelectedConnection.OrgId; solutionNode.AppendChild(org); XmlNode projectNameNode2 = doc.CreateElement("ProjectName"); projectNameNode2.InnerText = solution.BoundProject; solutionNode.AppendChild(projectNameNode2); XmlNode solutionId = doc.CreateElement("SolutionId"); solutionId.InnerText = solution.SolutionId.ToString(); solutionNode.AppendChild(solutionId); XmlNode downloadManaged = doc.CreateElement("DownloadManaged"); downloadManaged.InnerText = (DownloadManaged.IsChecked == true) ? "true" : "false"; solutionNode.AppendChild(downloadManaged); projects[0].AppendChild(solutionNode); if (SharedConfigFile.IsConfigReadOnly(path + "\\CRMDeveloperExtensions.config")) { FileInfo file = new FileInfo(path + "\\CRMDeveloperExtensions.config") { IsReadOnly = false }; } doc.Save(path + "\\CRMDeveloperExtensions.config"); } catch (Exception ex) { _logger.WriteToOutputWindow("Error Updating Mappings In Config File: " + ex.Message + Environment.NewLine + ex.StackTrace, Logger.MessageType.Error); } }
private string GetSolutionFromCrm(string connString, CrmSolution selectedSolution, bool managed) { try { CrmConnection connection = CrmConnection.Parse(connString); // Hardcode connection timeout to one-hour to support large solutions. connection.Timeout = new TimeSpan(1, 0, 0); using (_orgService = new OrganizationService(connection)) { ExportSolutionRequest request = new ExportSolutionRequest { Managed = managed, SolutionName = selectedSolution.UniqueName }; ExportSolutionResponse response = (ExportSolutionResponse)_orgService.Execute(request); var tempFolder = Path.GetTempPath(); string fileName = Path.GetFileName(selectedSolution.UniqueName + "_" + FormatVersionString(selectedSolution.Version) + ((managed) ? "_managed" : String.Empty) + ".zip"); var tempFile = Path.Combine(tempFolder, fileName); if (File.Exists(tempFile)) File.Delete(tempFile); File.WriteAllBytes(tempFile, response.ExportSolutionFile); return tempFile; } } catch (FaultException<OrganizationServiceFault> crmEx) { _logger.WriteToOutputWindow("Error Retrieving Solution From CRM: " + crmEx.Message + Environment.NewLine + crmEx.StackTrace, Logger.MessageType.Error); return null; } catch (Exception ex) { _logger.WriteToOutputWindow("Error Retrieving Solution From CRM: " + ex.Message + Environment.NewLine + ex.StackTrace, Logger.MessageType.Error); return null; } }
private void CreatePackage(CrmSolution selectedSolution, Version version, string savePath, Project project) { try { //https://msdn.microsoft.com/en-us/library/jj602987.aspx#arguments CommandWindow cw = _dte2.ToolWindows.CommandWindow; var props = _dte.Properties["CRM Developer Extensions", "Solution Packager"]; string spPath = (string)props.Item("SolutionPackagerPath").Value; if (string.IsNullOrEmpty(spPath)) { MessageBox.Show("Set SDK bin folder path under Tools -> Options -> CRM Developer Extensions"); return; } if (!spPath.EndsWith("\\")) spPath += "\\"; string toolPath = @"""" + spPath + "SolutionPackager.exe" + @""""; if (!File.Exists(spPath + "SolutionPackager.exe")) { MessageBox.Show("SolutionPackager.exe not found at: " + spPath); return; } string filename = selectedSolution.UniqueName + "_" + FormatVersionString(version) + ".zip"; string command = toolPath + " /action: Pack"; command += " /zipfile:" + "\"" + savePath + "\\" + filename + "\""; command += " /folder: " + "\"" + Path.GetDirectoryName(ConnPane.SelectedProject.FullName) + "\""; // Use a mapping file if one exists in the root folder of the project and be named mapping.xml if (File.Exists(Path.GetDirectoryName(ConnPane.SelectedProject.FullName) + "\\mapping.xml")) { command += " /map:" + "\"" + Path.GetDirectoryName(ConnPane.SelectedProject.FullName) + "\\mapping.xml\""; } cw.SendInput("shell " + command, true); AddNewSolutionToProject(savePath, project, filename); } catch (Exception ex) { _logger.WriteToOutputWindow("Error launching Solution Packager: " + Environment.NewLine + Environment.NewLine + ex.Message, Logger.MessageType.Error); } }
private async Task<bool> ExtractPackage(string path, CrmSolution selectedSolution, Project project, bool? downloadManaged) { //https://msdn.microsoft.com/en-us/library/jj602987.aspx#arguments try { CommandWindow cw = _dte2.ToolWindows.CommandWindow; var props = _dte.Properties["CRM Developer Extensions", "Solution Packager"]; string spPath = (string)props.Item("SolutionPackagerPath").Value; if (string.IsNullOrEmpty(spPath)) { MessageBox.Show("Set SDK bin folder path under Tools -> Options -> CRM Developer Extensions"); return false; } if (!spPath.EndsWith("\\")) spPath += "\\"; string toolPath = @"""" + spPath + "SolutionPackager.exe" + @""""; if (!File.Exists(spPath + "SolutionPackager.exe")) { MessageBox.Show("SolutionPackager.exe not found at: " + spPath); return false; } string tempDirectory = Path.GetDirectoryName(path); if (Directory.Exists(tempDirectory + "\\" + Path.GetFileNameWithoutExtension(path))) Directory.Delete(tempDirectory + "\\" + Path.GetFileNameWithoutExtension(path), true); DirectoryInfo extractedFolder = Directory.CreateDirectory(tempDirectory + "\\" + Path.GetFileNameWithoutExtension(path)); string command = toolPath + " /action: Extract"; command += " /zipfile:" + "\"" + path + "\""; command += " /folder: " + "\"" + extractedFolder.FullName + "\""; command += " /clobber"; // Add a mapping file which should be in the root folder of the project and be named mapping.xml if (File.Exists(Path.GetDirectoryName(ConnPane.SelectedProject.FullName) + "\\mapping.xml")) { command += " /map:" + "\"" + Path.GetDirectoryName(ConnPane.SelectedProject.FullName) + "\\mapping.xml\""; } // Write Solution Package output to a log file named SolutionPackager.log in the root folder of the project command += " /log:" + "\"" + Path.GetDirectoryName(ConnPane.SelectedProject.FullName) + "\\SolutionPackager.log\""; // Unpack managed solution as well. if (downloadManaged == true) { command += " /packagetype:Both"; } cw.SendInput("shell " + command, true); //Need this. Extend to allow bigger solutions to unpack System.Threading.Thread.Sleep(10000); bool solutionFileDelete = RemoveDeletedItems(extractedFolder.FullName, ConnPane.SelectedProject.ProjectItems); bool solutionFileAddChange = ProcessDownloadedSolution(extractedFolder, Path.GetDirectoryName(ConnPane.SelectedProject.FullName), ConnPane.SelectedProject.ProjectItems); Directory.Delete(extractedFolder.FullName, true); //Solution change or file not present bool solutionChange = solutionFileDelete || solutionFileAddChange; StoreSolutionFile(path, project, solutionChange); return solutionChange; } catch (Exception ex) { _logger.WriteToOutputWindow("Error launching Solution Packager: " + Environment.NewLine + Environment.NewLine + ex.Message, Logger.MessageType.Error); return false; } }
private async Task<bool> GetSolutions(string connString) { _dte.StatusBar.Text = "Connecting to CRM and getting solutions..."; _dte.StatusBar.Animate(true, vsStatusAnimation.vsStatusAnimationSync); LockMessage.Content = "Working..."; LockOverlay.Visibility = Visibility.Visible; EntityCollection results = await Task.Run(() => GetSolutionsFromCrm(connString)); if (results == null) { _dte.StatusBar.Clear(); _dte.StatusBar.Animate(false, vsStatusAnimation.vsStatusAnimationSync); LockOverlay.Visibility = Visibility.Hidden; MessageBox.Show("Error Retrieving Solutions. See the Output Window for additional details."); return false; } _logger.WriteToOutputWindow("Retrieved Solutions From CRM", Logger.MessageType.Info); ObservableCollection<CrmSolution> solutions = new ObservableCollection<CrmSolution>(); CrmSolution emptyItem = new CrmSolution { SolutionId = Guid.Empty, Name = String.Empty }; solutions.Add(emptyItem); foreach (Entity entity in results.Entities) { CrmSolution solution = new CrmSolution { SolutionId = entity.Id, Name = entity.GetAttributeValue<string>("friendlyname"), Prefix = entity.GetAttributeValue<AliasedValue>("publisher.customizationprefix").Value.ToString(), UniqueName = entity.GetAttributeValue<string>("uniquename"), Version = Version.Parse(entity.GetAttributeValue<string>("version")) }; solutions.Add(solution); } //Empty on top var i = solutions.IndexOf( solutions.FirstOrDefault(s => s.SolutionId == new Guid("00000000-0000-0000-0000-000000000000"))); var item = solutions[i]; solutions.RemoveAt(i); solutions.Insert(0, item); //Default second i = solutions.IndexOf( solutions.FirstOrDefault(s => s.SolutionId == new Guid("FD140AAF-4DF4-11DD-BD17-0019B9312238"))); item = solutions[i]; solutions.RemoveAt(i); solutions.Insert(1, item); solutions = HandleMappings(solutions); SolutionToPackage.ItemsSource = solutions; if (solutions.Count(s => !string.IsNullOrEmpty(s.BoundProject)) > 0) { SolutionToPackage.SelectedItem = solutions.First(s => !string.IsNullOrEmpty(s.BoundProject)); var selectedProject = ConnPane.SelectedProject; if (selectedProject != null) SolutionToPackage.IsEnabled = !File.Exists(Path.GetDirectoryName(selectedProject.FullName) + "\\Other\\Solution.xml"); } else SolutionToPackage.IsEnabled = true; CrmSolution crmSolution = solutions.FirstOrDefault(s => !string.IsNullOrEmpty(s.BoundProject)); DownloadManaged.IsChecked = crmSolution != null && solutions.First(s => !string.IsNullOrEmpty(s.BoundProject)).DownloadManagedSolution; _dte.StatusBar.Clear(); _dte.StatusBar.Animate(false, vsStatusAnimation.vsStatusAnimationSync); LockOverlay.Visibility = Visibility.Hidden; return true; }
private async Task<bool> ExtractPackage(string path, CrmSolution selectedSolution, Project project, bool? downloadManaged) { //https://msdn.microsoft.com/en-us/library/jj602987.aspx#arguments try { CommandWindow cw = _dte2.ToolWindows.CommandWindow; var props = _dte.Properties["CRM Developer Extensions", "Solution Packager"]; string spPath = (string)props.Item("SolutionPackagerPath").Value; if (string.IsNullOrEmpty(spPath)) { MessageBox.Show("Set SDK bin folder path under Tools -> Options -> CRM Developer Extensions"); return false; } if (!spPath.EndsWith("\\")) spPath += "\\"; string toolPath = @"""" + spPath + "SolutionPackager.exe" + @""""; if (!File.Exists(spPath + "SolutionPackager.exe")) { MessageBox.Show("SolutionPackager.exe not found at: " + spPath); return false; } string tempDirectory = Path.GetDirectoryName(path); if (Directory.Exists(tempDirectory + "\\" + Path.GetFileNameWithoutExtension(path))) Directory.Delete(tempDirectory + "\\" + Path.GetFileNameWithoutExtension(path), true); DirectoryInfo extractedFolder = Directory.CreateDirectory(tempDirectory + "\\" + Path.GetFileNameWithoutExtension(path)); string command = toolPath + " /action: Extract"; command += " /zipfile:" + "\"" + path + "\""; command += " /folder: " + "\"" + extractedFolder.FullName + "\""; command += " /clobber"; cw.SendInput("shell " + command, true); //Need this System.Threading.Thread.Sleep(1000); bool solutionFileDelete = RemoveDeletedItems(extractedFolder.FullName, ConnPane.SelectedProject.ProjectItems); bool solutionFileAddChange = ProcessDownloadedSolution(extractedFolder, Path.GetDirectoryName(ConnPane.SelectedProject.FullName), ConnPane.SelectedProject.ProjectItems); Directory.Delete(extractedFolder.FullName, true); //Solution change or file not present bool solutionChange = solutionFileDelete || solutionFileAddChange; StoreSolutionFile(path, project, solutionChange); //Download Managed if (downloadManaged != true) return false; path = await Task.Run(() => GetSolutionFromCrm(ConnPane.SelectedConnection.ConnectionString, selectedSolution, true)); if (string.IsNullOrEmpty(path)) { _dte.StatusBar.Clear(); LockOverlay.Visibility = Visibility.Hidden; MessageBox.Show("Error Retrieving Solution. See the Output Window for additional details."); return false; } return solutionChange; } catch (Exception ex) { _logger.WriteToOutputWindow("Error launching Solution Packager: " + Environment.NewLine + Environment.NewLine + ex.Message, Logger.MessageType.Error); return false; } }