Skip to content

Visual Studio Extensibility: Setting.StringArray causes IDE to hang when expanding settings category #552

@Himmelt

Description

@Himmelt

Visual Studio Extensibility: Setting.StringArray causes IDE to hang when expanding settings category

问题描述 | Problem Description

中文

在 Visual Studio Extensibility 扩展开发中,使用 Setting.StringArray 类型定义设置时,当用户尝试在 工具 > 选项 中展开包含 Setting.StringArray 的设置类别时,Visual Studio 会完全卡死并最终崩溃重启。

English

When using Setting.StringArray type to define settings in Visual Studio Extensibility extension development, Visual Studio completely hangs and eventually crashes with a restart when users try to expand a settings category containing Setting.StringArray in Tools > Options.


复现步骤 | Reproduction Steps

步骤 1: 创建测试扩展 | Step 1: Create test extension

Create a minimal extension with Setting.StringArray:

[VisualStudioContribution]
internal static Setting.StringArray TestStringArray { get; } = new(
    "testStringArray",
    "Test String Array",
    TestCategory,
    defaultValue: new[] {
        "item1",
        "item2",
        "item3",
        "item4",
        "item5",
    }) {
    Description = "A test setting of type StringArray",
};

步骤 2: 调试扩展 | Step 2: Debug the extension

  1. Open the extension project in Visual Studio
  2. Press F5 to start debugging
  3. Open Tools > Options in the experimental instance
  4. Navigate to the extension's settings category
  5. Try to expand the category

步骤 3: 观察卡死 | Step 3: Observe the hang

  • Visual Studio becomes completely unresponsive
  • UI freezes
  • After ~30 seconds, the process is terminated and restarts

环境信息 | Environment Information

  • Visual Studio Version: Visual Studio Community 2022 (Version 18.x)
  • .NET SDK: .NET 8.0
  • VisualStudio.Extensibility.Sdk Version: 17.14.40608
  • OS: Windows
dotnet --list-sdks
# 10.0.102 [C:\Program Files\dotnet\sdk]

问题分析 | Problem Analysis

测试项目 | Test Project

已创建一个最小化的测试项目来隔离问题:

A minimal test project has been created to isolate the issue:

项目结构 | Project Structure:

StringArrayTestExtension/
├── StringArrayTestExtension.csproj
├── Extension/
│   ├── ExtensionEntrypoint.cs
│   ├── Commands/
│   │   └── TestCommand.cs
│   └── Settings/
│       └── TestSettings.cs        # Contains Setting.StringArray
└── .vsextension/
    └── string-resources.json

测试结果 | Test Results

设置类型 Setting Type 结果 Result
Setting.Boolean ✅ 正常 Works normally
Setting.String ✅ 正常 Works normally
Setting.StringArray 卡死 Hangs

官方文档对比 | Official Documentation Comparison

文档中支持的设置类型 | Supported setting types in documentation

根据 settings.md:

- `Setting.Boolean`
- `Setting.Decimal`
- `Setting.Enum` ✅ (有示例)
- `Setting.FormattedString`
- `Setting.Integer`
- `Setting.String`
- `Setting.EnumArray`
- `Setting.FormattedStringArray`
- `Setting.StringArray` ⚠️ (无示例)
- `Setting.ObjectArray`

问题 | Issue

  • Setting.Enum 有官方示例,使用 C# 12 集合表达式语法 [...],工作正常
  • Setting.Enum has official examples using C# 12 collection expression syntax [...], works fine
  • Setting.StringArray 没有任何使用示例,可能是一个不稳定的实验性功能
  • Setting.StringArray has no usage examples, may be an unstable experimental feature

请求 | Request

  1. 确认问题 | Confirm the issue

    • 请确认 Setting.StringArray 是否是实验性功能
    • Please confirm if Setting.StringArray is an experimental feature
  2. 提供文档示例 | Provide documentation examples

    • 如果 Setting.StringArray 是稳定的,请提供使用示例
    • If Setting.StringArray is stable, please provide usage examples
  3. 修复 bug | Fix the bug

    • 如果是 bug,请修复 Setting.StringArray 的实现
    • If it's a bug, please fix the Setting.StringArray implementation
  4. 或者确认不支持 | Or confirm it's not supported

    • 如果不支持,请从文档中移除或在 API 文档中标记为已弃用
    • If not supported, please remove from documentation or mark as deprecated in API docs

附加文件:测试项目关键代码 | Appendix: Critical Test Project Code

1. 项目文件 | Project File (StringArrayTestExtension.csproj)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RootNamespace>StringArrayTestExtension</RootNamespace>
    <NoWarn>$(NoWarn);VSEXTPREVIEW_SETTINGS;VSTHRD103</NoWarn>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.14.40608" PrivateAssets="all" Aliases="VSExtensibility" />
    <PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.14.40608" PrivateAssets="all" />
  </ItemGroup>

  <ItemGroup>
    <Content Include=".vsextension\**">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>

2. 设置代码 | Settings Code (TestSettings.cs)

文件路径 | File Path: StringArrayTestExtension\Extension\Settings\TestSettings.cs

#pragma warning disable VSEXTPREVIEW_SETTINGS

using Microsoft.VisualStudio.Extensibility;
using Microsoft.VisualStudio.Extensibility.Settings;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace StringArrayTestExtension.Settings {
    internal static partial class TestSettings {
        [VisualStudioContribution]
        internal static SettingCategory TestCategory { get; } = new("testCategory", "%StringArrayTestExtension.Settings.Category.Test.DisplayName%") {
            Description = "%StringArrayTestExtension.Settings.Category.Test.Description%",
            GenerateObserverClass = true,
        };

        [VisualStudioContribution]
        internal static Setting.StringArray TestStringArray { get; } = new(
            "testStringArray",
            "%StringArrayTestExtension.Settings.TestStringArray.DisplayName%",
            TestCategory,
            defaultValue: new[] {
                "item1",
                "item2",
                "item3",
                "item4",
                "item5",
            }) {
            Description = "%StringArrayTestExtension.Settings.TestStringArray.Description%",
        };

        [VisualStudioContribution]
        internal static Setting.Boolean TestBoolean { get; } = new(
            "testBoolean",
            "%StringArrayTestExtension.Settings.TestBoolean.DisplayName%",
            TestCategory,
            defaultValue: true) {
            Description = "%StringArrayTestExtension.Settings.TestBoolean.Description%",
        };

        [VisualStudioContribution]
        internal static Setting.String TestString { get; } = new(
            "testString",
            "%StringArrayTestExtension.Settings.TestString.DisplayName%",
            TestCategory,
            defaultValue: "test value") {
            Description = "%StringArrayTestExtension.Settings.TestString.Description%",
        };

        // 静态构造函数用于记录初始化
        static TestSettings() {
            var logPath = Path.Combine(Path.GetTempPath(), "StringArrayTestExtension.log");
            try {
                File.AppendAllText(logPath, $"[{DateTime.Now:HH:mm:ss.fff}] TestSettings static constructor called{Environment.NewLine}");
                File.AppendAllText(logPath, $"[{DateTime.Now:HH:mm:ss.fff}] TestStringArray default value length: {TestStringArray?.GetType()?.GetProperty("DefaultValue")?.GetValue(TestStringArray) as string[]?.Length ?? -1}{Environment.NewLine}");
            }
            catch (Exception ex) {
                File.AppendAllText(logPath, $"[{DateTime.Now:HH:mm:ss.fff}] Error: {ex.Message}{Environment.NewLine}");
            }
        }
    }
}

3. 关键观察 | Key Observations

  • Setting.BooleanSetting.String 工作正常
  • Setting.Boolean and Setting.String work normally
  • 只有 Setting.StringArray 导致卡死
  • Only Setting.StringArray causes hang
  • ⚠️ 使用 C# 集合表达式语法 new[] { ... }
  • ⚠️ Using C# collection expression syntax new[] { ... }

4. 测试项目完整结构 | Complete Test Project Structure

StringArrayTestExtension/
├── StringArrayTestExtension.csproj          # SDK 版本: 17.14.40608
├── Extension/
│   ├── ExtensionEntrypoint.cs               # 扩展入口点
│   ├── Commands/
│   │   └── TestCommand.cs                  # 测试命令
│   └── Settings/
│       └── TestSettings.cs                  # 设置定义 (包含问题代码)
├── .vsextension/
│   ├── vsixmanifest.json
│   └── string-resources.json                # 本地化资源
└── GitHubIssue_SettingStringArray_Hang.md   # 此 Issue 文档

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions