3

I am updating a Visual Studio extension to work in Visual Studio 2022. The extension was last updated for Visual Studio 2017.

In the extension is a helper method, ReloadProject, used to reload a project and optionally apply an action while the project is unloaded.

static internal EnvDTE.Project ReloadProject(EnvDTE.Project proj, Action duringUnload = null)
{
    Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();

    IVsSolution sol = (IVsSolution)ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution));
    IVsHierarchy selectedHierarchy;
    ErrorHandler.ThrowOnFailure(sol.GetProjectOfUniqueName(proj.UniqueName, out selectedHierarchy));
    Guid guid;
    sol.GetGuidOfProject(selectedHierarchy, out guid);
    sol.CloseSolutionElement((uint)__VSSLNCLOSEOPTIONS.SLNCLOSEOPT_UnloadProject, selectedHierarchy, 0);
    if (duringUnload != null) duringUnload();
    IVsSolution4 sol4 = (IVsSolution4)sol;
    ErrorHandler.ThrowOnFailure(sol4.ReloadProject(guid));
    return GetProject(guid);
}

However, when trying to cast sol to IVsSolution4 I get the following exception:

System.InvalidCastException
  HResult=0x80004002
  Message=Unable to cast object of type 'Microsoft.VisualStudio.CommonIDE.Solutions.Solution' to type 'Microsoft.VisualStudio.Shell.Interop.IVsSolution4'.
  Source=<Project Name>
  StackTrace:
   at <Project>.Utilities.DTE.ReloadProject(Project proj, Action duringUnload) in <FilePath>\Utilities\DTE.cs:line 185
   at <Project>.Features.NuGetBackedFeature.Enable(Project project) in <FilePath>\Features\NuGetBackedFeature.cs:line 41
   at <Project>.MyPackage.<>c.<InitializeAsync>b__1_6(Object sender, EventArgs e) in <FilePath>\MyPackage.cs:line 105
   at Microsoft.VisualStudio.Shell.OleMenuCommand.Invoke(Object inArg, IntPtr outArg, OLECMDEXECOPT options)
   at Microsoft.VisualStudio.Shell.OleMenuCommandService.Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget.Exec(Guid& commandGroup, UInt32 nCmdId, UInt32 nCmdExcept, IntPtr pIn, IntPtr vOut)

Every example I've found online suggests that I should be able to cast the result of ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)) to IVsSolution4, but this hasn't been working for me.

As far as I know, this approach still works in Visual Studio 2017 with the current version of the extension.

Does anyone know what the correct approach is to creating an IVsSolution4, or more generally, to reloading a project?

EDIT: Did some more experimenting, and found that the returned object implements IVsSolution, IVsSolution2, and IVsSolution3 (i.e. it successfully casts to each of these types). I'm wondering if something changed with the definition of IVsSolution4 in VS2022 that prevents casting.

Ganon11
  • 151
  • 6
  • Does [this](https://vssbe.r-eg.net/doc/Examples/ReloadProjects/) can help you about how to reloading a project? – Jingmiao Xu-MSFT Nov 03 '22 at 08:38
  • 2
    Adapting from your link, I tried `object service = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IVsSolution)); IVsSolution sln = (IVsSolution)service; IVsSolution4 sln4 = (IVsSolution4)service;` And get the same exception trying to convert `service` to an `IVsSolution4`. – Ganon11 Nov 04 '22 at 15:18

0 Answers0