diff --git a/src/Paket.VisualStudio/Paket.VisualStudio.csproj b/src/Paket.VisualStudio/Paket.VisualStudio.csproj
index 8ef70b7cb..4c05505e0 100644
--- a/src/Paket.VisualStudio/Paket.VisualStudio.csproj
+++ b/src/Paket.VisualStudio/Paket.VisualStudio.csproj
@@ -107,6 +107,7 @@
+
diff --git a/src/Paket.VisualStudio/SolutionExplorer/PaketMenuCommandService.cs b/src/Paket.VisualStudio/SolutionExplorer/PaketMenuCommandService.cs
index 08ec92d4d..f6315ea7a 100644
--- a/src/Paket.VisualStudio/SolutionExplorer/PaketMenuCommandService.cs
+++ b/src/Paket.VisualStudio/SolutionExplorer/PaketMenuCommandService.cs
@@ -6,6 +6,8 @@
using Paket.VisualStudio.Utils;
using System.Threading.Tasks;
using System.Threading;
+using Microsoft.VisualStudio.Shell.Interop;
+using System.Collections.Generic;
namespace Paket.VisualStudio.SolutionExplorer
{
@@ -30,12 +32,14 @@ internal class PaketMenuCommandService
private readonly IServiceProvider serviceProvider;
private readonly OleMenuCommandService menuCommandService;
private readonly ActiveGraphNodeTracker tracker;
+ private readonly SolutionEventsProxy solutionEventsProxy;
public PaketMenuCommandService(IServiceProvider serviceProvider, OleMenuCommandService menuCommandService, ActiveGraphNodeTracker tracker)
{
this.serviceProvider = serviceProvider;
this.menuCommandService = menuCommandService;
this.tracker = tracker;
+ this.solutionEventsProxy = new SolutionEventsProxy(serviceProvider);
}
@@ -189,6 +193,9 @@ private void RunCommandOnPackageAndReloadAllDependendProjects(string helpTopic,
.ToArray();
SolutionExplorerExtensions.SaveSolution();
+
+ solutionEventsProxy.TrackOpenedDocuments();
+
foreach (var projectGuid in projectGuids)
SolutionExplorerExtensions.UnloadProject(projectGuid);
@@ -232,6 +239,8 @@ private void RunCommandAndReloadAllProjects(string helpTopic, Action
+ {
+ if (openedDocuments == null || !openedDocuments.Any()) return;
+
+ SolutionExplorerExtensions.OpenFiles(this.openedDocuments)
+ .ToList()
+ .ForEach(file => this.openedDocuments.Remove(file));
+ });
+ }
+
+ private uint handle;
+ private IVsSolution solution;
+ private List openedDocuments;
+
+ private _SolutionEventsProxy solutionEventsProxy { get; }
+
+ ///
+ /// Track opened documents in projects, if they are in solution folders
+ /// they will not be unloaded, so we can ignore them
+ ///
+ internal void TrackOpenedDocuments()
+ {
+ openedDocuments = DteHelper.DTE.Documents
+ .Cast()
+ .Where(d => d.ProjectItem?.ContainingProject?.Kind != ProjectKinds.vsProjectKindSolutionFolder)
+ .Select(d => d.FullName).ToList();
+ }
+
+ class _SolutionEventsProxy : IVsSolutionEvents3
+ {
+ public ISubject ProjectOpened { get; private set; }
+
+ public _SolutionEventsProxy()
+ {
+ this.ProjectOpened = new Subject();
+ }
+
+ public int OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded)
+ {
+ this.ProjectOpened.OnNext(true);
+ return VSConstants.S_OK;
+ }
+ public int OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) { return VSConstants.S_OK; }
+ public int OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved) { return VSConstants.S_OK; }
+ public int OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) { return VSConstants.S_OK; }
+ public int OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel) { return VSConstants.S_OK; }
+ public int OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy) { return VSConstants.S_OK; }
+ public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution) { return VSConstants.S_OK; }
+ public int OnQueryCloseSolution(object pUnkReserved, ref int pfCancel) { return VSConstants.S_OK; }
+ public int OnBeforeCloseSolution(object pUnkReserved) { return VSConstants.S_OK; }
+ public int OnAfterCloseSolution(object pUnkReserved) { return VSConstants.S_OK; }
+ public int OnAfterMergeSolution(object pUnkReserved) { return VSConstants.S_OK; }
+ public int OnBeforeOpeningChildren(IVsHierarchy pHierarchy) { return VSConstants.S_OK; }
+ public int OnAfterOpeningChildren(IVsHierarchy pHierarchy) { return VSConstants.S_OK; }
+ public int OnBeforeClosingChildren(IVsHierarchy pHierarchy) { return VSConstants.S_OK; }
+ public int OnAfterClosingChildren(IVsHierarchy pHierarchy) { return VSConstants.S_OK; }
+ }
+ }
+}
diff --git a/src/Paket.VisualStudio/SolutionExplorer/SolutionExplorerExtensions.cs b/src/Paket.VisualStudio/SolutionExplorer/SolutionExplorerExtensions.cs
index dbf11ae3c..17533ecf2 100644
--- a/src/Paket.VisualStudio/SolutionExplorer/SolutionExplorerExtensions.cs
+++ b/src/Paket.VisualStudio/SolutionExplorer/SolutionExplorerExtensions.cs
@@ -84,6 +84,27 @@ public static void UnloadProject(Guid projectGuid)
ErrorHandler.ThrowOnFailure(hr);
}
+ public static IEnumerable OpenFiles(IEnumerable filesname)
+ {
+ return DteUtils.DTE.Solution.Projects
+ .OfType()
+ .SelectMany(GetProjects)
+ .SelectMany(p =>
+ {
+ var projectPath = Path.GetDirectoryName(GetProjectFullName(p));
+ var items = p.ProjectItems?.Cast();
+ return items?.Select(item => new Tuple(item, Path.Combine(projectPath, item.Name)))
+ ?? Enumerable.Empty>();
+ })
+ .Where(item => item != null && item.Item1 != null && filesname.Contains(item.Item2))
+ .Select(item => new Tuple(item.Item2, item.Item1.Open()))
+ .Select(item =>
+ {
+ item.Item2.Visible = true;
+ return item.Item1;
+ });
+ }
+
public static void ReloadProject(Guid projectGuid)
{
if (projectGuid == Guid.Empty)
@@ -117,6 +138,12 @@ public static List GetAllProjectGuids()
return projectGuids;
}
+ private static string GetProjectFullName(Project project)
+ {
+ var solutionFolder = Path.GetDirectoryName(DteUtils.DTE.Solution.FullName);
+ return Path.Combine(solutionFolder, project.UniqueName);
+ }
+
public static IEnumerable GetAllProjects()
{
return DteUtils.DTE.Solution.Projects