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.