How do I programmatically refresh/reload a VS project after modifying the underlying file?
Asked Answered
U

2

9

I am developing a Visual Studio package and I have written some code that will make a file in Solution Explorer dependant upon another file.

What this means is that it gives them the same relationship as code-behind files or designer files, where they appear nested under the parent file with a plus/minus icon.

+ MainForm.cs


- MainForm.cs
   MainForm.Designer.cs
   MainForm.resx

The code that I have written successfully and correctly modifies the underlying project file, however the change is not reflected in Solution Explorer until the project is closed and re-opened.

I'm looking for some code that will refresh or reload the project so that the change is visible in Solution Explorer immediately.

Further Information...

Here is the sudo code that demonstrates the mechanism by which I create the dependant file.

IVsBuildPropertyStorage vsBuildPropertyStorage = GetBuildPropertyStorage();
vsBuildPropertyStorage.SetItemAttribute(projectItemIdentifier, "DependentUpon", parentFileName);

I have also tried adding this in an attempt to get the project to reload, but it doesn't have any effect.

project.Save();
VSProject obj = project.Object as VSProject;
obj.Refresh();
Unholy answered 7/9, 2012 at 14:54 Comment(5)
How did you find the value you used for projectItemIdentifier and did you come up with a good solution for refreshing that didn't involve unloading the project?Persis
@Persis This is a rather brute-force way to make changes within a project by manually manipulating the project file's XML. A reload will be required but I never found a good way to do this. A much better way is to find the correct operation within the VS API (EnvDTE) and call that instead. Going through the API is much more robust and VS will take care of any necessary reloading. What operation are you trying to perform? If its adding a dependent file then I can help with that.Unholy
@Persis Sorry, I cant help with the projectItemIdentifier. I ended up not using this or any similar code. The VS API is more object-oriented and works by you supplying ProjectItem objects rather than identifier strings. The ProjectItems (effectively files and folders in the project) can be retrieved by iterating the Project.ProjectItems property. If you really need the projectItemIdentifier then I'd suggest debugging and looking at the properties of the ProjectItem object.Unholy
That's the confusing part. ProjectItem doesn't have a property that corresponds clearly relates to the argument expected for projectItemIdentifier that I can tell. Out of curiosity, did you ever find the "correct operation withing the VS API"? I haven't, and this solution is the closest I've seen.Persis
can you tried https://mcmap.net/q/1183644/-how-do-i-programmatically-refresh-reload-a-vs-project-after-modifying-the-underlying-file ? I test and working right in VS 2012 (I call it using my custom Addin VS). And not dialog box neither reload dialog appears (Project saved and in Source control TFS)Hannie
R
10

AFAIK the only way of doing this is via automation of the Solution Explorer tool-window:

EnvDTE.DTE dte = ...;

string solutionName = Path.GetFileNameWithoutExtension(dte.Solution.FullName);
string projectName = project.Name;

dte.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Activate();
((DTE2)dte).ToolWindows.SolutionExplorer.GetItem(solutionName + @"\" + projectName).Select(vsUISelectionType.vsUISelectionTypeSelect);

dte.ExecuteCommand("Project.UnloadProject");
dte.ExecuteCommand("Project.ReloadProject");

Note that, if the project hasn't been saved, the user will get a dialog box prior to the "Project.UnloadProject" call.

Rocaille answered 8/9, 2012 at 5:32 Comment(1)
Trying this in VS 2017, and I get the following error when it gets to dte.Windows: System.Runtime.Serialization.SerializationException: Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.Windows' in Assembly 'Microsoft.VisualStudio.Platform.WindowManagement, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.Outward
K
3

Here is my code (with reactivating the old window):

public void RefreshSolutionExplorer(EnvDTE.Project activeProject, string captionOfActiveWindow)
{
  DTE2 dte2 = activeProject.DTE as DTE2;
  string solutionName = Path.GetFileNameWithoutExtension(dte2.Solution.FullName);
  string projectName = activeProject.Name;

  // Activate SolutionExplorer window
  dte2.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate();
  // Select your project to be updated
  dte2.ToolWindows.SolutionExplorer.GetItem(solutionName + @"\" + projectName).Select(vsUISelectionType.vsUISelectionTypeSelect);
  // Refresh SolutionExplorer window
  dte2.ExecuteCommand("View.Refresh", String.Empty);
  // Reactivate your old window
  dte2.Windows.Item(captionOfActiveWindow).Activate();
}
Kreitman answered 8/4, 2020 at 9:40 Comment(1)
The View.Refresh command works only for VB and C# projects. It is useless for other types of projects, including C and C++. This asymmetry seems really odd and quirky.Siffre

© 2022 - 2024 — McMap. All rights reserved.