Visual Studio Upgrade Wizard

1 view
Skip to first unread message

Kusi Bertoldo

unread,
Aug 5, 2024, 2:23:52 PM8/5/24
to motermautsik
Changesto the project model from one version of Visual Studio to the next may require that projects and solutions be upgraded so that they can run on the newer version. The Visual Studio SDK provides interfaces that can be used to implement upgrade support in your own projects.

To support an upgrade, your project system implementation must define and implement an upgrade strategy. In determining your strategy, you can choose to support side-by-side (SxS) backup, copy backup, or both.


When a solution created in an earlier version of Visual Studio is opened in a newer version, the IDE checks the solution file to determine if it needs to be upgraded. If upgrading is required, the Upgrade Wizard is automatically launched to walk the user through the upgrade process.


When a solution needs upgrading, it queries each project factory for its upgrade strategy. The strategy determines whether the project factory supports copy backup or SxS backup. The information is sent to the Upgrade Wizard, which collects the information required for the backup and presents the applicable options to the user.


If a solution contains multiple projects and the upgrade strategies differ, such as when a C++ project that only supports SxS backup and a Web project that only support copy backup, the project factories must negotiate the upgrade strategy.


The solution queries each project factory for IVsProjectUpgradeViaFactory. It then calls UpgradeProject_CheckOnly to see if global project files need upgrading and to determine the supported upgrade strategies. The Upgrade Wizard is then invoked.


After the user completes the wizard, UpgradeProject is called on each project factory to perform the actual upgrade. To facilitate backup, IVsProjectUpgradeViaFactory methods provide the SVsUpgradeLogger service to log the details of the upgrade process. This service cannot be cached.


After updating all relevant global files, each project factory can choose to instantiate a project. The project implementation must support IVsProjectUpgrade. The UpgradeProject method is then called to upgrade all relevant project items.


Use the SVsQueryEditQuerySave service to check if you can edit a file before editing it, and can save it before saving it. This will help your backup and upgrade implementations handle project files under source control, files with insufficient permissions, and so forth.


If you change the information persisted in the project file between different Visual Studio versions of your product, then you need to support upgrading your project file from the old to the new version. To support upgrading that allows you to participate in the Visual Studio Conversion Wizard, implement the IVsProjectUpgradeViaFactory interface. This interface contains the only mechanism available for copy upgrading. The upgrading of the project happens as a part of the solution opens. The IVsProjectUpgradeViaFactory interface is implemented by the project factory, or should at least be obtainable from the project factory.


The old mechanism that uses the IVsProjectUpgrade interface is still supported, but conceptually upgrades the project system as a part of the project open. The IVsProjectUpgrade interface is therefore called by the Visual Studio environment even if the IVsProjectUpgradeViaFactory interface is called or implemented. This approach allows you to use IVsProjectUpgradeViaFactory to implement the copy and project only portions of the upgrade, and delegate the rest of the work to be done in-place (possibly at the new location) by the IVsProjectUpgrade interface.


If the UPF_SILENTMIGRATE flag is specified in the UpgradeProject call, then the user has been prompted by the environment to upgrade the project file as an in-place upgrade, after the project is opened. For example, the environment prompts the user to upgrade when the user opens an older version of the solution.


"The project '%1' was created with an older version of Visual Studio. If you open it with this version of Visual Studio, you may not be able to open it with older versions of Visual Studio. Do you want to continue and open this project?"


Implement the method of the IVsProjectUpgradeViaFactory interface, specifically the UpgradeProject method in your project factory implementation, or make the implementations callable from your project factory implementation.


For both the steps 2 and 3, the actual file upgrade steps, using IVsQueryEditQuerySave2, can be implemented as described in the "Implementing IVsProjectUpgade" section below, or you can delegate the actual file upgrade to IVsProjectUpgrade.


IVsFileUpgrade interface is used to implement any kind of file upgrade that needs to happen as part of project upgrade. This interface is not called from IVsProjectUpgradeViaFactory, but is supplied as a mechanism to upgrade files that are part of the project system, but the main project system might not be directly aware of. For example, this situation could arise if the compiler related files and properties are not handled by the same development team that handles the rest of the project system.


If your project system implements IVsProjectUpgrade only, it can't participate in the Visual Studio Conversion Wizard. However, even if you implement the IVsProjectUpgradeViaFactory interface, you can still delegate the file upgrade to IVsProjectUpgrade implementation.


When a user attempts to open a project, the UpgradeProject method is called by the environment after the project is opened and before any other user action can be taken on the project. If the user had already been prompted to upgrade the solution, then the UPF_SILENTMIGRATE flag is passed in the grfUpgradeFlags parameter. If the user opens a project directly, such as by using the Add Existing Project command, then the UPF_SILENTMIGRATE flag is not passed and the project needs to prompt the user to upgrade.


In response to the UpgradeProject call, the project must evaluate whether the project file is upgraded. If the project does not need to upgrade the project type to a new version, then it can simply return the S_OK flag.


If the project needs to upgrade the project type to a new version, then it must determine whether the project file can be modified by calling the QueryEditFiles method and passing in a value of tagVSQueryEditFlags for the rgfQueryEdit parameter. The project then needs to do the following:


If the VSQueryEditResult value returned in the pfEditCanceled parameter is QER_EditNotOK and the VSQueryEditResult value has the QER_ReadOnlyNotUnderScc bit set, then UpgradeProject must return failure, because users should resolve the permissions issue themselves. The project should then do the following:


If the VSQueryEditResult value is QER_EditNotOK and the VSQueryEditResultFlags value has the QER_ReadOnlyUnderScc bit set, then the project file should be checked out by calling QueryEditFiles (QEF_ForceEdit_NoPrompting, QEF_DisallowInMemoryEdits,...).


If the QueryEditFiles call on the project file causes the file to be checked out, and the latest version to be retrieved, then the project is unloaded and reloaded. The UpgradeProject method is called again once another instance of the project is created. On this second call, the project file can be written to disk; it is recommended that the project save a copy of the project file in the previous format with an .OLD extension, make its necessary upgrade changes, and save the project file in the new format. Again, if any part of the upgrade process fails, the method must indicate failure by returning VS_E_PROJECTMIGRATIONFAILED. This causes the project to be unloaded in Solution Explorer.


It is important to understand the complete process that occurs in the environment for the case in which the call to the QueryEditFiles method (specifying a value of ReportOnly) returns the QER_EditNotOK and the QER_ReadOnlyUnderScc flags.


If you handle your own project reload, then the environment calls your ReloadItem (VSITEMID_ROOT) implementation. When you receive this call, reload the first instance of your project (Project1) and continue upgrading your project file. The environment knows that you handle your own project reload if you return true for GetProperty (VSHPROPID_HandlesOwnReload).


If you do not handle your own project reload, then you return false for GetProperty (VSHPROPID_HandlesOwnReload). In this case, before QueryEditFiles(QEF_ForceEdit_NoPrompting, QEF_DisallowInMemoryEdits) returns, the environment creates another new instance of your project, for example, Project2, as follows:


The environment calls IVsProjectUpgrade::UpgradeProject for a second time to determine whether the project object should be upgraded. However, this call is made on a new, second, instance of the project, Project2. This is the project that is opened in the solution.


If you fail to upgrade, return VS_E_PROJECTMIGRATIONFAILED from IVsProjectUpgrade::UpgradeProject. If no upgrade is necessary or you choose not to upgrade, treat the IVsProjectUpgrade::UpgradeProject call as a no-op. If you return VS_E_PROJECTMIGRATIONFAILED, a placeholder node is added to the solution for your project.


If you add or manage items inside project systems you do not implement, you may need to participate in the project upgrade process. Crystal Reports is an example of an item that can be added to the project system.


Typically, project item implementers want to leverage an already fully instantiated and upgraded project because they need to know what the project references are and what other project properties are there to make an upgrade decision.


Set the SolutionOrProjectUpgrading flag (defined in vsshell80.idl) in your project item implementation. This causes your project item VSPackage to auto load when the Visual Studio shell determines that a project system is in the process of upgrading.


The IVsSolutionEventsProjectUpgrade interface is fired after the project system implementation has completed its upgrade operations and the new upgraded project is created. Depending on the scenario, the IVsSolutionEventsProjectUpgrade interface is fired after the OnAfterOpenSolution, the OnAfterOpenProject, or the OnAfterLoadProject methods.

3a8082e126
Reply all
Reply to author
Forward
0 new messages