/// <summary> /// This function is the callback used to execute the command when the menu item is clicked. /// See the constructor to see how the menu item is associated with this function using /// OleMenuCommandService service and MenuCommand class. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event args.</param> private async void MenuItemCallback(object sender, EventArgs e) { try { var componentModel = (IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel)); var workspace = componentModel.GetService <VisualStudioWorkspace>(); var selectedItem = this.GetSelectedSolutionExplorerItem(); Microsoft.CodeAnalysis.Document doc = null; if (selectedItem != null && selectedItem.Name != null && !selectedItem.Name.EndsWith(".cs")) { VsShellUtilities.ShowMessageBox(this.package, "Generate DTO action can only be invoked on CSharp files.", "Error", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return; } if (selectedItem?.Document != null) { doc = workspace.CurrentSolution.GetDocumentByFilePath(selectedItem.Document.FullName); } else if (selectedItem != null) { var file = selectedItem.Name; var projectName = selectedItem.ContainingProject.Name; var docs = workspace.CurrentSolution.Projects .Where(p => p.Name == projectName) .SelectMany(p => p.Documents) .Where(d => d.Name == file) .ToList(); if (docs.Count == 0) { VsShellUtilities.ShowMessageBox(this.package, "Shitty exception - cannot get current selected solution item :/// . Try opening desired document, and then activating this command.", "Error", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } if (docs.Count > 1) { VsShellUtilities.ShowMessageBox(this.package, "Multiple documents with same name exist - cannot get current selected solution item. Try opening desired document, and then activating this command.", "Error", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } doc = docs.FirstOrDefault(); } else { VsShellUtilities.ShowMessageBox(this.package, "Shitty exception - cannot get current selected solution item :/// . Try opening desired document, and then activating this command.", "Error", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return; } var possibleProjects = doc.GetPossibleProjects(); var vmBasic = BasicOptionsViewModel.Create(possibleProjects, doc.Name.Replace(".cs", ""), doc.Project.Solution.GetMostLikelyDtoLocation()); var shouldProceed = new BasicOptionsWindow { DataContext = vmBasic }.ShowModal(); if (shouldProceed != true) { return; } var existingDoc = doc.Project.Solution.GetDocumentByLocation(vmBasic.DtoLocation, vmBasic.DtoName); if (existingDoc != null) { var result = VsShellUtilities.ShowMessageBox(this.package, "There is already a DTO class in the specified location. Press OK if you would like to regenerate it, or cancel to choose different name.", "Warninig - regenerate DTO?", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OKCANCEL, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); if (result != 1) { return; } } var vm = await PropertySelectorViewModel.Create(doc, vmBasic.DtoName, vmBasic.DtoLocation, existingDto : existingDoc); var isConfirmed = new PropertySelectorWindow() { DataContext = vm }.ShowModal(); if (isConfirmed == true) { var modifiedSolution = await doc.Project.Solution.WriteDto(vm.DtoLocation, vm.EntityModel.ConvertToMetadata(), vm.GenerateMapper, vm.AddDataContract); var ok = workspace.TryApplyChanges(modifiedSolution); if (!ok) { VsShellUtilities.ShowMessageBox(this.package, "Unable to generate DTO. Please try again (could not apply changes).", "Error", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } } } catch (Exception ex) { try { VsShellUtilities.ShowMessageBox(this.package, ex.Message, "An exception has occurred. Please c/p stack trace to project website (https://github.com/yohney/dto-generator), with brief description of the problem.", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); var tmpFile = Path.GetTempFileName(); string stackTrace = ""; Exception tmp = ex; while (tmp != null) { stackTrace += tmp.StackTrace; stackTrace += "\n----------------------------\n\n"; tmp = ex.InnerException; } File.WriteAllText(tmpFile, stackTrace); VsShellUtilities.OpenBrowser("file:///" + tmpFile); } catch (Exception innerEx) { VsShellUtilities.ShowMessageBox(this.package, innerEx.Message, "An exception has occurred. Unable to write stack trace to TEMP directory.", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } } }