private async Task <bool> CheckPackageManagementFormat(INuGetUI uiService, CancellationToken token) { var potentialProjects = new List <NuGetProject>(); // check if project suppports <PackageReference> items. // otherwise don't show format selector dialog for this project var capableProjects = uiService .Projects .Where(project => project.ProjectStyle == ProjectModel.ProjectStyle.PackagesConfig && project.ProjectServices.Capabilities.SupportsPackageReferences); // get all packages.config based projects with no installed packages foreach (var project in capableProjects) { var installedPackages = await project.GetInstalledPackagesAsync(token); if (!installedPackages.Any()) { potentialProjects.Add(project); } } // only show this dialog if there are any new project(s) with no installed packages. if (potentialProjects.Count > 0) { var packageManagementFormat = new PackageManagementFormat(uiService.Settings); if (!packageManagementFormat.Enabled) { // user disabled this prompt either through Tools->options or previous interaction of this dialog. // now check for default package format, if its set to PackageReference then update the project. if (packageManagementFormat.SelectedPackageManagementFormat == 1) { await uiService.UpdateNuGetProjectToPackageRef(potentialProjects); } return(true); } packageManagementFormat.ProjectNames = potentialProjects .Select(project => project.GetMetadata <string>(NuGetProjectMetadataKeys.Name)) .OrderBy(name => name, StringComparer.OrdinalIgnoreCase).ToList(); // show dialog for package format selector var result = uiService.PromptForPackageManagementFormat(packageManagementFormat); // update nuget projects if user selected PackageReference option if (result && packageManagementFormat.SelectedPackageManagementFormat == 1) { await uiService.UpdateNuGetProjectToPackageRef(potentialProjects); } return(result); } return(true); }
public async Task UpgradeNuGetProjectAsync(INuGetUI uiService, NuGetProject nuGetProject) { var context = uiService.UIContext; // Restore the project before proceeding var solutionDirectory = context.SolutionManager.SolutionDirectory; await context.PackageRestoreManager.RestoreMissingPackagesInSolutionAsync(solutionDirectory, uiService.ProjectContext, CancellationToken.None); var packagesDependencyInfo = await context.PackageManager.GetInstalledPackagesDependencyInfo(nuGetProject, CancellationToken.None, includeUnresolved : true); var upgradeInformationWindowModel = new NuGetProjectUpgradeWindowModel(nuGetProject, packagesDependencyInfo.ToList()); var result = uiService.ShowNuGetUpgradeWindow(upgradeInformationWindowModel); if (!result) { // raise upgrade telemetry event with Cancelled status var packagesCount = upgradeInformationWindowModel.UpgradeDependencyItems.Count; var upgradeTelemetryEvent = VSTelemetryServiceUtility.GetUpgradeTelemetryEvent( uiService.Projects, NuGetOperationStatus.Cancelled, packagesCount); TelemetryActivity.EmitTelemetryEvent(upgradeTelemetryEvent); return; } var progressDialogData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage); string backupPath; using (var progressDialogSession = context.StartModalProgressDialog(Resources.WindowTitle_NuGetMigrator, progressDialogData, uiService)) { backupPath = await PackagesConfigToPackageReferenceMigrator.DoUpgradeAsync( context, uiService, nuGetProject, upgradeInformationWindowModel.UpgradeDependencyItems, upgradeInformationWindowModel.NotFoundPackages, progressDialogSession.Progress, progressDialogSession.UserCancellationToken); } if (!string.IsNullOrEmpty(backupPath)) { var htmlLogFile = GenerateUpgradeReport(nuGetProject, backupPath, upgradeInformationWindowModel); Process process = null; try { process = Process.Start(htmlLogFile); } catch { } } }
/// <summary> /// Calculates the list of actions needed to perform packages updates. /// </summary> /// <param name="uiService">ui service.</param> /// <param name="packagesToUpdate">The list of packages to update.</param> /// <param name="token">Cancellation token.</param> /// <returns>The list of actions.</returns> private async Task <IReadOnlyList <ResolvedAction> > ResolveActionsForUpdate( INuGetUI uiService, List <PackageIdentity> packagesToUpdate, CancellationToken token) { var resolvedActions = new List <ResolvedAction>(); // Keep a single gather cache across projects var gatherCache = new GatherCache(); foreach (var project in uiService.Projects) { var installedPackages = await project.GetInstalledPackagesAsync(token); HashSet <string> packageIds = new HashSet <string>(StringComparer.OrdinalIgnoreCase); foreach (var p in installedPackages) { packageIds.Add(p.PackageIdentity.Id); } // We need to filter out packages from packagesToUpdate that are not installed // in the current project. Otherwise, we'll incorrectly install a // package that is not installed before. var packagesToUpdateInProject = packagesToUpdate.Where( package => packageIds.Contains(package.Id)).ToList(); if (packagesToUpdateInProject.Any()) { var includePrerelease = packagesToUpdateInProject.Where( package => package.Version.IsPrerelease).Any(); var resolutionContext = new ResolutionContext( uiService.DependencyBehavior, includePrelease: includePrerelease, includeUnlisted: true, versionConstraints: VersionConstraints.None, gatherCache: gatherCache); var actions = await _packageManager.PreviewUpdatePackagesAsync( packagesToUpdateInProject, project, resolutionContext, uiService.ProgressWindow, uiService.ActiveSources, uiService.ActiveSources, token); resolvedActions.AddRange(actions.Select(action => new ResolvedAction(project, action)) .ToList()); } } return(resolvedActions); }
public PackageManagerModel(INuGetUI uiController, bool isSolution, Guid editorFactoryGuid) { if (uiController == null) { throw new ArgumentNullException(nameof(uiController)); } UIController = uiController; IsSolution = isSolution; _editorFactoryGuid = editorFactoryGuid; }
/// <summary> /// Perform a user action. /// </summary> /// <remarks>This needs to be called from a background thread. It may hang on the UI thread.</remarks> public async Task PerformActionAsync( INuGetUI uiService, UserAction userAction, CancellationToken token) { var operationType = NuGetOperationType.Install; if (userAction.Action == NuGetProjectActionType.Uninstall) { operationType = NuGetOperationType.Uninstall; } await PerformActionImplAsync( uiService, (sourceCacheContext) => { var projects = uiService.Projects; // Allow prerelease packages only if the target is prerelease var includePrelease = userAction.Action == NuGetProjectActionType.Uninstall || userAction.Version.IsPrerelease == true; var includeUnlisted = userAction.Action == NuGetProjectActionType.Uninstall; var resolutionContext = new ResolutionContext( uiService.DependencyBehavior, includePrelease, includeUnlisted, VersionConstraints.None, new GatherCache(), sourceCacheContext); return(GetActionsAsync( uiService, projects, userAction, uiService.RemoveDependencies, uiService.ForceRemove, resolutionContext, projectContext: uiService.ProjectContext, token: token)); }, (actions, sourceCacheContext) => { return(ExecuteActionsAsync(actions, uiService.ProjectContext, uiService.CommonOperations, userAction, sourceCacheContext, token)); }, operationType, userAction, token); }
/// <summary> /// Warns the user about the fact that the dotnet TFM is deprecated. /// </summary> /// <returns>Returns true if the user wants to ignore the warning or if the warning does not apply.</returns> private bool ShouldContinueDueToDotnetDeprecation( INuGetUI uiService, IEnumerable <ResolvedAction> actions, CancellationToken token) { var projects = DotnetDeprecatedPrompt.GetAffectedProjects(actions); if (projects.Any()) { return(uiService.WarnAboutDotnetDeprecation(projects)); } return(true); }
/// <summary> /// Perform a user action. /// </summary> /// <remarks>This needs to be called from a background thread. It may hang on the UI thread.</remarks> public async Task PerformActionAsync( INuGetUI uiService, UserAction userAction, DependencyObject windowOwner, CancellationToken token) { var stopWatch = new Stopwatch(); stopWatch.Start(); await PerformActionImplAsync( uiService, () => { var projects = uiService.Projects; // Allow prerelease packages only if the target is prerelease var includePrelease = userAction.Action == NuGetProjectActionType.Uninstall || userAction.Version.IsPrerelease == true; var includeUnlisted = userAction.Action == NuGetProjectActionType.Uninstall; var resolutionContext = new ResolutionContext( uiService.DependencyBehavior, includePrelease, includeUnlisted, VersionConstraints.None); return(GetActionsAsync( uiService, projects, userAction, uiService.RemoveDependencies, uiService.ForceRemove, resolutionContext, projectContext: uiService.ProgressWindow, token: token)); }, (actions) => { return(ExecuteActionsAsync(actions, uiService.ProgressWindow, userAction, token)); }, windowOwner, token); stopWatch.Stop(); uiService.ProgressWindow.Log(ProjectManagement.MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, stopWatch.Elapsed)); }
/// <summary> /// Return the resolve package actions /// </summary> protected async Task <IEnumerable <Tuple <NuGetProject, NuGetProjectAction> > > GetActions( INuGetUI uiService, IEnumerable <NuGetProject> targets, UserAction userAction, bool removeDependencies, bool forceRemove, ResolutionContext resolutionContext, INuGetProjectContext projectContext, CancellationToken token) { List <Tuple <NuGetProject, NuGetProjectAction> > results = new List <Tuple <NuGetProject, NuGetProjectAction> >(); Debug.Assert(userAction.PackageId != null, "Package id can never be null in a User action"); if (userAction.Action == NuGetProjectActionType.Install) { Debug.Assert(userAction.PackageIdentity != null, "Package identity cannot be null when installing a package"); foreach (var target in targets) { IEnumerable <NuGetProjectAction> actions; actions = await _packageManager.PreviewInstallPackageAsync(target, userAction.PackageIdentity, resolutionContext, projectContext, uiService.ActiveSource, null, token); results.AddRange(actions.Select(a => new Tuple <NuGetProject, NuGetProjectAction>(target, a))); } } else { UninstallationContext uninstallationContext = new UninstallationContext( removeDependencies: removeDependencies, forceRemove: forceRemove); foreach (var target in targets) { IEnumerable <NuGetProjectAction> actions; if (userAction.PackageIdentity != null) { actions = await _packageManager.PreviewUninstallPackageAsync(target, userAction.PackageIdentity, uninstallationContext, projectContext, token); } else { actions = await _packageManager.PreviewUninstallPackageAsync(target, userAction.PackageId, uninstallationContext, projectContext, token); } results.AddRange(actions.Select(a => new Tuple <NuGetProject, NuGetProjectAction>(target, a))); } } return(results); }
/// <summary> /// Return the resolve package actions /// </summary> private async Task <IReadOnlyList <ResolvedAction> > GetActionsAsync( INuGetUI uiService, IEnumerable <NuGetProject> targets, UserAction userAction, bool removeDependencies, bool forceRemove, ResolutionContext resolutionContext, INuGetProjectContext projectContext, CancellationToken token) { var results = new List <ResolvedAction>(); Debug.Assert(userAction.PackageId != null, "Package id can never be null in a User action"); if (userAction.Action == NuGetProjectActionType.Install) { foreach (var target in targets) { var actions = await _packageManager.PreviewInstallPackageAsync( target, new PackageIdentity(userAction.PackageId, userAction.Version), resolutionContext, projectContext, uiService.ActiveSources, null, token); results.AddRange(actions.Select(a => new ResolvedAction(target, a))); } } else { var uninstallationContext = new UninstallationContext( removeDependencies: removeDependencies, forceRemove: forceRemove); foreach (var target in targets) { IEnumerable <NuGetProjectAction> actions; actions = await _packageManager.PreviewUninstallPackageAsync( target, userAction.PackageId, uninstallationContext, projectContext, token); results.AddRange(actions.Select(a => new ResolvedAction(target, a))); } } return(results); }
/// <summary> /// Get the package metadata to see if RequireLicenseAcceptance is true /// </summary> private async Task <List <IPackageSearchMetadata> > GetPackageMetadataAsync( INuGetUI uiService, IEnumerable <PackageIdentity> packages, CancellationToken token) { var results = new List <IPackageSearchMetadata>(); // local sources var sources = new List <SourceRepository>(); sources.Add(_packageManager.PackagesFolderSourceRepository); sources.AddRange(_packageManager.GlobalPackageFolderRepositories); var allPackages = packages.ToArray(); // first check all the packages with local sources. var completed = (await TaskCombinators.ThrottledAsync( allPackages, (p, t) => GetPackageMetadataAsync(sources, p, t), token)).Where(metadata => metadata != null).ToArray(); results.AddRange(completed); if (completed.Length != allPackages.Length) { // get remaining package's metadata from remote repositories var remainingPackages = allPackages.Where(package => !completed.Any(pack => pack.Identity.Equals(package))); var remoteResults = (await TaskCombinators.ThrottledAsync( remainingPackages, (p, t) => GetPackageMetadataAsync(uiService.ActiveSources, p, t), token)).Where(metadata => metadata != null).ToArray(); results.AddRange(remoteResults); } // check if missing metadata for any package if (allPackages.Length != results.Count) { var package = allPackages.First(pkg => !results.Any(result => result.Identity.Equals(pkg))); throw new InvalidOperationException( string.Format("Unable to find metadata of {0}", package)); } return(results); }
/// <summary> /// Calculates the list of actions needed to perform packages updates. /// </summary> /// <param name="uiService">ui service.</param> /// <param name="packagesToUpdate">The list of packages to update.</param> /// <param name="token">Cancellation token.</param> /// <returns>The list of actions.</returns> private async Task <IReadOnlyList <ResolvedAction> > ResolveActionsForUpdateAsync( INuGetUI uiService, List <PackageIdentity> packagesToUpdate, CancellationToken token) { var resolvedActions = new List <ResolvedAction>(); // Keep a single gather cache across projects var gatherCache = new GatherCache(); var includePrerelease = packagesToUpdate.Where( package => package.Version.IsPrerelease).Any(); using (var sourceCacheContext = new SourceCacheContext()) { var resolutionContext = new ResolutionContext( uiService.DependencyBehavior, includePrelease: includePrerelease, includeUnlisted: true, versionConstraints: VersionConstraints.None, gatherCache: gatherCache, sourceCacheContext: sourceCacheContext); var secondarySources = _sourceProvider.GetRepositories().Where(e => e.PackageSource.IsEnabled); var actions = await _packageManager.PreviewUpdatePackagesAsync( packagesToUpdate, uiService.Projects, resolutionContext, uiService.ProjectContext, uiService.ActiveSources, secondarySources, token); resolvedActions.AddRange(actions.Select(action => new ResolvedAction(action.Project, action)) .ToList()); } return(resolvedActions); }
/// <summary> /// Perform the multi-package update action. /// </summary> /// <remarks>This needs to be called from a background thread. It may make the UI thread stop responding.</remarks> public async Task PerformUpdateAsync( INuGetUI uiService, List <PackageIdentity> packagesToUpdate, CancellationToken cancellationToken) { IServiceBroker serviceBroker = uiService.UIContext.ServiceBroker; using (INuGetProjectManagerService projectManagerService = await serviceBroker.GetProxyAsync <INuGetProjectManagerService>( NuGetServices.ProjectManagerService, cancellationToken: cancellationToken)) { Assumes.NotNull(projectManagerService); await PerformActionAsync( uiService, userAction : null, NuGetOperationType.Update, (projectManagerService) => ResolveActionsForUpdateAsync(projectManagerService, uiService, packagesToUpdate, cancellationToken), cancellationToken); } }
/// <summary> /// Calculates the list of actions needed to perform packages updates. /// </summary> private async Task <IReadOnlyList <ProjectAction> > ResolveActionsForUpdateAsync( INuGetProjectManagerService projectManagerService, INuGetUI uiService, List <PackageIdentity> packagesToUpdate, CancellationToken token) { bool includePrerelease = packagesToUpdate .Where(package => package.Version.IsPrerelease) .Any(); string[] projectIds = uiService.Projects.Select(project => project.ProjectId).ToArray(); IReadOnlyList <string> packageSourceNames = uiService.ActivePackageSourceMoniker.PackageSourceNames; return(await projectManagerService.GetUpdateActionsAsync( projectIds, packagesToUpdate, VersionConstraints.None, includePrerelease, uiService.DependencyBehavior, packageSourceNames, token)); }
private async Task ExecuteUpgradeNuGetProjectCommandAsync(object sender, EventArgs e) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (ShouldMEFBeInitialized()) { await InitializeMEFAsync(); } var project = VsMonitorSelection.GetActiveProject(); if (!await NuGetProjectUpgradeUtility.IsNuGetProjectUpgradeableAsync(null, project)) { MessageHelper.ShowWarningMessage(Resources.ProjectMigrateErrorMessage, Resources.ErrorDialogBoxTitle); return; } string uniqueName = await project.GetCustomUniqueNameAsync(); // Close NuGet Package Manager if it is open for this project IVsWindowFrame windowFrame = await FindExistingWindowFrameAsync(project); windowFrame?.CloseFrame((uint)__FRAMECLOSE.FRAMECLOSE_SaveIfDirty); IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); NuGetProject nuGetProject = await SolutionManager.Value.GetNuGetProjectAsync(uniqueName); IProjectContextInfo projectContextInfo = await ProjectContextInfo.CreateAsync(nuGetProject, CancellationToken.None); using (INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, projectContextInfo)) { await uiController.UIContext.UIActionEngine.UpgradeNuGetProjectAsync(uiController, projectContextInfo); uiController.UIContext.UserSettingsManager.PersistSettings(); } }
/// <summary> /// Perform the multi-package update action. /// </summary> /// <remarks>This needs to be called from a background thread. It may hang on the UI thread.</remarks> public async Task PerformUpdateAsync( INuGetUI uiService, List <PackageIdentity> packagesToUpdate, DependencyObject windowOwner, CancellationToken token) { var stopWatch = new Stopwatch(); stopWatch.Start(); await PerformActionImplAsync( uiService, () => { return(ResolveActionsForUpdate( uiService, packagesToUpdate, token)); }, async (actions) => { foreach (var projectActions in actions.GroupBy(action => action.Project)) { await _packageManager.ExecuteNuGetProjectActionsAsync( projectActions.Key, projectActions.Select(action => action.Action), uiService.ProgressWindow, token); } }, windowOwner, token); stopWatch.Stop(); uiService.ProgressWindow.Log(ProjectManagement.MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, stopWatch.Elapsed)); }
// Returns false if user doesn't accept license agreements. private async Task <bool> CheckLicenseAcceptanceAsync( INuGetUI uiService, IEnumerable <PreviewResult> results, CancellationToken token) { // find all the packages that might need a license acceptance var licenseCheck = new HashSet <PackageIdentity>(PackageIdentity.Comparer); foreach (var result in results) { foreach (var pkg in result.Added) { licenseCheck.Add(pkg); } foreach (var pkg in result.Updated) { licenseCheck.Add(pkg.New); } } var sources = _sourceProvider.GetRepositories().Where(e => e.PackageSource.IsEnabled); var licenseMetadata = await GetPackageMetadataAsync(sources, licenseCheck, token); TelemetryUtility.StopTimer(); // show license agreement if (licenseMetadata.Any(e => e.RequireLicenseAcceptance)) { var licenseInfoItems = licenseMetadata .Where(p => p.RequireLicenseAcceptance) .Select(e => new PackageLicenseInfo(e.Identity.Id, e.LicenseUrl, e.Authors)); return(uiService.PromptForLicenseAcceptance(licenseInfoItems)); } return(true); }
internal static async Task <string> DoUpgradeAsync( INuGetUIContext context, INuGetUI uiService, NuGetProject nuGetProject, IEnumerable <NuGetProjectUpgradeDependencyItem> upgradeDependencyItems, IEnumerable <PackageIdentity> notFoundPackages, IProgress <ProgressDialogData> progress, CancellationToken token) { var startTime = DateTimeOffset.Now; var packagesCount = 0; var status = NuGetOperationStatus.Succeeded; using (var telemetry = new TelemetryActivity(Guid.Empty)) { try { // 0. Fail if any package was not found if (notFoundPackages.Any()) { status = NuGetOperationStatus.Failed; var notFoundPackageIds = string.Join(",", notFoundPackages.Select(t => t.Id)); uiService.ProjectContext.Log(MessageLevel.Error, string.Format(CultureInfo.CurrentCulture, Resources.Migrator_PackageNotFound, notFoundPackageIds)); return(null); } // 1. Backup files (csproj and packages.config) that will change var solutionManager = context.SolutionManager; var msBuildNuGetProject = (MSBuildNuGetProject)nuGetProject; var msBuildNuGetProjectSystem = msBuildNuGetProject.ProjectSystem; var backupPath = string.Empty; try { backupPath = CreateBackup(msBuildNuGetProject, solutionManager.SolutionDirectory); } catch (Exception ex) { status = NuGetOperationStatus.Failed; // log error message uiService.ShowError(ex); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrader_BackupFailed)); return(null); } // 2. Uninstall all packages currently in packages.config var progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Uninstalling); progress.Report(progressData); // Don't uninstall packages we couldn't find - that will just fail var actions = upgradeDependencyItems.Select(d => d.Package) .Where(p => !notFoundPackages.Contains(p)) .Select(t => NuGetProjectAction.CreateUninstallProjectAction(t, nuGetProject)); try { await context.PackageManager.ExecuteNuGetProjectActionsAsync(nuGetProject, actions, uiService.ProjectContext, NullSourceCacheContext.Instance, CancellationToken.None); } catch (Exception ex) { status = NuGetOperationStatus.Failed; // log error message uiService.ShowError(ex); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_UninstallFailed)); return(null); } // Reload the project, and get a reference to the reloaded project var uniqueName = msBuildNuGetProjectSystem.ProjectUniqueName; await msBuildNuGetProject.SaveAsync(token); nuGetProject = await solutionManager.GetNuGetProjectAsync(uniqueName); nuGetProject = await solutionManager.UpgradeProjectToPackageReferenceAsync(nuGetProject); // Ensure we use the updated project for installing, and don't display preview or license acceptance windows. context.Projects = new[] { nuGetProject }; var nuGetUI = (NuGetUI)uiService; nuGetUI.Projects = new[] { nuGetProject }; nuGetUI.DisplayPreviewWindow = false; // 4. Install the requested packages var ideExecutionContext = uiService.ProjectContext.ExecutionContext as IDEExecutionContext; if (ideExecutionContext != null) { await ideExecutionContext.SaveExpandedNodeStates(solutionManager); } progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Installing); progress.Report(progressData); var activeSources = new List <SourceRepository>(); PackageSourceMoniker .PopulateList(context.SourceProvider) .ForEach(s => activeSources.AddRange(s.SourceRepositories)); var packagesToInstall = GetPackagesToInstall(upgradeDependencyItems).ToList(); packagesCount = packagesToInstall.Count; // create low level NuGet actions based on number of packages being installed var lowLevelActions = new List <NuGetProjectAction>(); foreach (var packageIdentity in packagesToInstall) { lowLevelActions.Add(NuGetProjectAction.CreateInstallProjectAction(packageIdentity, activeSources.FirstOrDefault(), nuGetProject)); } try { var buildIntegratedProject = nuGetProject as BuildIntegratedNuGetProject; await context.PackageManager.ExecuteBuildIntegratedProjectActionsAsync( buildIntegratedProject, lowLevelActions, uiService.ProjectContext, token); if (ideExecutionContext != null) { await ideExecutionContext.CollapseAllNodes(solutionManager); } return(backupPath); } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_InstallFailed, backupPath)); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_RevertSteps, "https://aka.ms/nugetupgraderevertv1")); return(null); } } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); return(null); } finally { telemetry.TelemetryEvent = VSTelemetryServiceUtility.GetUpgradeTelemetryEvent( uiService.Projects, status, packagesCount); } } }
private async Task PerformActionImplAsync( IServiceBroker serviceBroker, INuGetProjectManagerService projectManagerService, INuGetUI uiService, ResolveActionsAsync resolveActionsAsync, NuGetOperationType operationType, UserAction userAction, CancellationToken cancellationToken) { var status = NuGetOperationStatus.Succeeded; var startTime = DateTimeOffset.Now; var packageCount = 0; var continueAfterPreview = true; var acceptedLicense = true; List <string> removedPackages = null; var existingPackages = new HashSet <Tuple <string, string> >(); List <Tuple <string, string> > addedPackages = null; List <Tuple <string, string> > updatedPackagesOld = null; List <Tuple <string, string> > updatedPackagesNew = null; // Enable granular level telemetry events for nuget ui operation uiService.ProjectContext.OperationId = Guid.NewGuid(); Stopwatch packageEnumerationTime = new Stopwatch(); packageEnumerationTime.Start(); try { // collect the install state of the existing packages foreach (IProjectContextInfo project in uiService.Projects) { IEnumerable <IPackageReferenceContextInfo> installedPackages = await project.GetInstalledPackagesAsync( uiService.UIContext.ServiceBroker, cancellationToken); foreach (IPackageReferenceContextInfo package in installedPackages) { Tuple <string, string> packageInfo = new Tuple <string, string>( package.Identity.Id, (package.Identity.Version == null ? "" : package.Identity.Version.ToNormalizedString())); if (!existingPackages.Contains(packageInfo)) { existingPackages.Add(packageInfo); } } } } catch (Exception) { // don't teardown the process if we have a telemetry failure } packageEnumerationTime.Stop(); await _lockService.ExecuteNuGetOperationAsync(async() => { try { uiService.BeginOperation(); using (INuGetProjectUpgraderService projectUpgrader = await serviceBroker.GetProxyAsync <INuGetProjectUpgraderService>( NuGetServices.ProjectUpgraderService, cancellationToken)) { bool isAcceptedFormat = await CheckPackageManagementFormatAsync(projectUpgrader, uiService, cancellationToken); if (!isAcceptedFormat) { return; } } TelemetryServiceUtility.StartOrResumeTimer(); IReadOnlyList <ProjectAction> actions = await resolveActionsAsync(projectManagerService); IReadOnlyList <PreviewResult> results = await GetPreviewResultsAsync(projectManagerService, actions, cancellationToken); if (operationType == NuGetOperationType.Uninstall) { // removed packages don't have version info removedPackages = results.SelectMany(result => result.Deleted) .Select(package => package.Id) .Distinct() .ToList(); packageCount = removedPackages.Count; } else { // log rich info about added packages addedPackages = results.SelectMany(result => result.Added) .Select(package => new Tuple <string, string>(package.Id, (package.Version == null ? "" : package.Version.ToNormalizedString()))) .Distinct() .ToList(); var addCount = addedPackages.Count; //updated packages can have an old and a new id. updatedPackagesOld = results.SelectMany(result => result.Updated) .Select(package => new Tuple <string, string>(package.Old.Id, (package.Old.Version == null ? "" : package.Old.Version.ToNormalizedString()))) .Distinct() .ToList(); updatedPackagesNew = results.SelectMany(result => result.Updated) .Select(package => new Tuple <string, string>(package.New.Id, (package.New.Version == null ? "" : package.New.Version.ToNormalizedString()))) .Distinct() .ToList(); var updateCount = updatedPackagesNew.Count; // update packages count packageCount = addCount + updateCount; if (updateCount > 0) { // set operation type to update when there are packages being updated operationType = NuGetOperationType.Update; } } TelemetryServiceUtility.StopTimer(); // Show the preview window. if (uiService.DisplayPreviewWindow) { bool shouldContinue = uiService.PromptForPreviewAcceptance(results); if (!shouldContinue) { continueAfterPreview = false; return; } } TelemetryServiceUtility.StartOrResumeTimer(); // Show the license acceptance window. bool accepted = await CheckLicenseAcceptanceAsync(uiService, results, cancellationToken); TelemetryServiceUtility.StartOrResumeTimer(); if (!accepted) { acceptedLicense = false; return; } // Warn about the fact that the "dotnet" TFM is deprecated. if (uiService.DisplayDeprecatedFrameworkWindow) { bool shouldContinue = await ShouldContinueDueToDotnetDeprecationAsync(projectManagerService, uiService, cancellationToken); TelemetryServiceUtility.StartOrResumeTimer(); if (!shouldContinue) { return; } } if (!cancellationToken.IsCancellationRequested) { await projectManagerService.ExecuteActionsAsync( actions, cancellationToken); string[] projectIds = actions .Select(action => action.ProjectId) .Distinct() .ToArray(); uiService.UIContext.RaiseProjectActionsExecuted(projectIds); } else { status = NuGetOperationStatus.Cancelled; } } catch (System.Net.Http.HttpRequestException ex) { status = NuGetOperationStatus.Failed; if (ex.InnerException != null) { uiService.ShowError(ex.InnerException); } else { uiService.ShowError(ex); } } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); } finally { TelemetryServiceUtility.StopTimer(); var duration = TelemetryServiceUtility.GetTimerElapsedTime(); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, duration)); uiService.EndOperation(); // don't show "Succeeded" if we actually cancelled... if ((!continueAfterPreview) || (!acceptedLicense)) { if (status == NuGetOperationStatus.Succeeded) { status = NuGetOperationStatus.Cancelled; } } var plc = new PackageLoadContext(isSolution: false, uiService.UIContext); IReadOnlyCollection <string> frameworks = await plc.GetSupportedFrameworksAsync(); string[] projectIds = (await ProjectUtility.GetSortedProjectIdsAsync( uiService.UIContext.ServiceBroker, uiService.Projects, cancellationToken)).ToArray(); var packageSourceMapping = PackageSourceMapping.GetPackageSourceMapping(uiService.Settings); bool isPackageSourceMappingEnabled = packageSourceMapping?.IsEnabled ?? false; var actionTelemetryEvent = new VSActionsTelemetryEvent( uiService.ProjectContext.OperationId.ToString(), projectIds, operationType, OperationSource.UI, startTime, status, packageCount, DateTimeOffset.Now, duration.TotalSeconds, isPackageSourceMappingEnabled: isPackageSourceMappingEnabled); var nuGetUI = uiService as NuGetUI; AddUiActionEngineTelemetryProperties( actionTelemetryEvent, continueAfterPreview, acceptedLicense, userAction, nuGetUI?.SelectedIndex, nuGetUI?.RecommendedCount, nuGetUI?.RecommendPackages, nuGetUI?.RecommenderVersion, nuGetUI?.TopLevelVulnerablePackagesCount ?? 0, nuGetUI?.TopLevelVulnerablePackagesMaxSeverities?.ToList() ?? new List <int>(), existingPackages, addedPackages, removedPackages, updatedPackagesOld, updatedPackagesNew, frameworks); actionTelemetryEvent["InstalledPackageEnumerationTimeInMilliseconds"] = packageEnumerationTime.ElapsedMilliseconds; TelemetryActivity.EmitTelemetryEvent(actionTelemetryEvent); } }, cancellationToken); }
public async Task UpgradeNuGetProjectAsync(INuGetUI uiService, IProjectContextInfo project) { Assumes.NotNull(uiService); Assumes.NotNull(project); INuGetUIContext context = uiService.UIContext; // Restore the project before proceeding string solutionDirectory = await context.SolutionManagerService.GetSolutionDirectoryAsync(CancellationToken.None); await context.PackageRestoreManager.RestoreMissingPackagesInSolutionAsync( solutionDirectory, uiService.ProjectContext, new LoggerAdapter(uiService.ProjectContext), CancellationToken.None); IServiceBroker serviceBroker = context.ServiceBroker; NuGetProjectUpgradeWindowModel upgradeInformationWindowModel; using (INuGetProjectManagerService projectManager = await serviceBroker.GetProxyAsync <INuGetProjectManagerService>( NuGetServices.ProjectManagerService, CancellationToken.None)) { Assumes.NotNull(projectManager); IReadOnlyCollection <PackageDependencyInfo> packagesDependencyInfo = await projectManager.GetInstalledPackagesDependencyInfoAsync( project.ProjectId, includeUnresolved : true, CancellationToken.None); upgradeInformationWindowModel = await NuGetProjectUpgradeWindowModel.CreateAsync( serviceBroker, project, packagesDependencyInfo.ToList(), CancellationToken.None); } var result = uiService.ShowNuGetUpgradeWindow(upgradeInformationWindowModel); if (!result) { // raise upgrade telemetry event with Cancelled status var packagesCount = upgradeInformationWindowModel.UpgradeDependencyItems.Count; var upgradeTelemetryEvent = new UpgradeInformationTelemetryEvent(); IEnumerable <string> projectIds = await ProjectUtility.GetSortedProjectIdsAsync( uiService.UIContext.ServiceBroker, uiService.Projects, CancellationToken.None); upgradeTelemetryEvent.SetResult( projectIds, NuGetOperationStatus.Cancelled, packagesCount); TelemetryActivity.EmitTelemetryEvent(upgradeTelemetryEvent); return; } var progressDialogData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage); string projectName = await project.GetUniqueNameOrNameAsync( uiService.UIContext.ServiceBroker, CancellationToken.None); string backupPath; var windowTitle = string.Format( CultureInfo.CurrentCulture, Resources.WindowTitle_NuGetMigrator, projectName); using (IModalProgressDialogSession progressDialogSession = await context.StartModalProgressDialogAsync(windowTitle, progressDialogData, uiService)) { backupPath = await PackagesConfigToPackageReferenceMigrator.DoUpgradeAsync( context, uiService, project, upgradeInformationWindowModel.UpgradeDependencyItems, upgradeInformationWindowModel.NotFoundPackages, progressDialogSession.Progress, progressDialogSession.UserCancellationToken); } if (!string.IsNullOrEmpty(backupPath)) { string htmlLogFile = GenerateUpgradeReport(projectName, backupPath, upgradeInformationWindowModel); Process process = null; try { process = Process.Start(htmlLogFile); } catch { } } }
public PackageManagerModel(INuGetUI uiController, INuGetUIContext context) { _context = context; _uiController = uiController; }
public IModalProgressDialogSession StartModalProgressDialog(string caption, ProgressDialogData initialData, INuGetUI uiService) { var waitForDialogFactory = (IVsThreadedWaitDialogFactory)Package.GetGlobalService(typeof(SVsThreadedWaitDialogFactory)); var progressData = new ThreadedWaitDialogProgressData( initialData.WaitMessage, initialData.ProgressText, null, initialData.IsCancelable, initialData.CurrentStep, initialData.TotalSteps); var session = waitForDialogFactory.StartWaitDialog(caption, progressData); return(new VisualStudioProgressDialogSession(session)); }
public async Task <IModalProgressDialogSession> StartModalProgressDialogAsync(string caption, ProgressDialogData initialData, INuGetUI uiService) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var waitForDialogFactory = (IVsThreadedWaitDialogFactory)Package.GetGlobalService(typeof(SVsThreadedWaitDialogFactory)); var progressData = new ThreadedWaitDialogProgressData( initialData.WaitMessage, initialData.ProgressText, null, initialData.IsCancelable, initialData.CurrentStep, initialData.TotalSteps); var session = waitForDialogFactory.StartWaitDialog(caption, progressData); return(new VisualStudioProgressDialogSession(session)); }
/// <summary> /// Perform a user action. /// </summary> /// <remarks>This needs to be called from a background thread. It may hang on the UI thread.</remarks> public async Task PerformAction(INuGetUI uiService, UserAction userAction, DependencyObject windowOwner, CancellationToken token) { try { uiService.ShowProgressDialog(windowOwner); var projects = uiService.Projects; // TODO: should stable packages allow prerelease dependencies if include prerelease was checked? // Allow prerelease packages only if the target is prerelease bool includePrelease = userAction.PackageIdentity.Version.IsPrerelease || userAction.Action == NuGetProjectActionType.Uninstall; bool includeUnlisted = userAction.Action == NuGetProjectActionType.Uninstall; ResolutionContext resolutionContext = new ResolutionContext(uiService.DependencyBehavior, includePrelease, includeUnlisted); IEnumerable<Tuple<NuGetProject, NuGetProjectAction>> actions = await GetActions( uiService, projects, userAction, removeDependencies: uiService.RemoveDependencies, forceRemove: uiService.ForceRemove, resolutionContext: resolutionContext, projectContext: uiService.ProgressWindow, token: token); IEnumerable<PreviewResult> results = GetPreviewResults(actions); // preview window if (uiService.DisplayPreviewWindow) { var shouldContinue = false; shouldContinue = uiService.PromptForPreviewAcceptance(results); if (!shouldContinue) { return; } } bool accepted = await CheckLicenseAcceptance(uiService, results, token); if (!accepted) { return; } if (!token.IsCancellationRequested) { // execute the actions await ExecuteActions(actions, uiService.ProgressWindow, userAction, token); // update uiService.RefreshPackageStatus(); } } catch (Exception ex) { uiService.ShowError(ex); } finally { uiService.CloseProgressDialog(); } }
/// <summary> /// The internal implementation to perform user action. /// </summary> /// <param name="resolveActionsAsync">A function that returns a task that resolves the user /// action into project actions.</param> /// <param name="executeActionsAsync">A function that returns a task that executes /// the project actions.</param> private async Task PerformActionImplAsync( INuGetUI uiService, Func <Task <IReadOnlyList <ResolvedAction> > > resolveActionsAsync, Func <IReadOnlyList <ResolvedAction>, Task> executeActionsAsync, DependencyObject windowOwner, CancellationToken token) { try { uiService.ShowProgressDialog(windowOwner); var actions = await resolveActionsAsync(); var results = GetPreviewResults(actions); // Show the preview window. if (uiService.DisplayPreviewWindow) { var shouldContinue = uiService.PromptForPreviewAcceptance(results); if (!shouldContinue) { return; } } // Show the license acceptance window. var accepted = await CheckLicenseAcceptanceAsync(uiService, results, token); if (!accepted) { return; } // Warn about the fact that the "dotnet" TFM is deprecated. if (uiService.DisplayDeprecatedFrameworkWindow) { var shouldContinue = ShouldContinueDueToDotnetDeprecation(uiService, actions, token); if (!shouldContinue) { return; } } if (!token.IsCancellationRequested) { // execute the actions await executeActionsAsync(actions); // fires ActionsExecuted event to update the UI uiService.OnActionsExecuted(actions); } } catch (System.Net.Http.HttpRequestException ex) { if (ex.InnerException != null) { uiService.ShowError(ex.InnerException); } else { uiService.ShowError(ex); } } catch (Exception ex) { uiService.ShowError(ex); } finally { uiService.CloseProgressDialog(); } }
/// <summary> /// The internal implementation to perform user action. /// </summary> /// <param name="resolveActionsAsync">A function that returns a task that resolves the user /// action into project actions.</param> /// <param name="executeActionsAsync">A function that returns a task that executes /// the project actions.</param> private async Task PerformActionImplAsync( INuGetUI uiService, Func <SourceCacheContext, Task <IReadOnlyList <ResolvedAction> > > resolveActionsAsync, Func <IReadOnlyList <ResolvedAction>, SourceCacheContext, Task> executeActionsAsync, NuGetOperationType operationType, UserAction userAction, CancellationToken token) { var status = NuGetOperationStatus.Succeeded; var startTime = DateTimeOffset.Now; var packageCount = 0; bool continueAfterPreview = true; bool acceptedLicense = true; List <string> removedPackages = null; HashSet <Tuple <string, string> > existingPackages = new HashSet <Tuple <string, string> >(); List <Tuple <string, string> > addedPackages = null; List <Tuple <string, string> > updatedPackagesOld = null; List <Tuple <string, string> > updatedPackagesNew = null; // Enable granular level telemetry events for nuget ui operation uiService.ProjectContext.OperationId = Guid.NewGuid(); Stopwatch packageEnumerationTime = new Stopwatch(); packageEnumerationTime.Start(); try { // collect the install state of the existing packages foreach (var project in uiService.Projects) { var result = await project.GetInstalledPackagesAsync(token); foreach (var package in result) { Tuple <string, string> packageInfo = new Tuple <string, string>(package.PackageIdentity.Id, (package.PackageIdentity.Version == null ? "" : package.PackageIdentity.Version.ToNormalizedString())); if (!existingPackages.Contains(packageInfo)) { existingPackages.Add(packageInfo); } } } } catch (Exception) { // don't teardown the process if we have a telemetry failure } packageEnumerationTime.Stop(); await _lockService.ExecuteNuGetOperationAsync(async() => { try { uiService.BeginOperation(); var acceptedFormat = await CheckPackageManagementFormat(uiService, token); if (!acceptedFormat) { return; } TelemetryServiceUtility.StartOrResumeTimer(); using (var sourceCacheContext = new SourceCacheContext()) { var actions = await resolveActionsAsync(sourceCacheContext); var results = GetPreviewResults(actions); if (operationType == NuGetOperationType.Uninstall) { // removed packages don't have version info removedPackages = results.SelectMany(result => result.Deleted) .Select(package => package.Id) .Distinct() .ToList(); packageCount = removedPackages.Count; } else { // log rich info about added packages addedPackages = results.SelectMany(result => result.Added) .Select(package => new Tuple <string, string>(package.Id, (package.Version == null ? "" : package.Version.ToNormalizedString()))) .Distinct() .ToList(); var addCount = addedPackages.Count; //updated packages can have an old and a new id. updatedPackagesOld = results.SelectMany(result => result.Updated) .Select(package => new Tuple <string, string>(package.Old.Id, (package.Old.Version == null ? "" : package.Old.Version.ToNormalizedString()))) .Distinct() .ToList(); updatedPackagesNew = results.SelectMany(result => result.Updated) .Select(package => new Tuple <string, string>(package.New.Id, (package.New.Version == null ? "" : package.New.Version.ToNormalizedString()))) .Distinct() .ToList(); var updateCount = updatedPackagesNew.Count; // update packages count packageCount = addCount + updateCount; if (updateCount > 0) { // set operation type to update when there are packages being updated operationType = NuGetOperationType.Update; } } TelemetryServiceUtility.StopTimer(); // Show the preview window. if (uiService.DisplayPreviewWindow) { var shouldContinue = uiService.PromptForPreviewAcceptance(results); if (!shouldContinue) { continueAfterPreview = false; return; } } TelemetryServiceUtility.StartOrResumeTimer(); // Show the license acceptance window. var accepted = await CheckLicenseAcceptanceAsync(uiService, results, token); TelemetryServiceUtility.StartOrResumeTimer(); if (!accepted) { acceptedLicense = false; return; } // Warn about the fact that the "dotnet" TFM is deprecated. if (uiService.DisplayDeprecatedFrameworkWindow) { var shouldContinue = ShouldContinueDueToDotnetDeprecation(uiService, actions, token); TelemetryServiceUtility.StartOrResumeTimer(); if (!shouldContinue) { return; } } if (!token.IsCancellationRequested) { // execute the actions await executeActionsAsync(actions, sourceCacheContext); // fires ActionsExecuted event to update the UI uiService.OnActionsExecuted(actions); } else { status = NuGetOperationStatus.Cancelled; } } } catch (System.Net.Http.HttpRequestException ex) { status = NuGetOperationStatus.Failed; if (ex.InnerException != null) { uiService.ShowError(ex.InnerException); } else { uiService.ShowError(ex); } } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); } finally { TelemetryServiceUtility.StopTimer(); var duration = TelemetryServiceUtility.GetTimerElapsedTime(); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, duration)); uiService.EndOperation(); // don't show "Succeeded" if we actually cancelled... if ((!continueAfterPreview) || (!acceptedLicense)) { if (status == NuGetOperationStatus.Succeeded) { status = NuGetOperationStatus.Cancelled; } } var actionTelemetryEvent = VSTelemetryServiceUtility.GetActionTelemetryEvent( uiService.ProjectContext.OperationId.ToString(), uiService.Projects, operationType, OperationSource.UI, startTime, status, packageCount, duration.TotalSeconds); AddUiActionEngineTelemetryProperties(actionTelemetryEvent, continueAfterPreview, acceptedLicense, userAction, existingPackages, addedPackages, removedPackages, updatedPackagesOld, updatedPackagesNew); actionTelemetryEvent["InstalledPackageEnumerationTimeInMilliseconds"] = packageEnumerationTime.ElapsedMilliseconds; TelemetryActivity.EmitTelemetryEvent(actionTelemetryEvent); } }, token); }
/// <summary> /// The internal implementation to perform user action. /// </summary> /// <param name="resolveActionsAsync">A function that returns a task that resolves the user /// action into project actions.</param> /// <param name="executeActionsAsync">A function that returns a task that executes /// the project actions.</param> private async Task PerformActionImplAsync( INuGetUI uiService, Func <Task <IReadOnlyList <ResolvedAction> > > resolveActionsAsync, Func <IReadOnlyList <ResolvedAction>, Task> executeActionsAsync, NuGetOperationType operationType, CancellationToken token) { var status = NuGetOperationStatus.Succeeded; var startTime = DateTimeOffset.Now; var packageCount = 0; var operationId = Guid.NewGuid().ToString(); // Enable granular level telemetry events for nuget ui operation var telemetryService = new TelemetryServiceHelper(); uiService.ProjectContext.TelemetryService = telemetryService; await _lockService.ExecuteNuGetOperationAsync(async() => { try { uiService.BeginOperation(); var acceptedFormat = await CheckPackageManagementFormat(uiService, token); if (!acceptedFormat) { return; } TelemetryUtility.StartorResumeTimer(); var actions = await resolveActionsAsync(); var results = GetPreviewResults(actions); if (operationType == NuGetOperationType.Uninstall) { packageCount = results.SelectMany(result => result.Deleted). Select(package => package.Id).Distinct().Count(); } else { var addCount = results.SelectMany(result => result.Added). Select(package => package.Id).Distinct().Count(); var updateCount = results.SelectMany(result => result.Updated). Select(result => result.New.Id).Distinct().Count(); // update packages count packageCount = addCount + updateCount; if (updateCount > 0) { // set operation type to update when there are packages being updated operationType = NuGetOperationType.Update; } } TelemetryUtility.StopTimer(); // Show the preview window. if (uiService.DisplayPreviewWindow) { var shouldContinue = uiService.PromptForPreviewAcceptance(results); if (!shouldContinue) { return; } } TelemetryUtility.StartorResumeTimer(); // Show the license acceptance window. var accepted = await CheckLicenseAcceptanceAsync(uiService, results, token); TelemetryUtility.StartorResumeTimer(); if (!accepted) { return; } // Warn about the fact that the "dotnet" TFM is deprecated. if (uiService.DisplayDeprecatedFrameworkWindow) { var shouldContinue = ShouldContinueDueToDotnetDeprecation(uiService, actions, token); TelemetryUtility.StartorResumeTimer(); if (!shouldContinue) { return; } } if (!token.IsCancellationRequested) { // execute the actions await executeActionsAsync(actions); // fires ActionsExecuted event to update the UI uiService.OnActionsExecuted(actions); } } catch (System.Net.Http.HttpRequestException ex) { status = NuGetOperationStatus.Failed; if (ex.InnerException != null) { uiService.ShowError(ex.InnerException); } else { uiService.ShowError(ex); } } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); } finally { TelemetryUtility.StopTimer(); var duration = TelemetryUtility.GetTimerElapsedTime(); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Operation_TotalTime, duration)); uiService.EndOperation(); var actionTelemetryEvent = TelemetryUtility.GetActionTelemetryEvent( uiService.Projects, operationType, OperationSource.UI, startTime, status, packageCount, duration.TotalSeconds); ActionsTelemetryService.Instance.EmitActionEvent(actionTelemetryEvent, telemetryService.TelemetryEvents); } }, token); }
private async ValueTask <IVsWindowFrame> CreateToolWindowAsync(WorkspaceVisualNodeBase workspaceVisualNodeBase, IVsHierarchy hier, uint itemId) { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); if (!Guid.TryParse(IProjectContextInfoUtility.GetProjectGuidStringFromVslsQueryString(workspaceVisualNodeBase.VSSelectionMoniker), out Guid projectGuid)) { throw new InvalidOperationException(); } IVsWindowFrame windowFrame = null; var uiShell = await _asyncServiceProvider.GetServiceAsync <SVsUIShell, IVsUIShell>(); Assumes.Present(uiShell); uint toolWindowId; bool foundToolWindowId = _projectGuidToToolWindowId.TryGetValue(projectGuid.ToString(), out toolWindowId); const uint FTW_none = 0; if (foundToolWindowId) { ErrorHandler.ThrowOnFailure( uiShell.FindToolWindowEx( FTW_none, //grfFTW - badly-documented enum value. typeof(PackageManagerToolWindowPane).GUID, // rguidPersistenceSlot toolWindowId, // dwToolWindowId out windowFrame)); if (windowFrame != null) { ((IVsWindowFrame2)windowFrame).ActivateOwnerDockedWindow(); } else { _projectGuidToToolWindowId.Remove(projectGuid.ToString()); } } if (windowFrame == null) { IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); IProjectContextInfo projectContextInfo = await IProjectContextInfoUtility.CreateAsync(serviceBroker, projectGuid.ToString(), CancellationToken.None); INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, projectContextInfo); // This model takes ownership of --- and Dispose() responsibility for --- the INuGetUI instance. var model = new PackageManagerModel(uiController, isSolution: false, editorFactoryGuid: GuidList.NuGetEditorType); var control = await PackageManagerControl.CreateAsync(model, OutputConsoleLogger.Value); var caption = string.Format(CultureInfo.CurrentCulture, Resx.Label_NuGetWindowCaption, Path.GetFileNameWithoutExtension(workspaceVisualNodeBase.NodeMoniker)); int[] pfDefaultPosition = null; var windowPane = new PackageManagerToolWindowPane(control, projectGuid.ToString()); ErrorHandler.ThrowOnFailure( uiShell.CreateToolWindow( (uint)__VSCREATETOOLWIN.CTW_fInitNew, ++_maxToolWindowId, // dwToolWindowId windowPane, // ToolWindowPane Guid.Empty, // rclsidTool = GUID_NULL typeof(PackageManagerToolWindowPane).GUID, // rguidPersistenceSlot Guid.Empty, // reserved - do not use - GUID_NULL null, // IServiceProvider caption, pfDefaultPosition, out windowFrame)); _projectGuidToToolWindowId.Add(projectGuid.ToString(), _maxToolWindowId); windowPane.Closed += WindowPane_Closed; if (windowFrame != null) { WindowFrameHelper.AddF1HelpKeyword(windowFrame, keywordValue: F1KeywordValuePmUI); WindowFrameHelper.DisableWindowAutoReopen(windowFrame); WindowFrameHelper.DockToolWindow(windowFrame); } } return(windowFrame); }
/// <summary> /// Perform a user action. /// </summary> /// <remarks>This needs to be called from a background thread. It may hang on the UI thread.</remarks> public async Task PerformAction(INuGetUI uiService, UserAction userAction, DependencyObject windowOwner, CancellationToken token) { try { uiService.ShowProgressDialog(windowOwner); var projects = uiService.Projects; // TODO: should stable packages allow prerelease dependencies if include prerelease was checked? // Allow prerelease packages only if the target is prerelease bool includePrelease = userAction.PackageIdentity.Version.IsPrerelease || userAction.Action == NuGetProjectActionType.Uninstall; bool includeUnlisted = userAction.Action == NuGetProjectActionType.Uninstall; ResolutionContext resolutionContext = new ResolutionContext(uiService.DependencyBehavior, includePrelease, includeUnlisted); IEnumerable <Tuple <NuGetProject, NuGetProjectAction> > actions = await GetActions( uiService, projects, userAction, removeDependencies : uiService.RemoveDependencies, forceRemove : uiService.ForceRemove, resolutionContext : resolutionContext, projectContext : uiService.ProgressWindow, token : token); IEnumerable <PreviewResult> results = GetPreviewResults(actions); // preview window if (uiService.DisplayPreviewWindow) { var shouldContinue = false; shouldContinue = uiService.PromptForPreviewAcceptance(results); if (!shouldContinue) { return; } } bool accepted = await CheckLicenseAcceptance(uiService, results, token); if (!accepted) { return; } if (!token.IsCancellationRequested) { // execute the actions await ExecuteActions(actions, uiService.ProgressWindow, userAction, token); // update uiService.RefreshPackageStatus(); } } catch (Exception ex) { uiService.ShowError(ex); } finally { uiService.CloseProgressDialog(); } }
/// <summary> /// Return the resolve package actions /// </summary> protected async Task<IEnumerable<Tuple<NuGetProject, NuGetProjectAction>>> GetActions( INuGetUI uiService, IEnumerable<NuGetProject> targets, UserAction userAction, bool removeDependencies, bool forceRemove, ResolutionContext resolutionContext, INuGetProjectContext projectContext, CancellationToken token) { List<Tuple<NuGetProject, NuGetProjectAction>> results = new List<Tuple<NuGetProject, NuGetProjectAction>>(); Debug.Assert(userAction.PackageId != null, "Package id can never be null in a User action"); if (userAction.Action == NuGetProjectActionType.Install) { Debug.Assert(userAction.PackageIdentity != null, "Package identity cannot be null when installing a package"); foreach (var target in targets) { IEnumerable<NuGetProjectAction> actions; actions = await _packageManager.PreviewInstallPackageAsync(target, userAction.PackageIdentity, resolutionContext, projectContext, uiService.ActiveSource, null, token); results.AddRange(actions.Select(a => new Tuple<NuGetProject, NuGetProjectAction>(target, a))); } } else { UninstallationContext uninstallationContext = new UninstallationContext( removeDependencies: removeDependencies, forceRemove: forceRemove); foreach (var target in targets) { IEnumerable<NuGetProjectAction> actions; if (userAction.PackageIdentity != null) { actions = await _packageManager.PreviewUninstallPackageAsync(target, userAction.PackageIdentity, uninstallationContext, projectContext, token); } else { actions = await _packageManager.PreviewUninstallPackageAsync(target, userAction.PackageId, uninstallationContext, projectContext, token); } results.AddRange(actions.Select(a => new Tuple<NuGetProject, NuGetProjectAction>(target, a))); } } return results; }
private async Task <IVsWindowFrame> CreateDocWindowForSolutionAsync() { await NuGetUIThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsWindowFrame windowFrame = null; var solution = await this.GetServiceAsync <IVsSolution>(); var uiShell = await this.GetServiceAsync <SVsUIShell, IVsUIShell>(); var windowFlags = (uint)_VSRDTFLAGS.RDT_DontAddToMRU | (uint)_VSRDTFLAGS.RDT_DontSaveAs; // when VSSolutionManager is already initialized, then use the existing APIs to check pre-conditions. if (!await SolutionManager.Value.IsSolutionAvailableAsync()) { throw new InvalidOperationException(Resources.SolutionIsNotSaved); } IServiceBroker serviceBroker = await ServiceBrokerProvider.Value.GetAsync(); IReadOnlyCollection <IProjectContextInfo> projectContexts; using (INuGetProjectManagerService projectManagerService = await serviceBroker.GetProxyAsync <INuGetProjectManagerService>( NuGetServices.ProjectManagerService)) { Assumes.NotNull(projectManagerService); projectContexts = await projectManagerService.GetProjectsAsync(CancellationToken.None); if (projectContexts.Count == 0) { MessageHelper.ShowWarningMessage(Resources.NoSupportedProjectsInSolution, Resources.ErrorDialogBoxTitle); return(null); } } INuGetUI uiController = await UIFactory.Value.CreateAsync(serviceBroker, projectContexts.ToArray()); var solutionName = (string)_dte.Solution.Properties.Item("Name").Value; // This model takes ownership of --- and Dispose() responsibility for --- the INuGetUI instance. var model = new PackageManagerModel( uiController, isSolution: true, editorFactoryGuid: GuidList.guidNuGetEditorType) { SolutionName = solutionName }; PackageManagerControl control = await PackageManagerControl.CreateAsync(model, OutputConsoleLogger.Value); var windowPane = new PackageManagerWindowPane(control); var guidEditorType = GuidList.guidNuGetEditorType; var guidCommandUI = Guid.Empty; var caption = Resx.Label_SolutionNuGetWindowCaption; var documentName = await SolutionManager.Value.GetSolutionFilePathAsync(); var ppunkDocView = IntPtr.Zero; var ppunkDocData = IntPtr.Zero; var hr = 0; try { ppunkDocView = Marshal.GetIUnknownForObject(windowPane); ppunkDocData = Marshal.GetIUnknownForObject(model); hr = uiShell.CreateDocumentWindow( windowFlags, documentName, (IVsUIHierarchy)solution, (uint)VSConstants.VSITEMID.Root, ppunkDocView, ppunkDocData, ref guidEditorType, null, ref guidCommandUI, null, caption, string.Empty, null, out windowFrame); if (windowFrame != null) { WindowFrameHelper.AddF1HelpKeyword(windowFrame, keywordValue: F1KeywordValuePmUI); WindowFrameHelper.DisableWindowAutoReopen(windowFrame); } } finally { if (ppunkDocView != IntPtr.Zero) { Marshal.Release(ppunkDocData); } if (ppunkDocData != IntPtr.Zero) { Marshal.Release(ppunkDocView); } } ErrorHandler.ThrowOnFailure(hr); return(windowFrame); }
internal static async Task <string> DoUpgradeAsync( INuGetUIContext context, INuGetUI uiService, IProjectContextInfo project, IEnumerable <NuGetProjectUpgradeDependencyItem> upgradeDependencyItems, IEnumerable <PackageIdentity> notFoundPackages, IProgress <ProgressDialogData> progress, CancellationToken token) { var startTime = DateTimeOffset.Now; var packagesCount = 0; var status = NuGetOperationStatus.Succeeded; var upgradeInformationTelemetryEvent = new UpgradeInformationTelemetryEvent(); using (var telemetry = TelemetryActivity.Create(upgradeInformationTelemetryEvent)) { try { // 0. Fail if any package was not found if (notFoundPackages.Any()) { status = NuGetOperationStatus.Failed; var notFoundPackageIds = string.Join(",", notFoundPackages.Select(t => t.Id)); uiService.ProjectContext.Log(MessageLevel.Error, string.Format(CultureInfo.CurrentCulture, Resources.Migrator_PackageNotFound, notFoundPackageIds)); return(null); } IServiceBroker serviceBroker = await BrokeredServicesUtilities.GetRemoteServiceBrokerAsync(); using (INuGetProjectUpgraderService projectUpgrader = await serviceBroker.GetProxyAsync <INuGetProjectUpgraderService>( NuGetServices.ProjectUpgraderService, token)) { Assumes.NotNull(projectUpgrader); string backupPath; // 1. Backup files (csproj and packages.config) that will change try { backupPath = await projectUpgrader.BackupProjectAsync(project.ProjectId, token); } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); uiService.ProjectContext.Log( MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrader_BackupFailed)); return(null); } // 2. Uninstall all packages currently in packages.config var progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Uninstalling); progress.Report(progressData); // Don't uninstall packages we couldn't find - that will just fail PackageIdentity[] packagesToUninstall = upgradeDependencyItems.Select(d => d.Identity) .Where(p => !notFoundPackages.Contains(p)) .ToArray(); try { await projectUpgrader.UninstallPackagesAsync(project.ProjectId, packagesToUninstall, token); } catch (Exception ex) { status = NuGetOperationStatus.Failed; // log error message uiService.ShowError(ex); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_UninstallFailed)); return(null); } // Reload the project, and get a reference to the reloaded project await projectUpgrader.SaveProjectAsync(project.ProjectId, token); IProjectContextInfo upgradedProject = await projectUpgrader.UpgradeProjectToPackageReferenceAsync( project.ProjectId, token); // Ensure we use the updated project for installing, and don't display preview or license acceptance windows. context.Projects = new[] { upgradedProject }; var nuGetUI = (NuGetUI)uiService; nuGetUI.Projects = new[] { upgradedProject }; nuGetUI.DisplayPreviewWindow = false; // 4. Install the requested packages var ideExecutionContext = uiService.ProjectContext.ExecutionContext as IDEExecutionContext; if (ideExecutionContext != null) { await ideExecutionContext.SaveExpandedNodeStates(context.SolutionManager); } progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Installing); progress.Report(progressData); List <PackageIdentity> packagesToInstall = GetPackagesToInstall(upgradeDependencyItems).ToList(); packagesCount = packagesToInstall.Count; try { await projectUpgrader.InstallPackagesAsync( project.ProjectId, packagesToInstall, token); if (ideExecutionContext != null) { await ideExecutionContext.CollapseAllNodes(context.SolutionManager); } return(backupPath); } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_InstallFailed, backupPath)); uiService.ProjectContext.Log(MessageLevel.Info, string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_RevertSteps, "https://aka.ms/nugetupgraderevertv1")); return(null); } } } catch (Exception ex) { status = NuGetOperationStatus.Failed; uiService.ShowError(ex); return(null); } finally { IEnumerable <string> projectIds = await ProjectUtility.GetSortedProjectIdsAsync(uiService.Projects, token); upgradeInformationTelemetryEvent.SetResult(projectIds, status, packagesCount); } } }
private void LogError(Task task, INuGetUI uiService) { var exception = ExceptionUtilities.Unwrap(task.Exception); uiService.ProjectContext.Log(MessageLevel.Error, exception.Message); }
// Returns false if user doesn't accept license agreements. private async Task<bool> CheckLicenseAcceptance( INuGetUI uiService, IEnumerable<PreviewResult> results, CancellationToken token) { // find all the packages that might need a license acceptance HashSet<PackageIdentity> licenseCheck = new HashSet<PackageIdentity>(PackageIdentity.Comparer); foreach (var result in results) { foreach (var pkg in result.Added) { licenseCheck.Add(pkg); } foreach (var pkg in result.Updated) { licenseCheck.Add(pkg.New); } } IEnumerable<UIPackageMetadata> licenseMetadata = await GetPackageMetadata(licenseCheck, token); // show license agreement if (licenseMetadata.Any(e => e.RequireLicenseAcceptance)) { var licenseInfoItems = licenseMetadata .Where(p => p.RequireLicenseAcceptance) .Select(e => new PackageLicenseInfo(e.Identity.Id, e.LicenseUrl, e.Authors)); return uiService.PromptForLicenseAcceptance(licenseInfoItems); } return true; }