You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS2022扩展升级:IVsSolution转IVsSolution4失败求助

问题描述

将适配Visual Studio 2017的扩展升级至Visual Studio 2022时,原有的ReloadProject辅助方法在转换IVsSolution到IVsSolution4时抛出InvalidCastException,异常信息显示无法将Microsoft.VisualStudio.CommonIDE.Solutions.Solution类型转换为Microsoft.VisualStudio.Shell.Interop.IVsSolution4。该方法在VS2017中可正常工作,且测试发现返回对象可转换为IVsSolution、IVsSolution2和IVsSolution3。

原方法代码如下:

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);
}

异常详情:

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)
解决方案

方法1:用QueryInterface显式获取IVsSolution4实例

直接强制转换失败时,改用COM互操作的QueryInterface方式获取接口:

IVsSolution4 sol4 = null;
if (sol is IUnknown unknown)
{
    Guid ivsSolution4Guid = typeof(IVsSolution4).GUID;
    IntPtr ptr = IntPtr.Zero;
    int hr = unknown.QueryInterface(ref ivsSolution4Guid, out ptr);
    if (ErrorHandler.Succeeded(hr) && ptr != IntPtr.Zero)
    {
        sol4 = Marshal.GetObjectForIUnknown(ptr) as IVsSolution4;
        Marshal.Release(ptr);
    }
}

if (sol4 != null)
{
    ErrorHandler.ThrowOnFailure(sol4.ReloadProject(guid));
}
else
{
    // 降级处理逻辑,比如使用IVsSolution3的替代方案
}

方法2:改用DTE高层API实现重载

直接利用EnvDTE.Project自带的Unload和Reload方法,无需依赖IVsSolution系列接口,兼容性更强:

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

    proj.Unload();
    duringUnload?.Invoke();
    proj.Reload();
    
    return proj;
}

该方式在VS2017和VS2022中均能稳定运行,代码更简洁。

方法3:检查VS SDK引用版本

确保扩展项目引用了Visual Studio 2022对应的SDK包,版本不低于17.0.x。在NuGet包管理器中确认Microsoft.VisualStudio.Shell.17.0或更高版本已安装,避免因SDK版本不匹配导致接口定义不一致。


内容的提问来源于stack exchange,提问作者Ganon11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:50:30