VB Visual Basic 2026 中文教程
第 34 课 · 把会变化的值移出程序代码

应用设置与配置

真正的应用不应该把所有可变化的数据都硬编码在 Form1.vb 中。API 地址、应用名称和功能开关属于“应用配置”;用户最后选择的课程、是否记住选择和窗体大小则属于“用户偏好”。本课会用 appsettings.json 管理应用配置,再用 System.Text.Json 把用户偏好保存到 LocalApplicationData,让应用重新启动后仍然记得用户的选择。

环境:Visual Studio 2026 · VB.NET · .NET 10配置:Microsoft.Extensions.Configuration实作:StudentSettingsManager2026

本课学习目标

  • 理解“应用配置”与“用户偏好”的区别。
  • 理解为什么不应该把所有可变值硬编码在程序中。
  • 建立 appsettings.json
  • 安装并使用 Microsoft.Extensions.Configuration.Json
  • 使用 ConfigurationBuilder 读取 JSON 配置。
  • 使用 IConfiguration 读取分层配置值。
  • 理解 CopyToOutputDirectory
  • 建立 UserPreferences 类。
  • 把用户偏好序列化成 JSON 文件。
  • 使用 Environment.SpecialFolder.LocalApplicationData 保存每个用户自己的设置。
  • 理解为什么秘密信息不能直接放进 appsettings.json 并提交到公开 GitHub。

34.1 什么叫“硬编码”?

如果一个可能会改变的值直接写死在程序代码里,每次修改都必须重新编辑代码、编译并发布。

例如:

Dim apiUrl As String =
    "https://api.example.com/students"

或者:

lblTitle.Text =
    "Student Manager 2026"
硬编码

值和程序逻辑混在一起;修改配置往往需要重新编译。

配置文件

把环境或部署相关值放在代码外,程序启动时读取。

34.2 应用配置与用户偏好

App Configuration

应用配置

API URL、应用标题、分页大小、功能开关等。

User Preferences

用户偏好

最后选择的课程、窗体大小、是否记住选择等。

Secrets

秘密资料

API Key、密码、Token 不应与普通配置同等处理。

34.3 建立 appsettings.json

在项目中加入:

appsettings.json

内容:

{
  "Application": {
    "Name": "Student Settings Manager 2026",
    "DefaultCourse": "Visual Basic 2026",
    "PageSize": 20
  },
  "Api": {
    "BaseUrl": "https://jsonplaceholder.typicode.com"
  },
  "Features": {
    "EnableApiDemo": true
  }
}

34.4 JSON 配置可以分层

例如:

Application
├─ Name
├─ DefaultCourse
└─ PageSize

Api
└─ BaseUrl

Features
└─ EnableApiDemo

读取时使用冒号分隔:

Application:Name
Application:DefaultCourse
Api:BaseUrl
Features:EnableApiDemo

34.5 安装 Configuration NuGet 包

右键项目:

Manage NuGet Packages
→ Browse

安装:

Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
为什么需要这个包? ConfigurationBuilder 本身负责组合配置来源,而 JSON provider 让它可以读取 appsettings.json。

34.6 确保 appsettings.json 被复制到输出目录

项目运行时,程序通常从输出目录执行。因此配置文件也必须出现在那里。

可以在项目文件中加入:

<ItemGroup>
  <None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

这样构建项目时,appsettings.json 会复制到应用输出目录。

34.7 建立 AppConfiguration.vb

创建:

Configuration\AppConfiguration.vb
Imports Microsoft.Extensions.Configuration

Public NotInheritable Class AppConfiguration

    Private Shared ReadOnly configuration As IConfigurationRoot =
        New ConfigurationBuilder().
            SetBasePath(
                AppContext.BaseDirectory).
            AddJsonFile(
                "appsettings.json",
                False,
                True).
            Build()

    Private Sub New()
    End Sub

    Public Shared ReadOnly Property ApplicationName As String
        Get
            Return configuration(
                "Application:Name")
        End Get
    End Property

    Public Shared ReadOnly Property DefaultCourse As String
        Get
            Return configuration(
                "Application:DefaultCourse")
        End Get
    End Property

    Public Shared ReadOnly Property ApiBaseUrl As String
        Get
            Return configuration(
                "Api:BaseUrl")
        End Get
    End Property

End Class

34.8 ConfigurationBuilder 在做什么?

程序启动AppContext
ConfigurationBuilder建立配置
AddJsonFile加入来源
Build()IConfigurationRoot
读取值Application:Name

34.9 为什么设置 Base Path?

SetBasePath(
    AppContext.BaseDirectory)

这样 appsettings.json 的相对路径会从应用实际运行目录开始解析,比依赖当前工作目录更清楚。

34.10 在 Form 中读取配置

Private Sub Form1_Load(
    sender As Object,
    e As EventArgs) Handles MyBase.Load

    Me.Text =
        AppConfiguration.ApplicationName

    lblApiUrl.Text =
        AppConfiguration.ApiBaseUrl

    cmbCourse.Text =
        AppConfiguration.DefaultCourse

End Sub

34.11 配置值可能缺失

如果 JSON 中没有某个 key,读取结果可能是 Nothing。因此可以提供默认值:

Dim applicationName As String =
    AppConfiguration.ApplicationName

If String.IsNullOrWhiteSpace(
    applicationName) Then

    applicationName =
        "Student Manager"

End If
配置也需要验证 不要因为值来自 appsettings.json 就假设一定正确。URL、数字范围和必要设置都应该检查。

34.12 建立 UserPreferences 类

用户可以修改的设置不要直接覆盖 appsettings.json。本课另外建立用户偏好文件。

创建:

Models\UserPreferences.vb
Public Class UserPreferences

    Public Property RememberLastCourse As Boolean = True

    Public Property LastCourse As String = ""

    Public Property WindowWidth As Integer = 1000

    Public Property WindowHeight As Integer = 700

End Class

34.13 用户设置保存在哪里?

取得当前用户本机应用数据目录:

Environment.GetFolderPath(
    Environment.SpecialFolder.LocalApplicationData)

然后建立本应用自己的子目录:

VBTutor
└─ StudentSettingsManager2026
   └─ user-settings.json
LocalApplicationData └─ VBTutor └─ StudentSettingsManager2026 └─ user-settings.json

34.14 建立 SettingsService

创建:

Services\SettingsService.vb
Imports System.IO
Imports System.Text.Json

Public Class SettingsService

    Private ReadOnly settingsFolder As String

    Private ReadOnly settingsFile As String

    Public Sub New()

        Dim localData As String =
            Environment.GetFolderPath(
                Environment.SpecialFolder.LocalApplicationData)

        settingsFolder =
            Path.Combine(
                localData,
                "VBTutor",
                "StudentSettingsManager2026")

        settingsFile =
            Path.Combine(
                settingsFolder,
                "user-settings.json")

    End Sub

34.15 保存用户偏好

Public Sub Save(
    settings As UserPreferences)

    Directory.CreateDirectory(
        settingsFolder)

    Dim options As New JsonSerializerOptions With {
        .WriteIndented = True
    }

    Dim json As String =
        JsonSerializer.Serialize(
            settings,
            options)

    File.WriteAllText(
        settingsFile,
        json)

End Sub

第一次保存时,如果目录不存在:

Directory.CreateDirectory()

会先建立它。

34.16 读取用户偏好

Public Function Load() As UserPreferences

    If Not File.Exists(
        settingsFile) Then

        Return New UserPreferences()

    End If

    Dim json As String =
        File.ReadAllText(
            settingsFile)

    Dim settings As UserPreferences =
        JsonSerializer.Deserialize(
            Of UserPreferences)(
                json)

    If settings Is Nothing Then

        Return New UserPreferences()

    End If

    Return settings

End Function

End Class

34.17 保存后的 user-settings.json

{
  "RememberLastCourse": true,
  "LastCourse": "Visual Basic 2026",
  "WindowWidth": 1100,
  "WindowHeight": 760
}

这就是 Lesson 33 所学 JSON 在真实桌面应用中的另一个用途:保存用户偏好。

34.18 实作:Student Settings Manager 2026

建立:

StudentSettingsManager2026

建议项目结构:

StudentSettingsManager2026
├─ Configuration
│  └─ AppConfiguration.vb
├─ Models
│  └─ UserPreferences.vb
├─ Services
│  └─ SettingsService.vb
├─ appsettings.json
└─ Form1.vb
Student Settings Manager 2026
应用名称:
Student Settings Manager 2026
API Base URL:
https://jsonplaceholder.typicode.com
最后课程:
Visual Basic 2026
记住课程:
Remember Last Course
窗体大小:
1100 × 760
保存偏好 重新读取 恢复默认值
设置已保存到当前用户的 LocalApplicationData。

34.19 Form1 保存 SettingsService

Public Class Form1

    Private ReadOnly settingsService As New SettingsService()

    Private currentSettings As UserPreferences

34.20 Form.Load 同时读取应用配置和用户偏好

Private Sub Form1_Load(
    sender As Object,
    e As EventArgs) Handles MyBase.Load

    Me.Text =
        AppConfiguration.ApplicationName

    lblApiUrl.Text =
        AppConfiguration.ApiBaseUrl

    Try

        currentSettings =
            settingsService.Load()

    Catch ex As Exception

        currentSettings =
            New UserPreferences()

        MessageBox.Show(
            "无法读取用户设置,将使用默认值。" &
            Environment.NewLine &
            ex.Message)

    End Try

    chkRememberCourse.Checked =
        currentSettings.RememberLastCourse

    If currentSettings.RememberLastCourse AndAlso
       Not String.IsNullOrWhiteSpace(
           currentSettings.LastCourse) Then

        cmbCourse.Text =
            currentSettings.LastCourse

    Else

        cmbCourse.Text =
            AppConfiguration.DefaultCourse

    End If

    Me.Width =
        Math.Max(
            600,
            currentSettings.WindowWidth)

    Me.Height =
        Math.Max(
            450,
            currentSettings.WindowHeight)

End Sub

34.21 保存偏好按钮

Private Sub btnSaveSettings_Click(
    sender As Object,
    e As EventArgs) Handles btnSaveSettings.Click

    Dim settings As New UserPreferences With {
        .RememberLastCourse =
            chkRememberCourse.Checked,
        .LastCourse =
            cmbCourse.Text.Trim(),
        .WindowWidth =
            Me.Width,
        .WindowHeight =
            Me.Height
    }

    Try

        settingsService.Save(
            settings)

        currentSettings =
            settings

        lblStatus.Text =
            "用户偏好已保存。"

    Catch ex As IOException

        MessageBox.Show(
            ex.Message,
            "保存设置失败",
            MessageBoxButtons.OK,
            MessageBoxIcon.Error)

    End Try

End Sub

34.22 重新读取设置

Private Sub btnReload_Click(
    sender As Object,
    e As EventArgs) Handles btnReload.Click

    Try

        currentSettings =
            settingsService.Load()

        chkRememberCourse.Checked =
            currentSettings.RememberLastCourse

        cmbCourse.Text =
            currentSettings.LastCourse

        lblStatus.Text =
            "用户偏好已重新读取。"

    Catch ex As Exception

        MessageBox.Show(
            ex.Message,
            "读取设置失败",
            MessageBoxButtons.OK,
            MessageBoxIcon.Error)

    End Try

End Sub

34.23 恢复默认值

Private Sub btnReset_Click(
    sender As Object,
    e As EventArgs) Handles btnReset.Click

    currentSettings =
        New UserPreferences()

    chkRememberCourse.Checked =
        currentSettings.RememberLastCourse

    cmbCourse.Text =
        AppConfiguration.DefaultCourse

    Me.Width =
        currentSettings.WindowWidth

    Me.Height =
        currentSettings.WindowHeight

    lblStatus.Text =
        "已经恢复默认设置。"

End Sub

34.24 关闭窗体时自动记住设置

如果希望关闭时保存:

Private Sub Form1_FormClosing(
    sender As Object,
    e As FormClosingEventArgs) Handles MyBase.FormClosing

    Dim settings As New UserPreferences With {
        .RememberLastCourse =
            chkRememberCourse.Checked,
        .LastCourse =
            cmbCourse.Text.Trim(),
        .WindowWidth =
            Me.Width,
        .WindowHeight =
            Me.Height
    }

    Try

        settingsService.Save(
            settings)

    Catch ex As IOException

        ' 关闭程序时不阻止退出。
        ' 正式应用可以写入日志。

    End Try

End Sub
自动保存和“保存”按钮可以二选一 教学时保留按钮比较容易观察流程;正式应用常在用户改变设置或程序关闭时自动保存。

34.25 为什么不直接修改 appsettings.json?

appsettings.json

随应用一起部署,适合程序级、环境级或管理员设定的非秘密配置。

user-settings.json

属于当前用户,可以在运行时修改,并保存在用户自己的应用数据目录。

34.26 配置文件不等于秘密保险箱

不要因为使用 appsettings.json 就把秘密直接放进去:

{
  "OpenAI": {
    "ApiKey": "真实秘密密钥"
  }
}
尤其不要把秘密配置提交到公开 GitHub API Key、数据库密码与 Token 应通过安全的环境变量、开发秘密机制或部署平台的密钥管理功能提供。普通 JSON 配置文件本身并不会自动加密秘密。

34.27 环境变量概念

程序可以读取环境变量:

Dim apiKey As String =
    Environment.GetEnvironmentVariable(
        "MY_API_KEY")

如果没有设置:

If String.IsNullOrWhiteSpace(
    apiKey) Then

    MessageBox.Show(
        "尚未配置 API Key。")

End If

这样源代码和公开配置文件中都不需要出现真正密钥。

34.28 配置值也要验证

例如 PageSize:

Dim pageSizeText As String =
    configuration(
        "Application:PageSize")

Dim pageSize As Integer

If Not Integer.TryParse(
    pageSizeText,
    pageSize) OrElse
   pageSize <= 0 Then

    pageSize =
        20

End If

即使值来自自己写的配置文件,也应该考虑配置被删掉、拼错或改成无效内容的情况。

34.29 本课设置架构

appsettings.json应用配置
AppConfiguration读取固定配置
Form1使用配置
SettingsService保存偏好
LocalApplicationDatauser-settings.json

34.30 初学者常见错误

错误 1

appsettings.json 没复制到输出目录

代码正确但运行时找不到文件。检查 CopyToOutputDirectory。

错误 2

把用户偏好写到安装目录

安装目录可能不适合普通用户写入;用户偏好应放到用户数据目录。

错误 3

相信配置永远有效

配置可能缺失或格式错误,重要值需要默认值与验证。

错误 4

把 API Key 当普通配置

秘密信息需要更安全的存储与部署方式。

34.31 小练习

  1. 在 appsettings.json 加入 Application:SupportEmail,在 About 对话框显示。
  2. 加入 Features:EnableApiDemo,False 时禁用 API 按钮。
  3. 在 UserPreferences 加入 DarkMode Boolean。
  4. 加入“记住上一次 API URL”的用户偏好。
  5. 故意删除 appsettings.json,观察程序启动错误,并加入更友好的错误处理。
  6. 把 PageSize 改成无效文字,加入默认值 20。
  7. 使用环境变量读取一个假的教学 API Key,而不是把值写进代码。

本课复习

  1. 什么是硬编码?
  2. 应用配置与用户偏好有什么不同?
  3. appsettings.json 适合保存哪一类设置?
  4. ConfigurationBuilder 的作用是什么?
  5. AddJsonFile() 做什么?
  6. 为什么需要 CopyToOutputDirectory?
  7. 为什么用户偏好适合放在 LocalApplicationData?
  8. 怎样把 UserPreferences 保存成 JSON?
  9. 为什么配置值也需要验证和默认值?
  10. 为什么 API Key 不应该直接放在公开 appsettings.json 或 GitHub?
技术参考: 本课配置与用户数据目录写法依据 Microsoft Learn 当前 .NET 文档整理。 ConfigurationBuilder · AddJsonFile · Environment.SpecialFolder · System.Text.Json 与 Visual Basic