using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using System; using System.ComponentModel.Design; using Task = System.Threading.Tasks.Task; using PortingAssistantVSExtensionClient.Models; using EnvDTE; using EnvDTE80; using PortingAssistantVSExtensionClient.Utils; using System.Collections.Generic; using PortingAssistantVSExtensionClient.Options; using Microsoft.VisualStudio.PlatformUI; using PortingAssistantVSExtensionClient.Dialogs; using PortingAssistantVSExtensionClient.Common; using System.Threading; using System.IO; namespace PortingAssistantVSExtensionClient.Commands { /// /// Command handler /// internal sealed class ProjectPortingCommand { /// /// Command ID. /// public const int CommandId = PackageIds.cmdidProjectPortingCommand; /// /// Command menu group (command set GUID). /// public static readonly Guid CommandSet = new Guid(PackageGuids.guidPortingAssistantVSExtensionClientPackageCmdSetString); /// /// VS Package that provides this command, not null. /// private readonly AsyncPackage package; /// /// Initializes a new instance of the class. /// Adds our command handlers for menu (commands must exist in the command table file) /// /// Owner package, not null. /// Command service to add command to, not null. private ProjectPortingCommand(AsyncPackage package, OleMenuCommandService commandService) { this.package = package ?? throw new ArgumentNullException(nameof(package)); commandService = commandService ?? throw new ArgumentNullException(nameof(commandService)); var menuCommandID = new CommandID(CommandSet, CommandId); var menuItem = new MenuCommand(this.Execute, menuCommandID); commandService.AddCommand(menuItem); } /// /// Gets the instance of the command. /// public static ProjectPortingCommand Instance { get; private set; } private string selectedProjectName = ""; /// /// Gets the service provider from the owner package. /// private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider { get { return this.package; } } /// /// Initializes the singleton instance of the command. /// /// Owner package, not null. public static async Task InitializeAsync(AsyncPackage package) { // Switch to the main thread - the call to AddCommand in ProjectPortingCommand's constructor requires // the UI thread. await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken); OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; Instance = new ProjectPortingCommand(package, commandService); } /// /// 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. /// /// Event sender. /// Event args. private async void Execute(object sender, EventArgs e) { try { if (!await CommandsCommon.CheckLanguageServerStatusAsync()) { NotificationUtils.ShowInfoMessageBox(PAGlobalService.Instance.Package, "Porting Assistant cannot be activated. Please open any .cs/.vb file if its not already opened.", "Porting Assistant can not be activated."); return; } if (!CommandsCommon.SetupPage()) return; string SelectedProjectPath = SolutionUtils.GetSelectedProjectPath(); selectedProjectName = Path.GetFileName(SelectedProjectPath); if (!UserSettings.Instance.SolutionAssessed) { NotificationUtils.ShowInfoMessageBox(this.package, "Please run a full assessment before porting", ""); return; } if (string.IsNullOrEmpty(SelectedProjectPath)) { NotificationUtils.ShowInfoMessageBox(this.package, "Please select or open a project", "Porting a project"); return; } if (UserSettings.Instance.TargetFramework.Equals(TargetFrameworkType.NO_SELECTION)) { if (!SelectTargetDialog.EnsureExecute()) return; } if (!PortingDialog.EnsureExecute(selectedProjectName)) return; string SolutionFile = await CommandsCommon.GetSolutionPathAsync(); CommandsCommon.EnableAllCommand(false); string pipeName = Guid.NewGuid().ToString(); CommandsCommon.RunPortingAsync(SolutionFile, new List { SelectedProjectPath }, pipeName, selectedProjectName); PipeUtils.StartListenerConnection(pipeName, GetPortingCompletionTasks(this.package, selectedProjectName, UserSettings.Instance.TargetFramework)); } catch (Exception ex) { NotificationUtils.ShowErrorMessageBox(this.package, $"Porting failed for {selectedProjectName} due to {ex.Message}", "Porting failed"); CommandsCommon.EnableAllCommand(true); } } public Func GetPortingCompletionTasks(AsyncPackage package, string selectedProject, string targetFramework) { async Task CompletionTask() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); try { var successfulMessage = $"The project has been ported to {targetFramework}" + (UserSettings.Instance.ApplyPortAction? $".{Environment.NewLine}Code changes have been applied" : ""); NotificationUtils.ShowInfoMessageBox( package, successfulMessage, "Porting successful"); await NotificationUtils.ShowInfoBarAsync(package, successfulMessage); await NotificationUtils.UseStatusBarProgressAsync(2, 2, successfulMessage); } catch (Exception ex) { NotificationUtils.ShowErrorMessageBox( package, $"Porting failed for {selectedProject} due to {ex.Message}", "Porting failed"); } finally { CommandsCommon.EnableAllCommand(true); } } return CompletionTask; } } }