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.