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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:07:02