Manage project loading in a solution

Visual Studio solutions can contain a large number of projects. The default Visual Studio behavior is to load all the projects in a solution at the time the solution is opened, and not to allow the user to access any of the projects until all of them have finished loading. When the process of project loading will last more than two minutes, a progress bar is displayed showing the number of projects loaded and the total number of projects. The user can unload projects while working in a solution with multiple projects, but this procedure has some disadvantages: the unloaded projects are not built as part of a Rebuild Solution command, and IntelliSense descriptions of types and members of closed projects are not displayed.

Developers can reduce solution load times and manage project loading behavior by creating a solution load manager. The solution load manager can make sure that projects are loaded before starting a background build, delay background loading until other background tasks are complete, and perform other project load management tasks.

Create a solution load manager

Developers can create a solution load manager by implementing IVsSolutionLoadManager and advising Visual Studio that the solution load manager is active.

Activate a solution load manager

Visual Studio allows only one solution load manager at a given time, so you must advise Visual Studio when you want to activate your solution load manager. If a second solution load manager is activated later on, your solution load manager will be disconnected.

You must get the SVsSolution service and set the __VSPROPID4.VSPROPID_ActiveSolutionLoadManager property:

IVsSolution pSolution = GetService(typeof(SVsSolution)) as IVsSolution;
object objLoadMgr = this;   //the class that implements IVsSolutionManager
pSolution.SetProperty((int)__VSPROPID4.VSPROPID_ActiveSolutionLoadManager, objLoadMgr);

The OnDisconnect method is called either when Visual Studio is being shut down or when a different package has taken over as the active solution load manager by calling SetProperty with the __VSPROPID4.VSPROPID_ActiveSolutionLoadManager property.

Strategies for different kinds of solution load manager

You can implement solution load managers in different ways, depending on the types of solutions they are meant to manage.

If the solution load manager is meant to manage solution loading in general, it can be implemented as part of a VSPackage. The package should be set to autoload by adding the ProvideAutoLoadAttribute on the VSPackage with a value of SolutionOpening_guid. The solution load manager can then be activated in the Initialize method.

Note

For more information about autoloading packages, see Loading VSPackages.

Since Visual Studio recognizes only the last solution load manager to be activated, general solution load managers should always detect whether there is an existing load manager before activating themselves. If calling GetProperty() on the solution service for __VSPROPID4.VSPROPID_ActiveSolutionLoadManager returns null, there is no active solution load manager. If it does not return null, check whether the object is the same as your solution load manager.

If the solution load manager is meant to manage only a few types of solution, the VSPackage can subscribe to solution load events (by calling AdviseSolutionEvents), and use the event handler for OnBeforeOpenSolution to activate the solution load manager.

If the solution load manager is meant to manage only specific solutions, the activation information can be persisted as part of the solution file by calling WriteSolutionProps for the pre-solution section.

Specific solution load managers should deactivate themselves in the OnAfterCloseSolution event handler, in order not to conflict with other solution load managers.

If you need a solution load manager only to persist global project load properties (for example, properties set on an Options page), you can activate the solution load manager in the OnAfterOpenProject event handler, persist the setting in the solution properties, then deactivate the solution load manager.

Handle solution load events

To subscribe to solution load events, call AdviseSolutionEvents when you activate your solution load manager. If you implement IVsSolutionLoadEvents, you can respond to events that relate to different project loading properties.

  • OnBeforeOpenSolution: This event is fired before a solution is opened.

  • OnBeforeBackgroundSolutionLoadBegins: This event is fired after the solution is completely loaded, but before background project loading begins again.

  • OnAfterBackgroundSolutionLoadComplete: This event is fired after a solution is initially fully loaded, whether or not there is a solution load manager. It is also fired after background load or demand load whenever the solution becomes fully loaded. At the same time, SolutionExistsAndFullyLoaded_guid is reactivated.

  • OnQueryBackgroundLoadProjectBatch: This event is fired before the loading of a project (or projects). To ensure that other background processes are completed before the projects are loaded, set pfShouldDelayLoadToNextIdle to true.

  • OnBeforeLoadProjectBatch: This event is fired when a batch of projects is about to be loaded. If fIsBackgroundIdleBatch is true, the projects are to be loaded in the background; if fIsBackgroundIdleBatch is false, the projects are to be loaded synchronously as a result of a user request, for example if the user expands a pending project in Solution Explorer. You can handle this event to do expensive work that otherwise would need to be done in OnAfterOpenProject.

  • OnAfterLoadProjectBatch: This event is fired after a batch of projects has been loaded.

Detect and manage solution and project loading

In order to detect the load state of projects and solutions, call GetProperty with the following values:

You can also ensure that projects and solutions are loaded by calling one of the following methods:

  • EnsureSolutionIsLoaded: calling this method forces the projects in a solution to load before the method returns.

  • EnsureProjectIsLoaded: calling this method forces the projects in guidProject to load before the method returns.

  • EnsureProjectsAreLoaded: calling this method forces the project in guidProjectID to load before the method returns.