Example #1
0
        private void RegisterProject(IReloadableProject project)
        {
            uint filechangeCookie;

            lock (_registeredProjects)
            {
                _registeredProjects.TryGetValue(project, out filechangeCookie);
            }

            System.Diagnostics.Debug.Assert(filechangeCookie == VSConstants.VSCOOKIE_NIL);
            if (filechangeCookie == VSConstants.VSCOOKIE_NIL)
            {
                IVsFileChangeEx fileChangeService = _serviceProvider.GetService <IVsFileChangeEx, SVsFileChangeEx>();
                if (fileChangeService != null)
                {
                    int hr = fileChangeService.AdviseFileChange(project.ProjectFile, (uint)(_VSFILECHANGEFLAGS.VSFILECHG_Time | _VSFILECHANGEFLAGS.VSFILECHG_Size), this, out filechangeCookie);
                    System.Diagnostics.Debug.Assert(ErrorHandler.Succeeded(hr) && filechangeCookie != VSConstants.VSCOOKIE_NIL);
                    if (ErrorHandler.Succeeded(hr) && filechangeCookie != VSConstants.VSCOOKIE_NIL)
                    {
                        lock (_registeredProjects)
                        {
                            _registeredProjects.Add(project, filechangeCookie);
                        }
                    }
                    else
                    {
                        throw new COMException(string.Format(VSResources.FailedToWatchProject, project.ProjectFile), hr);
                    }
                }
            }
        }
Example #2
0
        private void UnregisterProject(IReloadableProject project)
        {
            uint filechangeCookie;

            lock (_registeredProjects)
            {
                _registeredProjects.TryGetValue(project, out filechangeCookie);
            }

            if (filechangeCookie != VSConstants.VSCOOKIE_NIL)
            {
                // Remove watch
                IVsFileChangeEx fileChangeService = _serviceProvider.GetService <IVsFileChangeEx, SVsFileChangeEx>();
                if (fileChangeService != null)
                {
                    int hr = fileChangeService.UnadviseFileChange(filechangeCookie);
                    System.Diagnostics.Debug.Assert(ErrorHandler.Succeeded(hr));
                }

                // Always remove the watcher from our list
                lock (_registeredProjects)
                {
                    _registeredProjects.Remove(project);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Called when one of the project files changes. In our case since only one file is watched with each cookie so the list of files
        /// should be one.
        /// </summary>
        public int FilesChanged(uint cChanges, string[] rgpszFile, uint[] grfChange)
        {
            if (cChanges == 1 && (grfChange[0] & (uint)(_VSFILECHANGEFLAGS.VSFILECHG_Size | _VSFILECHANGEFLAGS.VSFILECHG_Time)) != 0)
            {
                IReloadableProject changedProject = null;
                lock (_registeredProjects)
                {
                    changedProject = _registeredProjects.FirstOrDefault(kv => kv.Key.ProjectFile.Equals(rgpszFile[0], StringComparison.OrdinalIgnoreCase)).Key;
                }

                if (changedProject != null)
                {
                    lock (_changedProjects)
                    {
                        if (!_changedProjects.Contains(changedProject))
                        {
                            _changedProjects.Add(changedProject);
                        }

                        ReloadDelayScheduler.ScheduleAsyncTask(async(ct) =>
                        {
                            // Grab the UI thread so that we block until the reload of this set of
                            // projects completes.
                            await _threadHandling.SwitchToUIThread();

                            if (ct.IsCancellationRequested)
                            {
                                return;
                            }

                            // Get the list of projects and create a new empty list to put new requests
                            List <IReloadableProject> changedProjects;
                            lock (_changedProjects)
                            {
                                changedProjects  = _changedProjects;
                                _changedProjects = new List <IReloadableProject>();
                            }

                            var failedProjects = new List <Tuple <IReloadableProject, ProjectReloadResult> >();
                            _threadHandling.ExecuteSynchronously(async() =>
                            {
                                foreach (var project in changedProjects)
                                {
                                    ProjectReloadResult result = await project.ReloadProjectAsync().ConfigureAwait(true);

                                    if (result == ProjectReloadResult.ReloadFailed || result == ProjectReloadResult.ReloadFailedProjectDirty)
                                    {
                                        failedProjects.Add(new Tuple <IReloadableProject, ProjectReloadResult>(project, result));
                                    }
                                }
                            });

                            ProcessProjectReloadFailures(failedProjects);
                        });
                    }
                }
            }
            return(VSConstants.S_OK);
        }
Example #4
0
        /// <summary>
        /// Called by reloadable projects upon close go unregister themselves
        /// Removes the file change watch on the project file.
        /// </summary>
        public async Task UnregisterProjectAsync(IReloadableProject project)
        {
            Requires.NotNull(project, nameof(project));

            await _threadHandling.SwitchToUIThread();

            UnregisterProject(project);
        }
Example #5
0
        /// <summary>
        /// Puts up UI to allow the user to decide on the appropriate action for a project which is dirty
        /// in memory
        /// </summary>
        private void ProcessProjectDirtyInMemory(IReloadableProject project)
        {
            var buttons = new string[] { VSResources.Ignore,
                                         VSResources.Overwrite,
                                         VSResources.Discard,
                                         VSResources.SaveAs };

            var msgText = string.Format(VSResources.ConflictingModificationsPrompt, Path.GetFileNameWithoutExtension(project.ProjectFile));

            switch (_dialogServices.ShowMultiChoiceMsgBox(VSResources.ConflictingProjectModificationTitle, msgText, buttons))
            {
            case MultiChoiceMsgBoxResult.Cancel:
            {
                break;
            }

            case MultiChoiceMsgBoxResult.Button1:
            {
                // Ignore
                break;
            }

            case MultiChoiceMsgBoxResult.Button2:
            {
                // Overwrite
                int hr = SaveProject(project);

                if (ErrorHandler.Failed(hr))
                {
                    _userNotificationServices.ReportErrorInfo(hr);
                }
                break;
            }

            case MultiChoiceMsgBoxResult.Button3:
            {
                // Discard
                ReloadProjectInSolution(project);
                break;
            }

            case MultiChoiceMsgBoxResult.Button4:
            {
                // Save as
                int hr = SaveAsProject(project);
                if (ErrorHandler.Succeeded(hr))
                {
                    ReloadProjectInSolution(project);
                }
                else
                {
                    _userNotificationServices.ReportErrorInfo(hr);
                }
                break;
            }
            }
        }
Example #6
0
        /// <summary>
        /// Called by reloadable projects to register themselves
        /// </summary>
        public async Task RegisterProjectAsync(IReloadableProject project)
        {
            Requires.NotNull(project, nameof(project));

            await Initialize().ConfigureAwait(false);

            await _threadHandling.SwitchToUIThread();

            RegisterProject(project);
        }
Example #7
0
        /// <summary>
        /// Saves just the project file (does not save dirty documents)
        /// </summary>
        int SaveProject(IReloadableProject project)
        {
            IVsSolution        solution = _serviceProvider.GetService <IVsSolution, SVsSolution>();
            __VSSLNSAVEOPTIONS saveOpts = __VSSLNSAVEOPTIONS.SLNSAVEOPT_SkipDocs;

            VsShellUtilities.GetRDTDocumentInfo(_serviceProvider, project.ProjectFile, out IVsHierarchy hier, out uint itemid, out IVsPersistDocData docData, out uint docCookie);
            int hr = solution.SaveSolutionElement((uint)saveOpts, project.VsHierarchy, docCookie);

            return(hr);
        }
Example #8
0
        /// <summary>
        /// Uses SaveAs to save a copy of the project somewhere else.
        /// </summary>
        int SaveAsProject(IReloadableProject project)
        {
            // Save as needs to go through IPersistFileFormat
            var persistFileFmt = project.VsHierarchy as IPersistFileFormat;
            var uishell        = _serviceProvider.GetService <IVsUIShell, SVsUIShell>();
            int hr             = uishell.SaveDocDataToFile(VSSAVEFLAGS.VSSAVE_SaveCopyAs, persistFileFmt, project.ProjectFile, out string newFile, out int canceled);

            if (ErrorHandler.Succeeded(hr) && canceled == 1)
            {
                hr = VSConstants.E_ABORT;
            }

            return(hr);
        }
Example #9
0
        /// <summary>
        /// Puts up a prompt appropriate for project which failed the autoload. ignoreAll or reloadAll will be set
        /// to true if the user selected those options
        /// </summary>
        private void ProcessProjectWhichFailedReload(IReloadableProject project, out bool ignoreAll, out bool reloadAll)
        {
            ignoreAll = false;
            reloadAll = false;
            var buttons = new string[] { VSResources.IgnoreAll,
                                         VSResources.Ignore,
                                         VSResources.ReloadAll,
                                         VSResources.Reload };

            // TODO: Consider showing different messages for reload failed and needs forced reload.
            var msgText = string.Format(VSResources.ProjectModificationsPrompt, Path.GetFileNameWithoutExtension(project.ProjectFile));

            switch (_dialogServices.ShowMultiChoiceMsgBox(VSResources.ProjectModificationDlgTitle, msgText, buttons))
            {
            case MultiChoiceMsgBoxResult.Cancel:
            {
                break;
            }

            case MultiChoiceMsgBoxResult.Button1:
            {
                // Ignore All
                ignoreAll = true;
                break;
            }

            case MultiChoiceMsgBoxResult.Button2:
            {
                // Ignore
                break;
            }

            case MultiChoiceMsgBoxResult.Button3:
            {
                // Reload  all
                reloadAll = true;
                ReloadProjectInSolution(project);
                break;
            }

            case MultiChoiceMsgBoxResult.Button4:
            {
                // Reload
                ReloadProjectInSolution(project);
                break;
            }
            }
        }
Example #10
0
        /// <summary>
        /// Helper to use the solution to reload the project.
        /// Reloading is managed via the ReloadItem() method of our parent hierarchy (solution
        /// or solution folder).  So first we get our parent hierarchy and our itemid in the parent
        /// hierarchy.
        /// </summary>
        void ReloadProjectInSolution(IReloadableProject project)
        {
            // Get our parent hierarchy and our itemid in the parent hierarchy.
            IVsHierarchy parentHier = project.VsHierarchy.GetProperty <IVsHierarchy>(VsHierarchyPropID.ParentHierarchy, null);

            if (parentHier == null)
            {
                ErrorHandler.ThrowOnFailure(VSConstants.E_UNEXPECTED);
            }

            uint parentItemid = (uint)project.VsHierarchy.GetProperty <int>(VsHierarchyPropID.ParentHierarchyItemid, unchecked ((int)VSConstants.VSITEMID_NIL));

            if (parentItemid == VSConstants.VSITEMID_NIL)
            {
                ErrorHandler.ThrowOnFailure(VSConstants.E_UNEXPECTED);
            }

            // Now using IVsPersistHierarchyItem2 we reload the project.
            int hr = ((IVsPersistHierarchyItem2)parentHier).ReloadItem((uint)parentItemid, dwReserved: 0);

            ErrorHandler.ThrowOnFailure(hr);
        }