Visual Studio 2022中VSIX跟踪解决方案资源管理器文件的异步问题
解决VS2022中VSIX扩展定位Solution Explorer文件的异步兼容问题
核心思路
替代不可靠的固定延迟方案,通过监听VS的选择变更事件,等待目标文件被自动选中后再恢复原设置,确保操作完全同步VS2022的异步处理流程。
实现步骤与代码示例
- 保存用户原有设置:避免修改用户的「Track Active Item in Solution Explorer」偏好
- 临时开启跟踪设置:触发VS自动定位目标文件的逻辑
- 监听选择变更事件:等待VS完成文件定位操作
- 恢复设置并激活Solution Explorer:完成后还原用户配置并聚焦资源管理器
using EnvDTE; using EnvDTE80; using Microsoft.VisualStudio.Shell; using System; using System.Threading.Tasks; public async Task LocateFileInSolutionExplorerAsync(DTE2 dte, string targetFileName) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // 保存用户原有跟踪设置 var projectsAndSolutionProps = dte.Properties["Environment", "ProjectsAndSolution"]; bool originalTrackSetting = (bool)projectsAndSolutionProps.Item("TrackActiveItem").Value; try { // 临时开启跟踪设置 projectsAndSolutionProps.Item("TrackActiveItem").Value = true; // 监听选择变更事件,等待目标文件被选中 var selectionEvents = dte.Events.SelectionEvents; var tcs = new TaskCompletionSource<bool>(); EventHandler selectionChangedHandler = null; selectionChangedHandler = (sender, e) => { ThreadHelper.ThrowIfNotOnUIThread(); var selectedItems = dte.SelectedItems; if (selectedItems.Count == 1 && selectedItems.Item(1).Name.Equals(targetFileName, StringComparison.OrdinalIgnoreCase)) { selectionEvents.SelectionChanged -= selectionChangedHandler; tcs.SetResult(true); } }; selectionEvents.SelectionChanged += selectionChangedHandler; // 等待事件触发或超时(2秒),避免无限等待 await Task.WhenAny(tcs.Task, Task.Delay(2000)).ConfigureAwait(true); } finally { // 恢复用户原有设置 projectsAndSolutionProps.Item("TrackActiveItem").Value = originalTrackSetting; // 激活Solution Explorer var solutionExplorer = dte.Windows.Item(Constants.vsWindowKindSolutionExplorer); solutionExplorer.Activate(); } }
关键说明
- 使用
ThreadHelper.JoinableTaskFactory确保所有操作在VS主线程执行,适配VS2022的异步上下文 - 通过
TaskCompletionSource将事件触发转换为可等待的Task,彻底替代固定延迟的不可靠方案 - 添加超时逻辑(2秒),防止因异常情况导致的无限等待
- 用
finally块确保用户设置一定会被恢复,避免破坏用户原有操作偏好
内容的提问来源于stack exchange,提问作者Ernie S
相关产品推荐
相关产品推荐

