locked
Implementing IVsProjectUpgradeViaFactory to convert a custom project. RRS feed

  • Question

  • I've searched around the forum a bit and looked at some of the project samples, but I'm still a bit unclear on whether I need to implement both IVsProjectUpgrade on my project node if I'm implementing IVsProjectUpgradeViaFactory on my project factory.  The docs indicate that IVsProjectUpgrade is always called, so I was afraid that the shell would try to query our project system for IVsProjectUpgrade and fail if it wasn't found.  A quick bit of experimenting indicates that it doesn't crash.  The docs also indicate that the project factory's implementation can just delegate much of the work to the project node's IVsProjectUpgrade implementation.  But, when the project factory's code is invoked, there is no IVsHierarchy instance to operate on, so how could the project factory delegate anything to the project node's IVsProjectUpgrade implementation?
    Monday, October 29, 2012 4:09 PM

Answers

  • If you don't implement IVsProjectUpgrade the project load will not fail. However, as you have noted, you may not be able to do everything in IVsProjectUpgradeViaFactory such as not having the IVsHierarchy instance.
    Also, IVsProjectUpgradeViaFactory::UpgradeProject is called only if IVsProjectUpgradeViaFactory::UpgradeProject_CheckOnly returns a flag indicating that an upgrade is needed but IVsUpgradeProject::UpgradeProject is always called.
    The delegation implied in the documentation is in terms of some of the work needed to have your project fully upgraded. The copy upgrade portions can be done in IvsProjectUpgradeViaFactory while you can evaluate which other portion can be done in IVsProjectFactory::UpgradeProject for example if you need IVsHierarchy.
    I would recommend checks which only need to be done once in the lifetime of the project to be done from the IVsProjectUpgradeViaFactory::UpgradeProject while those which need checking often be done in IVsProjectUpgrade::UpgradeProject.

    The project will not fail to load if IVsProjectUpgrade is not implemented as far as the method UpgradeProject is concerned but it would be better at least to implement stub if at all this must change in future.

    While you're reviewing your upgrade experience and if you're using VS 2012, please note the new upgrade improvements documented here for a better user experience:

    http://msdn.microsoft.com/en-us/library/hh266706.aspx

    Thanks

    Elisha

    Monday, October 29, 2012 8:48 PM

All replies

  • If you don't implement IVsProjectUpgrade the project load will not fail. However, as you have noted, you may not be able to do everything in IVsProjectUpgradeViaFactory such as not having the IVsHierarchy instance.
    Also, IVsProjectUpgradeViaFactory::UpgradeProject is called only if IVsProjectUpgradeViaFactory::UpgradeProject_CheckOnly returns a flag indicating that an upgrade is needed but IVsUpgradeProject::UpgradeProject is always called.
    The delegation implied in the documentation is in terms of some of the work needed to have your project fully upgraded. The copy upgrade portions can be done in IvsProjectUpgradeViaFactory while you can evaluate which other portion can be done in IVsProjectFactory::UpgradeProject for example if you need IVsHierarchy.
    I would recommend checks which only need to be done once in the lifetime of the project to be done from the IVsProjectUpgradeViaFactory::UpgradeProject while those which need checking often be done in IVsProjectUpgrade::UpgradeProject.

    The project will not fail to load if IVsProjectUpgrade is not implemented as far as the method UpgradeProject is concerned but it would be better at least to implement stub if at all this must change in future.

    While you're reviewing your upgrade experience and if you're using VS 2012, please note the new upgrade improvements documented here for a better user experience:

    http://msdn.microsoft.com/en-us/library/hh266706.aspx

    Thanks

    Elisha

    Monday, October 29, 2012 8:48 PM
  • Hello Elisha,

    Thank you for taking the time to craft such a thorough and helpful answer.  It does make more sense now.  I also had not yet come across the improved scheme offered in Dev11 but will look forward to checking that out as well.

    Thanks again.

    Monday, October 29, 2012 8:52 PM
  • Hi Elisha,

    I was hoping I ask a few follow-on questions, as we've gotten further along in our implementation.  Note that all of these questions are for Dev10.

    1) What is the proper way to report errors from IVsProjectUpgradeViaFactory?  Returning a failure HRESULT and calling the IVsUpgradeLogger.LogMessage with VSUL_ERROR does show an error message in the conversion report, but when the conversion wizard finishes, it says that all projects converted successfully (and the "Show report.." checkbox is unchecked).  The project iself does not load, so it appears greyed out in Solution Explorer, but the user has to actually look at the details of the conversion report to see that the Error count is non-zero for one of the projects.  How can we make the conversion wizard say that the project conversion failed rather than all projects converted successfully?  Note that our solution consists of multiple custom project types that may or may not be participating in the conversion for a particular session.

    2) If we choose to divide the conversion labor between IVsProjectUpgradeViaFactory and IVsProjectUpgrade, then how can the ProjectNode's implementation of UpgradeProject report errors in the conversion report. We've experimented with caching the logger from the project factory and passing it to the ProjectNode. But, this "feels" dangerous and it doesn't seem to work -- perhaps the conversion wizard is done with it's work by this time. It seems all we can do from the ProjectNode's UpgradeProject is return a failure HRESULT if something goes wrong. Then the user is left wondering why their project appears unloaded in Solution Explorer and they don't have anywhere to look for an explanation. Am I understanding this behavior correctly, and if so, wouldn't that imply that one should try to do as much as possible in IVsProjectUpgradeViaFactory (as opposed to IVsProjectUpgrade) if for no other reason than error reporting?

    3) I'm not clear on what the output values of "upgradeRequired" and "guidNewProjectFactory" should be in the UpgradeProject call.  In the case of upgradeRequired, the CheckOnly call has already indicated an upgrade was required, else the UpgradeProject call would not have been made.  What should this value be set to within UpgradeProject.  And, for guidNewProjectFactory, we use the same project factory, so should this value be null or just the same GUID as the currently executing factory class?

    4) Is there any way to report errors from CheckOnly and have it stop the conversion process?  For instance, if we can't determine the version of our project file for some reason (corrupt file, etc), then it's not safe for UpgradeProject to do anything.  Also, the logger seems to be null when CheckOnly is called, so we can't put anything in the report.

    5) Is there any way to participate in the conversion of other Visual Studio projects that we do not flavor?  Our custom project types manage C# and C++ project types that we don't flavor.  But, we do need to update some of their MSBuild properties and project items.  At the time of loading our custom project and upgrading it, I don't think we can even be assured the other non-custom projects have even been loaded, can we?

    Thanks very much in advance.

    Wednesday, October 31, 2012 2:18 PM
  • Was wondering if there were any thoughts on the follow-up questions posed above.  Any advice is much appreciated.

    Thanks in advance.

    Wednesday, November 7, 2012 2:27 PM