Visual Studio 2022社区预览版VSIX扩展无报错但无法工作
Visual Studio 2022扩展保存已打开文件列表无响应问题
问题背景
我是C#和Visual Studio初学者,正在为Visual Studio 2022社区版(64位)预览版17.7.0 Preview 2.0开发扩展,功能是将已打开的文件列表保存到文本文件C:\my_ruta\vsc_opened.txt中。
已完成操作:
- 代码无编译报错
- 编译成功并生成.vsix文件
- 扩展成功安装并激活
- 已创建
C:\my_ruta文件夹及vsc_opened.txt文件 - 以管理员身份重启Visual Studio
- 在Visual Studio中打开了多个文件
预期结果:扩展自动将已打开文件的完整路径写入vsc_opened.txt
实际结果:完全无反应,文件内容未更新
相关代码
using System; using System.ComponentModel.Design; using System.IO; using Microsoft.VisualStudio.Shell; using Task = System.Threading.Tasks.Task; using EnvDTE; using System.Runtime.InteropServices; using Microsoft.VisualStudio.Shell.Interop; using System.Threading; namespace OponedFilesHistory { [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] [Guid("297ae94e-533e-4578-a588-27a29faff749")] [ProvideAutoLoad(UIContextGuids.NoSolution)] [ProvideMenuResource("Menus.ctmenu", 1)] public static class PkgCmdIDList { public const int cmdidMyCommand = 0x100; } public sealed class OpenedFilesHistoryPackage : AsyncPackage { protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress) { System.Diagnostics.Debug.WriteLine("InitializeAsync called"); await base.InitializeAsync(cancellationToken, progress); var mcs = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; if (mcs != null) { var menuCommandID = new CommandID(new Guid("297ae94e-533e-4578-a588-27a29faff749"), (int)PkgCmdIDList.cmdidMyCommand); var menuItem = new MenuCommand(MenuItemCallback, menuCommandID); mcs.AddCommand(menuItem); } } private void MenuItemCallback(object sender, EventArgs e) { string logFile = @"C:\my_ruta\vsc_opened.txt"; ThreadHelper.ThrowIfNotOnUIThread(); EnvDTE.DTE dte = (EnvDTE.DTE)GetGlobalService(typeof(EnvDTE.DTE)); foreach (EnvDTE.Document document in dte.Documents) { string fileName = document.FullName; File.AppendAllText(logFile, fileName + Environment.NewLine); } } } }
问题排查与解决方案
1. 扩展触发逻辑误解
当前代码逻辑是仅点击对应菜单命令时才执行保存操作,而非自动监听文件打开事件。若预期自动保存,需添加文件打开事件监听;若为手动触发,需确认是否找到并点击了扩展对应的菜单按钮(通常在「工具」菜单下,需检查Menus.ctmenu配置是否正确)。
2. 包加载上下文限制
代码中[ProvideAutoLoad(UIContextGuids.NoSolution)]意味着扩展仅在无解决方案打开时加载。若你是在打开解决方案的场景下测试,包不会初始化,自然无反应。修改为支持两种场景:
[ProvideAutoLoad(UIContextGuids.NoSolution)] [ProvideAutoLoad(UIContextGuids.SolutionExists)]
3. 增加错误排查日志
在MenuItemCallback中添加异常捕获和日志输出,排查隐藏错误:
private void MenuItemCallback(object sender, EventArgs e) { string logFile = @"C:\my_ruta\vsc_opened.txt"; try { ThreadHelper.ThrowIfNotOnUIThread(); EnvDTE.DTE dte = (EnvDTE.DTE)GetGlobalService(typeof(EnvDTE.DTE)); if (dte == null) { File.AppendAllText(logFile, "Failed to get DTE service" + Environment.NewLine); return; } foreach (EnvDTE.Document document in dte.Documents) { string fileName = document.FullName; File.AppendAllText(logFile, fileName + Environment.NewLine); } File.AppendAllText(logFile, "Successfully wrote opened files" + Environment.NewLine); } catch (Exception ex) { File.AppendAllText(logFile, $"Error: {ex.Message}" + Environment.NewLine); } }
4. 检查菜单配置文件Menus.ctmenu
确保菜单配置与代码一致,示例配置:
<?xml version="1.0" encoding="utf-8"?> <CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable"> <Commands package="guidOpenedFilesHistoryPackage"> <Menus> <Menu guid="guidOpenedFilesHistoryPackageCmdSet" id="MyMenuGroup" priority="0x0600" type="Menu"> <Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/> <Strings> <ButtonText>Save Opened Files</ButtonText> </Strings> </Menu> </Menus> <Buttons> <Button guid="guidOpenedFilesHistoryPackageCmdSet" id="cmdidMyCommand" priority="0x0100" type="Button"> <Parent guid="guidOpenedFilesHistoryPackageCmdSet" id="MyMenuGroup"/> <Strings> <ButtonText>Save Opened Files List</ButtonText> </Strings> </Button> </Buttons> </Commands> <Symbols> <GuidSymbol name="guidOpenedFilesHistoryPackage" value="{297ae94e-533e-4578-a588-27a29faff749}"/> <GuidSymbol name="guidOpenedFilesHistoryPackageCmdSet" value="{297ae94e-533e-4578-a588-27a29faff749}"/> <IDSymbol name="MyMenuGroup" value="0x1020"/> <IDSymbol name="cmdidMyCommand" value="0x100"/> </Symbols> </CommandTable>
5. 验证扩展是否加载
可通过「扩展管理」确认扩展已启用,或在InitializeAsync中添加调试弹窗:
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress) { System.Diagnostics.Debug.WriteLine("InitializeAsync called"); await base.InitializeAsync(cancellationToken, progress); // 调试用弹窗,发布时移除 await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); MessageBox.Show("OpenedFilesHistoryPackage initialized!"); // ... 原有代码 }
内容的提问来源于stack exchange,提问作者MTK
相关产品推荐
相关产品推荐

