将 Visual Studio 2022 从 17.5 或 17.6(不确定是哪一个)更新到 17.7.4(当前版本)后,我无法再调试我正在编写的扩展。该扩展是用 C# 编写的。每当我开始调试时,Visual Studio 的实验实例就会加载,并在弹出错误对话框后不久:
“MaintenanceTaskProcessorPackage”包未正确加载。
该问题可能是由配置更改或安装其他扩展引起的。您可以通过检查文件“Path\To\Log\VS22ExpLog.xml”来获取更多信息。 重新启动 Visual Studio 可能有助于解决此问题。
其他错误随之而来,VS完全无法使用。日志文件多次显示以下内容:
367 ERROR Catastrophic failure in extension loading: Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) with stack:
at Microsoft.VisualStudio.Shell.Interop.IVsSettingsStore2.GetSubCollectionNames(String szCollectionPath)
at Microsoft.VisualStudio.Shell.Settings.ShellSettingsStore.GetSubCollectionNames(String collectionPath)
at Microsoft.VisualStudio.ExtensionManager.Impl.Settings.ExtensionSettingsCache.<ReadExtensionsAndMarkMissingExtensionsForDeletionAsync>d__91.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.ExtensionManager.Impl.Settings.ExtensionSettingsCache.<LoadInstalledExtensionsFromCacheAsync>d__84.MoveNext() Extension Manager 2023/09/30 15:26:26.573
368 ERROR Error retrieving cache version attempt 1 of 5
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) Extension Manager 2023/09/30 15:26:26.574
369 ERROR Error retrieving cache version attempt 2 of 5
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) Extension Manager 2023/09/30 15:26:26.574
370 ERROR Error retrieving cache version attempt 3 of 5
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) Extension Manager 2023/09/30 15:26:26.574
371 ERROR Error retrieving cache version attempt 4 of 5
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) Extension Manager 2023/09/30 15:26:26.574
372 ERROR Error retrieving cache version, permanent error, cache will be rebuilt
在调试器中,我看到很多类型为
System.Runtime.InteropServices.COMException
的异常。
删除实验文件夹
%localappdata%\Microsoft\VisualStudio\17.0_935fe49dExp
没有帮助。执行命令
devenv.exe /rootsuffix Exp /clearcache
devenv.exe /rootsuffix Exp /updateconfiguration
(如this帖子中所建议的)在构建扩展之后确实有帮助,但只有一次。当我修改源文件并且 Visual Studio 重建扩展并将其再次部署到实验实例时,错误又回来了。
TL;DR: 将扩展项目引用的nuget包
Microsoft.VSSDK.BuildTools
更新到版本17.7。
详情: 我花了几个小时才找出原因。逐步查看
System.Runtime.InteropServices.COMException
发生位置附近的反编译和反汇编的 VS 源代码(实验实例),我发现在加载扩展时 VS 尝试通过 \REGISTRY\A\{8128FB0E-7087-45B9-1FB9-C052602201F7}\SOFTWARE\MICROSOFT\VISUALSTUDIO\17.0_935FE49DEXP\EXTENSIONMANAGER\INSTALLEDEXTENSIONS
查询注册表项
RegQueryInfoKeyW()
。请注意,VS 使用的是私有注册表配置单元 (%localappdata%\Microsoft\VisualStudio\17.0_935fe49dExp\privateregistry.bin
)。然而,该密钥被标记为已删除。因此 RegQueryInfoKeyW()
返回 ERROR_KEY_DELETED
,然后将其转换为出现在 COM 异常和日志文件中的 HRESULT
0x8000FFFF (E_UNEXPECTED)
。
为什么该密钥被删除?在
RegDeleteKeyExW()
上设置断点,我得到以下调用堆栈:
msenv.dll!Microsoft::VisualStudio::Settings::CVsSettingsStore::DeleteCollection(unsigned short const *) Unknown
Microsoft.VisualStudio.Interop.ni.dll!00007ffd992ba46c() Unknown
[Managed to Native Transition]
Microsoft.VisualStudio.Shell.15.0.dll!Microsoft.VisualStudio.Shell.Settings.ShellWritableSettingsStore.DeleteCollection(string collectionPath) Line 225 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.SettingsStorage.SettingsStoreExtensions.DeleteCollection(Microsoft.VisualStudio.ExtensionManager.SettingsStorage.IWritableSettingsStore store, string collectionPath, object syncRoot) Line 113 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.Impl.Settings.ExtensionSettingsCache.ResetCache(Microsoft.VisualStudio.ExtensionManager.Impl.Settings.CacheMode updateMode) Line 700 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.Impl.Settings.ExtensionSettingsCache.LoadInstalledExtensionsFromCacheAsync(Microsoft.VisualStudio.ExtensionManager.Impl.Settings.CacheMode updateMode, System.Threading.CancellationToken cancellationToken, int attempt) Line 445 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.Impl.Settings.ExtensionSettingsCache.GetInstalledExtensionsAsync(bool forceRefresh, Microsoft.VisualStudio.ExtensionManager.Impl.Settings.CacheMode updateMode, System.Threading.CancellationToken cancellationToken) Line 160 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.Impl.Settings.InstalledExtensionSettingsList.LoadExtensionsFromCacheAsync(System.Threading.CancellationToken cancellationToken, bool forceRefresh, Microsoft.VisualStudio.ExtensionManager.Impl.Settings.CacheMode updateMode) Line 335 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.ExtensionEngineImpl.LoadExtensionsFromCacheAsync(System.Threading.CancellationToken cancellationToken) Line 1092 C#
Microsoft.VisualStudio.ExtensionEngine.dll!Microsoft.VisualStudio.ExtensionManager.ExtensionEngineImpl.ScanIfNeededAndInitializeCacheAsync(System.Collections.Generic.IEnumerable<string> enabledExtensions, bool safeMode, long extensionsChangedTimestamp, System.Threading.CancellationToken cancellationToken) Line 990 C#
所以VS的实验实例想要重置一些扩展缓存。查看反编译后的
LoadInstalledExtensionsFromCacheAsync()
,当!ReadableSettingsStore.CollectionExists("ExtensionManager\\InstalledExtensions", SyncRoot) || !IsCacheVersionValid()
为true
时,缓存会被重置。当 IsCacheVersionValid()
注册表项 not以 2 结尾(无论“2”意味着什么)时,
false
返回 ExtensionManager\InstalledExtensions\CacheVersion
。如果缓存被重置,注册表项 ExtensionManager\InstalledExtensions
将被删除。或者至少标记为要删除,因为显然它的一些句柄仍然打开,因此密钥不会立即删除。这可能是错误,也是 VS 最终无法重建缓存的原因。
当我开始调试扩展并使用 procmon 时,我可以看到注册表项
ExtensionManager\InstalledExtensions\CacheVersion
最初包含 17.2.2186.59434:1
。它想要设置17.7.34031.279:2
。注意运行后
devenv.exe /rootsuffix Exp /clearcache
devenv.exe /rootsuffix Exp /updateconfiguration
在不重建扩展的情况下,
17.7.34031.279:2
已经是CacheVersion
的值。所以在这种情况下 VS 不会重建任何东西,从而成功启动。
现在有一个问题:当您在 Visual Studio 中构建扩展(在非实验实例中!)并将其部署到实验实例时,MSBuild 实际上会打开实验实例的私有注册表配置单元并设置
CacheVersion
到17.2.2186.59434:1
。这导致实验实例想要完全重建缓存,这是有问题的并且失败了。
因此,此时我在扩展项目文件中搜索
"17.2"
,并注意到该项目引用了版本17.2.2186中的nuget包Microsoft.VSSDK.BuildTools
。更新到17.7.2196后,现在一切正常了。