Example #1
0
        /// <summary>
        /// Execute the installs/uninstalls
        /// </summary>
        protected async Task ExecuteActionsAsync(IEnumerable <ResolvedAction> actions,
                                                 NuGetUIProjectContext projectContext, UserAction userAction, CancellationToken token)
        {
            var processedDirectInstalls = new HashSet <PackageIdentity>(PackageIdentity.Comparer);

            foreach (var projectActions in actions.GroupBy(e => e.Project))
            {
                var nuGetProjectActions = projectActions.Select(e => e.Action);
                var directInstall       = GetDirectInstall(nuGetProjectActions, userAction, projectContext.CommonOperations);
                if (directInstall != null &&
                    !processedDirectInstalls.Contains(directInstall))
                {
                    NuGetPackageManager.SetDirectInstall(directInstall, projectContext);
                    processedDirectInstalls.Add(directInstall);
                }
                await _packageManager.ExecuteNuGetProjectActionsAsync(projectActions.Key, nuGetProjectActions, projectContext, token);

                NuGetPackageManager.ClearDirectInstall(projectContext);
            }
        }
 public override IEnumerable <IProjectContextInfo> GetSelectedProjects(UserAction action)
 {
     return(_nugetProjects);
 }
Example #3
0
        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;
                        }
                    }

                    PackageLoadContext plc = new PackageLoadContext(sourceRepositories: null, isSolution: false, uiService.UIContext);
                    var frameworks         = (await plc.GetSupportedFrameworksAsync()).ToList();
                    string[] projectIds    = (await ProjectUtility.GetSortedProjectIdsAsync(
                                                  uiService.UIContext.ServiceBroker,
                                                  uiService.Projects,
                                                  cancellationToken)).ToArray();

                    var actionTelemetryEvent = new VSActionsTelemetryEvent(
                        uiService.ProjectContext.OperationId.ToString(),
                        projectIds,
                        operationType,
                        OperationSource.UI,
                        startTime,
                        status,
                        packageCount,
                        DateTimeOffset.Now,
                        duration.TotalSeconds);

                    var nuGetUI = uiService as NuGetUI;
                    AddUiActionEngineTelemetryProperties(
                        actionTelemetryEvent,
                        continueAfterPreview,
                        acceptedLicense,
                        userAction,
                        nuGetUI?.SelectedIndex,
                        nuGetUI?.RecommendedCount,
                        nuGetUI?.RecommendPackages,
                        nuGetUI?.RecommenderVersion,
                        existingPackages,
                        addedPackages,
                        removedPackages,
                        updatedPackagesOld,
                        updatedPackagesNew,
                        frameworks);

                    actionTelemetryEvent["InstalledPackageEnumerationTimeInMilliseconds"] = packageEnumerationTime.ElapsedMilliseconds;

                    TelemetryActivity.EmitTelemetryEvent(actionTelemetryEvent);
                }
            }, cancellationToken);
        }
 /// <summary>
 /// Returns the list of projects that are selected for the given action
 /// </summary>
 public abstract IEnumerable <NuGetProject> GetSelectedProjects(UserAction action);
        private static void AddUiActionEngineTelemetryProperties(
            VSActionsTelemetryEvent actionTelemetryEvent,
            bool continueAfterPreview,
            bool acceptedLicense,
            UserAction userAction,
            List <Tuple <string, string> > addedPackages,
            List <string> removedPackages,
            List <Tuple <string, string> > updatedPackagesOld,
            List <Tuple <string, string> > updatedPackagesNew)
        {
            TelemetryEvent ToTelemetryPackage(Tuple <string, string> package)
            {
                var subEvent = new TelemetryEvent(eventName: null);

                subEvent.AddPiiData("id", package.Item1);
                subEvent["version"] = package.Item2;
                return(subEvent);
            }

            List <TelemetryEvent> ToTelemetryPackageList(List <Tuple <string, string> > packages)
            {
                var list = new List <TelemetryEvent>(packages.Count);

                list.AddRange(packages.Select(ToTelemetryPackage));
                return(list);
            }

            // log possible cancel reasons
            if (!continueAfterPreview)
            {
                actionTelemetryEvent["CancelAfterPreview"] = "True";
            }

            if (!acceptedLicense)
            {
                actionTelemetryEvent["AcceptedLicense"] = "False";
            }

            // log the single top level package the user is installing or removing
            if (userAction != null)
            {
                // userAction.Version can be null for deleted packages.
                actionTelemetryEvent.ComplexData["SelectedPackage"] = ToTelemetryPackage(new Tuple <string, string>(userAction.PackageId, userAction.Version?.ToNormalizedString() ?? string.Empty));
            }

            // other packages can be added, removed, or upgraded as part of bulk upgrade or as part of satisfying package dependencies, so log that also
            if (addedPackages != null && addedPackages.Count > 0)
            {
                var packages = new List <TelemetryEvent>();

                foreach (var package in addedPackages)
                {
                    packages.Add(ToTelemetryPackage(package));
                }

                actionTelemetryEvent.ComplexData["AddedPackages"] = packages;
            }

            if (removedPackages != null && removedPackages.Count > 0)
            {
                var packages = new List <TelemetryPiiProperty>();

                foreach (var package in removedPackages)
                {
                    packages.Add(new TelemetryPiiProperty(package));
                }

                actionTelemetryEvent.ComplexData["RemovedPackages"] = packages;
            }

            // two collections for updated packages: pre and post upgrade
            if (updatedPackagesNew != null && updatedPackagesNew.Count > 0)
            {
                actionTelemetryEvent.ComplexData["UpdatedPackagesNew"] = ToTelemetryPackageList(updatedPackagesNew);
            }

            if (updatedPackagesOld != null && updatedPackagesOld.Count > 0)
            {
                actionTelemetryEvent.ComplexData["UpdatedPackagesOld"] = ToTelemetryPackageList(updatedPackagesOld);
            }
        }
Example #6
0
 public override IEnumerable <NuGetProject> GetSelectedProjects(UserAction action)
 {
     return(_nugetProjects);
 }
        /// <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;
            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();

            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, addedPackages, removedPackages, updatedPackagesOld, updatedPackagesNew);

                    TelemetryActivity.EmitTelemetryEvent(actionTelemetryEvent);
                }
            }, token);
        }
        /// <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 PackageIdentity GetDirectInstall(IEnumerable<NuGetProjectAction> nuGetProjectActions,
            UserAction userAction,
            ICommonOperations commonOperations)
        {
            if (commonOperations != null && userAction != null && userAction.Action == NuGetProjectActionType.Install && nuGetProjectActions.Any())
            {
                PackageIdentity directInstall = null;
                if(userAction.PackageIdentity != null)
                {
                    directInstall = userAction.PackageIdentity;
                }
                else
                {
                    var identitiesWithSameId = nuGetProjectActions.Where(n => n.PackageIdentity.Id.Equals(userAction)).ToList();
                    if(identitiesWithSameId.Count == 1)
                    {
                        directInstall = identitiesWithSameId[0].PackageIdentity;
                    }
                    // If there multiple actions with the same package id as the user action, just ignore
                }

                if (directInstall != null)
                {
                    return directInstall;
                }
            }

            return null;
        }
 /// <summary>
 /// Execute the installs/uninstalls
 /// </summary>
 /// <param name="actions"></param>
 /// <param name="projectContext"></param>
 /// <param name="token"></param>
 /// <returns></returns>
 protected async Task ExecuteActions(IEnumerable<Tuple<NuGetProject, NuGetProjectAction>> actions,
     NuGetUIProjectContext projectContext, UserAction userAction, CancellationToken token)
 {
     HashSet<PackageIdentity> processedDirectInstalls = new HashSet<PackageIdentity>(PackageIdentity.Comparer);
     foreach (var projectActions in actions.GroupBy(e => e.Item1))
     {
         var nuGetProjectActions = projectActions.Select(e => e.Item2);
         var directInstall = GetDirectInstall(nuGetProjectActions, userAction, projectContext.CommonOperations);
         if (directInstall != null && !processedDirectInstalls.Contains(directInstall))
         {
             NuGetPackageManager.SetDirectInstall(directInstall, projectContext);
             processedDirectInstalls.Add(directInstall);
         }
         await _packageManager.ExecuteNuGetProjectActionsAsync(projectActions.Key, nuGetProjectActions, projectContext, token);
         NuGetPackageManager.ClearDirectInstall(projectContext);
     }
 }