PowerShell 技能连载 - Windows Terminal 自动化

适用于 PowerShell 7.0 及以上版本

Windows Terminal 自 2019 年发布以来,已经迅速成为 Windows 平台上最受欢迎的终端应用。它不仅支持多标签页、分屏布局、GPU 加速文本渲染,还提供了完善的 JSON 配置体系。对于系统运维工程师来说,每天启动工作环境时手动打开多个标签、连接不同服务器、调整窗口布局是一项重复且耗时的工作。

借助 PowerShell 对 JSON 配置文件的读写能力,以及 wt.exe 命令行工具的强大参数支持,我们可以将这套流程完全自动化——一条命令就能启动包含多个标签和分屏的完整工作环境。更进一步,还能批量管理配色方案、快捷键绑定等个性化配置,在团队内实现统一的工作环境标准化。

本文将围绕 Windows Terminal 的配置读取与修改、多标签分屏自动化启动、以及主题配色自定义三个方面,展示如何用 PowerShell 打造一套”开箱即用”的终端工作流。

读取和修改 Windows Terminal 配置

Windows Terminal 的所有配置存储在 settings.json 文件中。通过 PowerShell 可以方便地读取、解析和修改这些配置,实现配置的版本化管理或批量部署。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
function Get-WTSettings {
<#
.SYNOPSIS
获取 Windows Terminal 的 settings.json 配置对象
#>
$settingsPath = Join-Path $env:LOCALAPPDATA `
"Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"

if (-not (Test-Path $settingsPath)) {
# 兼容预览版路径
$settingsPath = Join-Path $env:LOCALAPPDATA `
"Packages\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\LocalState\settings.json"
}

if (-not (Test-Path $settingsPath)) {
throw "未找到 Windows Terminal 配置文件"
}

$content = Get-Content -Path $settingsPath -Raw -Encoding UTF8
# 去除 JSON 注释(简易处理)
$cleanJson = $content -replace '(?m)//.*?$', ''
$config = $cleanJson | ConvertFrom-Json
return @{
Config = $config
Path = $settingsPath
Raw = $content
}
}

function Set-WTDefaultProfile {
<#
.SYNOPSIS
设置 Windows Terminal 的默认配置文件(Profile)
.PARAMETER ProfileName
要设为默认的配置文件名称,例如 "PowerShell 7"
#>
param(
[Parameter(Mandatory)]
[string]$ProfileName
)

$settings = Get-WTSettings
$config = $settings.Config

# 在 profiles.list 中查找目标配置
$target = $config.profiles.list | Where-Object {
$_.name -eq $ProfileName
} | Select-Object -First 1

if (-not $target) {
throw "未找到名为 '$ProfileName' 的配置文件"
}

# 更新默认 Profile GUID
$config.defaultProfile = $target.guid

# 写回文件,保留可读格式
$config | ConvertTo-Json -Depth 20 |
Set-Content -Path $settings.Path -Encoding UTF8

Write-Host "已将默认 Profile 设为: $ProfileName ($($target.guid))"
}

# 示例:列出所有可用的 Profile
$settings = Get-WTSettings
$settings.Config.profiles.list | ForEach-Object {
[PSCustomObject]@{
Name = $_.name
GUID = $_.guid
Hidden = $_.hidden
}
} | Format-Table -AutoSize

# 示例:将 PowerShell 7 设为默认终端
Set-WTDefaultProfile -ProfileName "PowerShell 7"

执行结果示例:

1
2
3
4
5
6
7
8
9
Name                       GUID                                 Hidden
---- ---- ------
PowerShell 7 {574e775e-4f2a-5b96-ac1e-a2962a402336} False
Command Prompt {0caa0dad-35be-5f56-a8ff-afceeeaa6101} False
Windows PowerShell {61c54bbd-c2c6-5271-96e7-009a87ff44bf} False
Azure Cloud Shell {b453cfc9-5a51-5a7e-889c-f8e96be50e27} True
Ubuntu (WSL) {2c4de342-38b7-51cf-b940-2309a097f518} False

已将默认 Profile 设为: PowerShell 7 ({574e775e-4f2a-5b96-ac1e-a2962a402336})

自动化启动多标签分屏布局

Windows Terminal 提供了 wt.exe 命令行工具,支持通过参数指定标签页、分屏布局和启动命令。我们可以封装一个 PowerShell 函数,实现一键启动包含多个服务器连接的完整运维工作台。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
function Start-WTOpsWorkbench {
<#
.SYNOPSIS
一键启动运维工作台:自动打开多个标签页和分屏窗格
.PARAMETER Environment
目标环境名称:dev / staging / production
#>
param(
[ValidateSet("dev", "staging", "production")]
[string]$Environment = "dev"
)

# 定义各环境的服务器列表
$envConfig = @{
dev = @{
servers = @("dev-web-01", "dev-db-01")
profile = "PowerShell 7"
}
staging = @{
servers = @("stg-web-01", "stg-web-02", "stg-db-01")
profile = "PowerShell 7"
}
production = @{
servers = @("prod-web-01", "prod-web-02", "prod-db-01", "prod-monitor")
profile = "PowerShell 7"
}
}

$config = $envConfig[$Environment]
$servers = $config.servers
$profile = $config.profile

# 构建 wt.exe 参数
$wtArgs = @()

# 第一个标签:本地 PowerShell + 系统监控
$wtArgs += "-p"
$wtArgs += "`"$profile`""
$wtArgs += ";"
$wtArgs += "split-pane"
$wtArgs += "-V"
$wtArgs += "-p"
$wtArgs += "`"$profile`""
$wtArgs += "--"
$wtArgs += "pwsh"
$wtArgs += "-NoExit"
$wtArgs += "-Command"
$wtArgs += '"Write-Host \"[系统监控] 本地环境\" -ForegroundColor Cyan; Get-Process | Sort-Object CPU -Descending | Select-Object -First 10"'

# 后续标签:每台服务器一个标签
foreach ($server in $servers) {
$wtArgs += ";"
$wtArgs += "new-tab"
$wtArgs += "-p"
$wtArgs += "`"$profile`""
$wtArgs += "--"
$wtArgs += "pwsh"
$wtArgs += "-NoExit"
$wtArgs += "-Command"
$wtArgs += "\"Enter-PSSession -ComputerName $server -ConfigurationName PowerShell.7\""
}

# 最后一个标签:日志查看
$wtArgs += ";"
$wtArgs += "new-tab"
$wtArgs += "-p"
$wtArgs += "`"$profile`""
$wtArgs += "--"
$wtArgs += "pwsh"
$wtArgs += "-NoExit"
$wtArgs += "-Command"
$wtArgs += '"Write-Host \"[日志中心] $Environment 环境\" -ForegroundColor Yellow; Get-Content \\logserver\logs\app.log -Tail 50 -Wait"'

Write-Host "正在启动 $Environment 环境运维工作台..." -ForegroundColor Green
Write-Host " 服务器: $($servers -join ', ')" -ForegroundColor Gray
Write-Host " 标签数: $($servers.Count + 2)" -ForegroundColor Gray

Start-Process -FilePath "wt.exe" -ArgumentList $wtArgs
}

# 一键启动开发环境工作台
Start-WTOpsWorkbench -Environment dev

# 启动生产环境工作台
# Start-WTOpsWorkbench -Environment production

执行结果示例:

1
2
3
正在启动 dev 环境运维工作台...
服务器: dev-web-01, dev-db-01
标签数: 4

此时 Windows Terminal 会自动打开,包含 4 个标签页:第一个标签上下分屏显示本地 PowerShell 和系统监控,第二个标签通过 Enter-PSSession 连接 dev-web-01,第三个标签连接 dev-db-01,第四个标签实时跟踪日志文件。

自定义主题配色与快捷操作

Windows Terminal 的配色方案(Color Scheme)和快捷键绑定(Keybindings / Actions)同样存储在 settings.json 中。我们可以用 PowerShell 批量创建自定义主题,并配置实用的快捷操作,甚至将这些配置导出给团队成员使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
function Add-WTColorScheme {
<#
.SYNOPSIS
向 Windows Terminal 添加自定义配色方案
.PARAMETER Name
配色方案名称
.PARAMETER Style
预设风格:Dracula / Solarized / Nord / TokyoNight
#>
param(
[Parameter(Mandatory)]
[string]$Name,
[ValidateSet("Dracula", "Solarized", "Nord", "TokyoNight")]
[string]$Style = "Dracula"
)

$presets = @{
Dracula = @{
"background" = "#282a36"
"foreground" = "#f8f8f2"
"cursorColor" = "#f8f8f2"
"black" = "#21222c"
"red" = "#ff5555"
"green" = "#50fa7b"
"yellow" = "#f1fa8c"
"blue" = "#bd93f9"
"purple" = "#ff79c6"
"cyan" = "#8be9fd"
"white" = "#f8f8f2"
"brightBlack" = "#6272a4"
"brightRed" = "#ff6e6e"
"brightGreen" = "#69ff94"
"brightYellow"= "#ffffa5"
"brightBlue" = "#d6acff"
"brightPurple"= "#ff92df"
"brightCyan" = "#a4ffff"
"brightWhite" = "#ffffff"
}
Nord = @{
"background" = "#2e3440"
"foreground" = "#d8dee9"
"cursorColor" = "#d8dee9"
"black" = "#3b4252"
"red" = "#bf616a"
"green" = "#a3be8c"
"yellow" = "#ebcb8b"
"blue" = "#81a1c1"
"purple" = "#b48ead"
"cyan" = "#88c0d0"
"white" = "#e5e9f0"
"brightBlack" = "#4c566a"
"brightRed" = "#bf616a"
"brightGreen" = "#a3be8c"
"brightYellow"= "#ebcb8b"
"brightBlue" = "#81a1c1"
"brightPurple"= "#b48ead"
"brightCyan" = "#8fbcbb"
"brightWhite" = "#eceff4"
}
}

$settings = Get-WTSettings
$config = $settings.Config
$rawJson = $settings.Raw

$scheme = $presets[$Style]
$scheme["name"] = $Name

# 将新配色方案追加到 schemes 数组
$schemeJson = $scheme | ConvertTo-Json -Depth 5
$newSchemesJson = $rawJson -replace \
'"schemes"\s*:\s*\[', `
("`"schemes`": [$schemeJson,")

Set-Content -Path $settings.Path -Value $newSchemesJson -Encoding UTF8
Write-Host "已添加配色方案: $Name ($Style 风格)" -ForegroundColor Green
}

function Export-WTThemeConfig {
<#
.SYNOPSIS
导出当前 Windows Terminal 的配色方案为独立 JSON 文件,方便团队共享
.PARAMETER OutputPath
导出文件路径
#>
param(
[string]$OutputPath = ".\wt-colorschemes.json"
)

$settings = Get-WTSettings
$schemes = $settings.Config.schemes

$schemes | ConvertTo-Json -Depth 10 |
Set-Content -Path $OutputPath -Encoding UTF8

Write-Host "已导出 $($schemes.Count) 个配色方案到: $OutputPath" -ForegroundColor Green

# 列出所有配色方案名称
$schemes | ForEach-Object {
" - $($_.name)"
} | Write-Host
}

function Set-WTQuickActions {
<#
.SYNOPSIS
向 Windows Terminal 添加实用快捷操作
#>

$quickActions = @(
@{
command = "splitPane"
name = "水平分屏"
keys = "ctrl+shift+bar"
},
@{
command = @{
action = "splitPane"
split = "vertical"
}
name = "垂直分屏"
keys = "ctrl+shift+plus"
},
@{
command = @{
action = "sendInput"
input = "cls`r"
}
name = "快速清屏"
keys = "ctrl+shift+k"
}
)

$settings = Get-WTSettings
$config = $settings.Config

# 追加快捷操作到 actions 列表
foreach ($action in $quickActions) {
# 检查是否已存在同名操作
$existing = $config.actions | Where-Object {
$_.name -eq $action.name
}
if (-not $existing) {
$config.actions += $action
Write-Host " 已添加快捷操作: $($action.name) [$($action.keys)]" -ForegroundColor Cyan
} else {
Write-Host " 已存在,跳过: $($action.name)" -ForegroundColor DarkGray
}
}

$config | ConvertTo-Json -Depth 20 |
Set-Content -Path $settings.Path -Encoding UTF8

Write-Host "`n快捷操作配置完成" -ForegroundColor Green
}

# 添加 Dracula 风格配色方案
Add-WTColorScheme -Name "MyDracula" -Style Dracula

# 导出配色方案供团队使用
Export-WTThemeConfig -OutputPath ".\team-wt-colors.json"

# 添加快捷操作
Set-WTQuickActions

执行结果示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
已添加配色方案: MyDracula (Dracula 风格)
已导出 6 个配色方案到: .\team-wt-colors.json
- Campbell
- Campbell Powershell
- One Half Dark
- One Half Light
- Solarized Dark
- MyDracula
已添加快捷操作: 水平分屏 [ctrl+shift+bar]
已添加快捷操作: 垂直分屏 [ctrl+shift+plus]
已添加快捷操作: 快速清屏 [ctrl+shift+k]

快捷操作配置完成

注意事项

  1. 配置文件备份:修改 settings.json 前务必先备份原文件(Copy-Item 即可)。Windows Terminal 在运行时可能随时写入配置,建议在 Terminal 关闭状态下执行修改操作,避免文件被覆盖导致配置丢失。

  2. JSON 注释兼容性settings.json 中可能包含 // 注释,标准的 ConvertFrom-Json 不支持注释。示例中使用了简易的正则去除注释,对于复杂场景建议使用 System.Text.JsonJsonNode API(PowerShell 7.4+)或第三方模块处理。

  3. wt.exe 参数转义wt.exe 的命令行参数中,分号 ; 是命令分隔符,双引号需要正确转义。在 PowerShell 中拼接参数时,注意内层引号与外层引号的嵌套关系,建议先用 $wtArgs -join ' ' 输出完整命令行检查一遍再执行。

  4. Profile GUID 稳定性:Windows Terminal 使用 GUID 标识每个 Profile,不同机器上的 GUID 可能不同。在脚本中应优先通过 Profile 名称(name 字段)查找,而非硬编码 GUID,确保脚本的可移植性。

  5. 路径兼容性:Windows Terminal 正式版和预览版的 settings.json 路径不同(包名包含 WindowsTerminalWindowsTerminalPreview)。脚本中应同时检测两个路径,也可以通过 Get-ChildItem$env:LOCALAPPDATA\Packages 下动态搜索。

  6. 远程会话依赖:使用 Enter-PSSession 连接远程服务器时,目标机器需要启用 WinRM 服务并配置好 PowerShell Remoting。生产环境中建议使用 JEA(Just Enough Administration)端点限制权限,并通过 -ConfigurationName 参数指定受限的会话配置。

PowerShell 技能连载 - Windows Terminal 定制

适用于 PowerShell 7.0 及以上版本

Windows Terminal 已经成为 Windows 平台上最受欢迎的终端模拟器之一。它支持多标签页、GPU 加速渲染、Unicode 和 UTF-8 字符显示,以及对 WSL、CMD、PowerShell 等多种 Shell 的统一管理。但对于日常重度使用命令行的开发者来说,默认的 Terminal 外观和功能往往不够用——提示符单调、配色平庸、缺少上下文信息,这些都会影响工作效率。

好消息是,借助 PowerShell 7 的强大生态,我们可以通过 Oh My Posh 主题引擎、Profile 脚本自动化以及 Terminal 的 JSON 配置,打造一个既美观又实用的终端环境。从 Git 状态感知的提示符,到一键切换配色方案,再到自定义快捷键绑定,几乎所有的视觉和行为要素都可以按需调整。

本文将从实际场景出发,逐步展示如何用 PowerShell 脚本完成 Windows Terminal 的深度定制。每一段代码都可以直接复制到你的环境中运行,让你在几分钟内拥有一个令人印象深刻的终端工作区。

安装和初始化 Oh My Posh

Oh My Posh 是一个跨平台的提示符主题引擎,可以为 PowerShell 提供丰富的上下文信息,包括 Git 分支状态、Python 虚拟环境、执行耗时等。首先我们需要安装它并配置到 Profile 中。

1
2
3
4
5
6
7
8
# 安装 Oh My Posh(使用 winget)
winget install JanDeDobbeleer.OhMyPosh -s winget

# 如果 winget 不可用,也可以用 PowerShell 直接安装
Install-Module oh-my-posh -Scope CurrentUser -Force

# 查看 Oh My Posh 版本确认安装成功
oh-my-posh --version

安装完成后,输出类似如下:

1
24.5.0

接下来将 Oh My Posh 初始化命令写入 Profile,使其在每次启动 PowerShell 时自动加载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查找或创建 Profile 文件
$profilePath = $PROFILE.CurrentUserAllHosts
if (-not (Test-Path $profilePath)) {
$null = New-Item -Path $profilePath -ItemType File -Force
Write-Host "已创建 Profile 文件: $profilePath"
} else {
Write-Host "Profile 文件已存在: $profilePath"
}

# 向 Profile 中追加 Oh My Posh 初始化行
$initLine = 'oh-my-posh init pwsh | Invoke-Expression'
$content = Get-Content -Path $profilePath -Raw -ErrorAction SilentlyContinue
if ($content -notmatch 'oh-my-posh init') {
Add-Content -Path $profilePath -Value $initLine
Write-Host '已添加 Oh My Posh 初始化命令'
} else {
Write-Host 'Oh My Posh 初始化命令已存在,跳过'
}

执行结果示例:

1
2
已创建 Profile 文件: C:\Users\dev\Documents\PowerShell\profile.ps1
已添加 Oh My Posh 初始化命令

浏览和应用主题

Oh My Posh 内置了大量开箱即用的主题,你可以通过脚本快速预览并切换。以下代码列出所有可用主题,并让你预览效果。

1
2
3
4
5
6
7
8
9
10
11
12
# 获取 Oh My Posh 主题目录
$themesDir = "$(oh-my-posh config export themes)"

# 列出所有主题文件名
$themes = Get-ChildItem -Path $themesDir -Filter '*.omp.json' |
Select-Object -ExpandProperty BaseName

Write-Host "共找到 $($themes.Count) 个主题"
Write-Host '---'
foreach ($t in $themes) {
Write-Host " - $t"
}

执行结果示例:

1
2
3
4
5
6
7
8
9
10
11
共找到 127 个主题
---
- 1_shell
- agnoster
- agnosterplus
- aliens
- amro
- atomic
- atomicBit
- avit
...

找到喜欢的主题后,将其写入 Profile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 选择主题名称
$selectedTheme = 'jandebuhr'

# 构建 Oh My Posh 初始化命令(指定主题)
$themeInit = "oh-my-posh init pwsh --config `"$themesDir\$selectedTheme.omp.json`" | Invoke-Expression"

# 读取当前 Profile 内容
$profileContent = Get-Content -Path $PROFILE.CurrentUserAllHosts -Raw

# 替换已有的 oh-my-posh init 行,或追加新行
if ($profileContent -match 'oh-my-posh init pwsh') {
$profileContent = $profileContent -replace 'oh-my-posh init pwsh.*Invoke-Expression', $themeInit
Set-Content -Path $PROFILE.CurrentUserAllHosts -Value $profileContent -NoNewline
Write-Host "已更新主题为: $selectedTheme"
} else {
Add-Content -Path $PROFILE.CurrentUserAllHosts -Value $themeInit
Write-Host "已添加主题: $selectedTheme"
}

Write-Host '请重新打开终端以查看效果'

执行结果示例:

1
2
已更新主题为: jandebuhr
请重新打开终端以查看效果

自动化管理 Terminal 配置文件

Windows Terminal 的设置存储在一个 JSON 文件中,路径通常是 settings.json。我们可以用 PowerShell 脚本直接读取和修改它,实现配色方案的批量管理和快捷键自定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 定位 Windows Terminal settings.json 路径
$settingsPath = Join-Path -Path $env:LOCALAPPDATA `
-ChildPath 'Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'

# 如果是 Preview 版本
if (-not (Test-Path $settingsPath)) {
$settingsPath = Join-Path -Path $env:LOCALAPPDATA `
-ChildPath 'Packages\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\LocalState\settings.json'
}

# 备份原始配置
$backupPath = $settingsPath + '.backup'
Copy-Item -Path $settingsPath -Destination $backupPath -Force
Write-Host "已备份配置到: $backupPath"

# 读取并解析 JSON
$settings = Get-Content -Path $settingsPath -Raw | ConvertFrom-Json
Write-Host "当前共有 $(($settings.schemes | Measure-Object).Count) 个配色方案"

执行结果示例:

1
2
已备份配置到: C:\Users\dev\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json.backup
当前共有 24 个配色方案

下面演示如何通过脚本添加自定义配色方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 定义一个新的配色方案
$newScheme = @{
name = 'PowerShell Dark Modern'
background = '#0C0C0C'
foreground = '#CCCCCC'
cursorColor = '#00FF00'
black = '#0C0C0C'
blue = '#0037DA'
cyan = '#3A96DD'
green = '#13A10E'
purple = '#881798'
red = '#C50F1F'
white = '#CCCCCC'
yellow = '#C19C00'
brightBlack = '#767676'
brightBlue = '#3B78FF'
brightCyan = '#61D6D6'
brightGreen = '#16C60C'
brightPurple = '#B4009E'
brightRed = '#E74856'
brightWhite = '#F2F2F2'
brightYellow = '#F9F1A5'
}

# 将哈希表转换为 PSCustomObject 并添加到 schemes 数组
$schemeObj = [PSCustomObject]$newScheme

if (-not $settings.schemes) {
$settings | Add-Member -MemberType NoteProperty -Name 'schemes' -Value @()
}
$settings.schemes += $schemeObj

# 将指定 Profile 的配色方案设置为新建的方案
foreach ($profile in $settings.profiles.list) {
if ($profile.name -match 'PowerShell') {
$profile | Add-Member -MemberType NoteProperty -Name 'colorScheme' `
-Value 'PowerShell Dark Modern' -Force
Write-Host "已为 Profile '$($profile.name)' 应用新配色"
}
}

# 写回 settings.json
$settings | ConvertTo-Json -Depth 10 | Set-Content -Path $settingsPath -Encoding UTF8
Write-Host '配置已保存,重新打开 Terminal 即可看到效果'

执行结果示例:

1
2
3
已为 Profile 'Windows PowerShell' 应用新配色
已为 Profile 'PowerShell 7' 应用新配色
配置已保存,重新打开 Terminal 即可看到效果

在 Profile 中添加实用函数

一个精心定制的终端不仅仅是好看,更要好用。以下是一组可以直接加入 Profile 的实用函数,提升日常操作效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 这段代码演示如何向 Profile 中批量添加实用函数
$functions = @(
@{
Name = 'Get-TerminalVersion'
Code = @'
function Get-TerminalVersion {
<# 获取当前 Windows Terminal 版本 #>
$pkg = Get-AppxPackage *WindowsTerminal*
if ($pkg) {
[PSCustomObject]@{
Name = $pkg.Name
Version = $pkg.Version
Status = '已安装'
}
} else {
Write-Warning '未检测到 Windows Terminal 安装'
}
}
'@
}
@{
Name = 'Export-TerminalSettings'
Code = @'
function Export-TerminalSettings {
<# 导出 Windows Terminal 配置到桌面 #>
$dest = Join-Path $env:USERPROFILE 'Desktop\wt-settings-backup.json'
$src = Join-Path $env:LOCALAPPDATA `
'Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'
if (Test-Path $src) {
Copy-Item -Path $src -Destination $dest -Force
Write-Host "配置已导出到: $dest"
} else {
Write-Warning '未找到 Windows Terminal 配置文件'
}
}
'@
}
@{
Name = 'Set-TerminalOpacity'
Code = @'
function Set-TerminalOpacity {
<# 设置 Terminal 窗口透明度(需要 Terminal 设置中启用亚克力效果)#>
param([int]$Opacity = 80)
$settingsPath = Join-Path $env:LOCALAPPDATA `
'Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json'
$settings = Get-Content $settingsPath -Raw | ConvertFrom-Json
foreach ($p in $settings.profiles.list) {
$p | Add-Member -MemberType NoteProperty -Name 'opacity' `
-Value $Opacity -Force
}
$settings | ConvertTo-Json -Depth 10 | Set-Content $settingsPath -Encoding UTF8
Write-Host "已将所有 Profile 透明度设置为 ${Opacity}%"
}
'@
}
)

# 写入 Profile
$profileFile = $PROFILE.CurrentUserAllHosts
foreach ($func in $functions) {
if (-not (Select-String -Path $profileFile -Pattern "function $($func.Name)" -Quiet)) {
Add-Content -Path $profileFile -Value "`n$($func.Code)"
Write-Host "已添加函数: $($func.Name)"
} else {
Write-Host "函数已存在,跳过: $($func.Name)"
}
}

执行结果示例:

1
2
3
已添加函数: Get-TerminalVersion
已添加函数: Export-TerminalSettings
已添加函数: Set-TerminalOpacity

添加完成后,重新加载 Profile 即可使用这些函数:

1
2
3
4
. $PROFILE.CurrentUserAllHosts

# 测试获取 Terminal 版本
Get-TerminalVersion
1
2
3
Name                            Version        Status
---- ------- ------
Microsoft.WindowsTerminal 1.22.11141.0 已安装

注意事项

  1. 备份配置再修改:Terminal 的 settings.json 是唯一配置来源,修改前务必备份。本文中的脚本会自动创建 .backup 副本,但建议你也定期将配置纳入版本控制。

  2. Oh My Posh 字体依赖:大部分 Oh My Posh 主题需要 Nerd Font 字体才能正确显示图标。推荐安装 CascadiaCodeFiraCode 的 Nerd Font 版本,并在 Terminal 设置中将字体名填入 Profile 的 font.face 字段。

  3. Profile 执行策略:如果系统执行策略禁止运行脚本,Oh My Posh 和自定义函数都不会生效。需要以管理员身份执行 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser 来放行本地脚本。

  4. JSON 序列化深度ConvertTo-Json 默认深度为 2,Terminal 的 settings.json 嵌套较深(特别是 actions 数组),务必使用 -Depth 10 或更高,否则部分配置会丢失。

  5. Preview 和 Stable 版本路径不同:Windows Terminal Preview 版的包名包含 Previewsettings.json 的路径也不同。脚本中应同时检测两个路径,避免修改错目标。

  6. 亚克力效果和透明度需要 GPU 支持useAcrylicopacity 设置依赖 GPU 加速渲染。在虚拟机或远程桌面会话中,这些视觉效果可能无法正常工作,但不影响核心功能使用。

PowerShell 技能连载 - Windows Terminal 与 PowerShell 环境配置

适用于 Windows 10/11,PowerShell 7.0 及以上版本

为什么终端环境如此重要

作为 PowerShell 用户,终端是每天打交道最多的工具。一个配置得当的终端环境不仅能让你心情愉悦,更能显著提升工作效率。试想一下:当你打开终端,迎接你的是清晰的配色、醒目的 Git 状态提示、智能的命令补全,和一系列顺手可用的自定义函数——是不是比面对默认的蓝底白字更有动力?

传统的 Windows PowerShell 5.1 控制台(conhost)功能有限,不支持多标签、缺乏自定义能力。而 Windows Terminal 的出现彻底改变了这一局面:它是开源的、高度可定制的、支持 GPU 加速渲染的现代终端应用。配合 PowerShell 7 和 Oh My Posh,我们可以打造一个不输 macOS/Linux 的终端体验。

本文将从 Windows Terminal 配置、PowerShell 7 Profile 定制、Oh My Posh 美化、PSReadLine 增强以及常用别名函数五个方面,带你一步步搭建理想的终端环境。

Windows Terminal 基础配置

Windows Terminal 的配置存储在一个 JSON 文件中,通过 Ctrl+Shift+, 可以快速打开。以下是一个经过优化的配置片段,涵盖默认配置文件、启动目录、字体和配色方案。

1
2
3
4
5
6
7
8
9
10
11
12
# 查看 Windows Terminal settings.json 的路径
$settingsPath = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
Write-Host "Windows Terminal 配置文件路径: $settingsPath"

# 如果文件存在,读取当前默认配置
if (Test-Path $settingsPath) {
$settings = Get-Content $settingsPath -Raw | ConvertFrom-Json
$defaultProfile = $settings.profiles.list | Where-Object { $_.guid -eq $settings.defaultProfile }
Write-Host "当前默认配置文件: $($defaultProfile.name)"
} else {
Write-Host "未找到 Windows Terminal 配置文件,请确认已安装 Windows Terminal"
}

执行结果示例:

1
2
Windows Terminal 配置文件路径: C:\Users\dev\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
当前默认配置文件: PowerShell 7

settings.json 中,以下几项配置值得优先调整:

  • defaultProfile:设置为 PowerShell 7 的 GUID,确保默认打开的是 PS7
  • startingDirectory:设定为你常用的工作目录
  • font.face:推荐使用 Nerd Font,以支持 Oh My Posh 的图标显示
  • colorScheme:选择一个护眼且对比度适中的配色方案

PowerShell 7 Profile 定制

PowerShell 的 Profile 文件类似于 bash 的 .bashrc,每次启动 PowerShell 时自动执行。PS7 的 Profile 路径与 PS5.1 不同,互不干扰。

1
2
# 查看 PowerShell 7 的所有 Profile 路径
$PROFILE | Format-List -Force

执行结果示例:

1
2
3
4
AllUsersAllHosts       : C:\Program Files\PowerShell\7\profile.ps1
AllUsersCurrentHost : C:\Program Files\PowerShell\7\Microsoft.PowerShell_profile.ps1
CurrentUserAllHosts : C:\Users\dev\Documents\PowerShell\profile.ps1
CurrentUserCurrentHost : C:\Users\dev\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

最常用的是 CurrentUserCurrentHost,即当前用户、当前宿主的 Profile。我们来创建一个基础 Profile,包含环境变量设置和模块导入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 确保 Profile 目录存在
$profileDir = Split-Path $PROFILE -Parent
if (-not (Test-Path $profileDir)) {
New-Item -ItemType Directory -Path $profileDir -Force | Out-Null
Write-Host "已创建 Profile 目录: $profileDir"
}

# 创建初始 Profile 文件
$profileContent = @'
# === 环境变量 ===
$env:EDITOR = "code"
$env:PYTHONIOENCODING = "utf-8"

# === 编码设置 ===
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8

# === 常用模块自动导入 ===
$modulesToImport = @(
"PSReadLine",
"Terminal-Icons"
)

foreach ($mod in $modulesToImport) {
if (Get-Module -ListAvailable -Name $mod) {
Import-Module $mod -ErrorAction SilentlyContinue
}
}

Write-Host "Profile 加载完成 - $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor DarkGray
'@

Set-Content -Path $PROFILE -Value $profileContent -Encoding UTF8
Write-Host "Profile 文件已写入: $PROFILE"

执行结果示例:

1
Profile 文件已写入: C:\Users\dev\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

这段 Profile 做了几件关键的事:统一了编码为 UTF-8(避免中文乱码)、设置了默认编辑器、自动导入常用模块。编码问题是 Windows 下开发最常遇到的坑之一,在 Profile 中统一处理可以省去大量排查时间。

Oh My Posh 终端美化

Oh My Posh 是 Windows 上最流行的终端提示符美化工具,它能为你的终端添加 Git 状态、语言版本、执行时间等信息。配合 Nerd Font,还可以显示丰富的图标。

1
2
3
4
5
6
7
8
9
# 安装 Oh My Posh(推荐通过 winget)
winget install JanDeDobbeleer.OhMyPosh -s winget

# 安装推荐的 Nerd Font
oh-my-posh font install FiraCode

# 查看可用的主题列表
oh-my-posh get shell
Write-Host "可用主题数量: $((oh-my-posh get themes).Count)"

执行结果示例:

1
2
3
4
已成功安装 Oh My Posh
正在安装 FiraCode Nerd Font...
已完成字体安装
可用主题数量: 87

在 Profile 中初始化 Oh My Posh。注意不要在 here-string 中使用三反引号,我们用变量拼接的方式来设置主题路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 将 Oh My Posh 初始化代码添加到 Profile
$ompInit = @'
# === Oh My Posh 初始化 ===
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) {
$ompTheme = Join-Path $env:POSH_THEMES_PATH "jandebuhr.omp.json"
if (-not (Test-Path $ompTheme)) {
$ompTheme = "jandedeurbel"
}
oh-my-posh init pwsh --config $ompTheme | Invoke-Expression
}
'@

# 追加到 Profile 末尾
Add-Content -Path $PROFILE -Value "`n$ompInit" -Encoding UTF8
Write-Host "Oh My Posh 初始化代码已添加到 Profile"

执行结果示例:

1
Oh My Posh 初始化代码已添加到 Profile

Oh My Posh 的主题文件是 JSON 格式,你也可以自定义主题。推荐先用内置主题找到喜欢的风格,再在此基础上微调颜色和段落的显示顺序。一个好主题应该在美观和信息密度之间取得平衡——信息太少不实用,太多则显得杂乱。

常用别名与自定义函数

Profile 中最实用的部分之一就是定义别名和函数,把日常高频操作压缩成简短的命令。以下是笔者常用的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 定义常用别名和函数
$aliasAndFuncs = @'
# === 常用别名 ===
Set-Alias -Name ll -Value Get-ChildItem
Set-Alias -Name which -Value Get-Command
Set-Alias -Name touch -Value New-Item
Set-Alias -Name cat -Value Get-Content

# === 自定义函数 ===

# 快速进入项目目录
function projects {
Set-Location "D:\Projects"
}

# 快速查看端口占用
function port {
param([int]$PortNumber)
Get-NetTCPConnection -LocalPort $PortNumber -ErrorAction SilentlyContinue |
Select-Object LocalPort, OwningProcess, State |
Format-Table -AutoSize
}

# 快速查看系统信息
function sysinfo {
$os = Get-CimInstance Win32_OperatingSystem
$cpu = Get-CimInstance Win32_Processor
$mem = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
OS = $os.Caption
CPU = $cpu.Name
FreeMem_GB = $mem
Uptime = (Get-Date) - $os.LastBootUpTime
} | Format-List
}

# Git 快捷操作
function gs { git status }
function gl { git log --oneline -15 }
function gp { git push }
function gd { git diff $args }

# Docker 快捷操作
function dps { docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}" }
function dex {
param([string]$ContainerName)
docker exec -it $ContainerName /bin/sh
}
'@

Add-Content -Path $PROFILE -Value "`n$aliasAndFuncs" -Encoding UTF8
Write-Host "别名和函数已添加到 Profile"

执行结果示例:

1
别名和函数已添加到 Profile

这些函数的设计原则是”短小精悍”:每个函数只做一件事,名字尽量简短但能望文生义。比如 port 8080 比输入完整的 Get-NetTCPConnection -LocalPort 8080 简洁得多,gs 则是 git status 的经典缩写。你可以根据自己的工作流继续扩展这个列表。

PSReadLine 增强补全

PSReadLine 是 PowerShell 的命令行编辑模块,PS7 已内置 2.x 版本。合理配置后,它能提供类似 fish shell 的自动补全体验——输入时实时预测、历史命令搜索、语法高亮一应俱全。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 配置 PSReadLine
$psreadlineConfig = @'
# === PSReadLine 配置 ===
if ($host.Name -eq 'ConsoleHost') {
# 预测文本来源:历史记录 + 插件
Set-PSReadLineOption -PredictiveSource HistoryAndPlugin
# 预测文本显示方式:列表视图(类似 fish)
Set-PSReadLineOption -PredictiveStyle ListView
# 历史记录去重
Set-PSReadLineOption -HistoryNoDuplicates
# 保存历史记录条数
Set-PSReadLineOption -MaximumHistoryCount 10000
# 历史记录保存路径
Set-PSReadLineOption -HistorySavePath (Join-Path $env:USERPROFILE ".ps_history")
# 编辑模式设为 Emacs(更符合开发习惯)
Set-PSReadLineOption -EditMode Emacs
# 颜色主题
Set-PSReadLineOption -Colors @{
Command = 'Yellow'
Parameter = 'Green'
String = 'Cyan'
Comment = 'DarkGray'
Operator = 'Magenta'
Prediction = 'DarkGray'
InlinePrediction = 'DarkGray'
}

# Ctrl+d 删除字符(类似 bash)
Set-PSReadLineKeyHandler -Chord 'Ctrl+d' -Function DeleteChar
# Ctrl+w 删除前一个单词
Set-PSReadLineKeyHandler -Chord 'Ctrl+w' -Function BackwardKillWord
# 上下箭头在预测列表中导航
Set-PSReadLineKeyHandler -Chord UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Chord DownArrow -Function HistorySearchForward
# Tab 补全显示菜单
Set-PSReadLineKeyHandler -Chord Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Chord Shift+Tab -Function Complete
}
'@

Add-Content -Path $PROFILE -Value "`n$psreadlineConfig" -Encoding UTF8
Write-Host "PSReadLine 配置已添加到 Profile"

执行结果示例:

1
PSReadLine 配置已添加到 Profile

PSReadLine 的预测补全功能是提升效率的关键。当你开始输入命令时,它会根据历史记录实时显示匹配建议,按右箭头即可接受。ListView 模式下还会显示一个下拉列表供你选择,配合 HistoryAndPlugin 来源,补全的准确度非常高。

完整 Profile 模板

经过以上各部分的配置,下面给出一个完整的 Profile 模板,方便你一次性部署。建议按需修改目录路径和主题名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 生成完整 Profile 模板
$templateContent = @'
# ============================================
# PowerShell 7 Profile - 完整模板
# 生成日期: 2025-04-25
# ============================================

# === 编码设置 ===
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8

# === 环境变量 ===
$env:EDITOR = "code"

# === Oh My Posh ===
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) {
$ompTheme = Join-Path $env:POSH_THEMES_PATH "jandebuhr.omp.json"
if (-not (Test-Path $ompTheme)) { $ompTheme = "jandedeurbel" }
oh-my-posh init pwsh --config $ompTheme | Invoke-Expression
}

# === 模块导入 ===
$autoModules = @("Terminal-Icons")
foreach ($m in $autoModules) {
if (Get-Module -ListAvailable -Name $m) {
Import-Module $m -ErrorAction SilentlyContinue
}
}

# === PSReadLine ===
if ($host.Name -eq 'ConsoleHost') {
Set-PSReadLineOption -PredictiveSource HistoryAndPlugin
Set-PSReadLineOption -PredictiveStyle ListView
Set-PSReadLineOption -HistoryNoDuplicates
Set-PSReadLineOption -MaximumHistoryCount 10000
Set-PSReadLineOption -HistorySavePath (Join-Path $env:USERPROFILE ".ps_history")
Set-PSReadLineOption -EditMode Emacs
Set-PSReadLineOption -Colors @{
Command = 'Yellow'
Parameter = 'Green'
String = 'Cyan'
Comment = 'DarkGray'
Prediction = 'DarkGray'
InlinePrediction = 'DarkGray'
}
Set-PSReadLineKeyHandler -Chord UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Chord DownArrow -Function HistorySearchForward
Set-PSReadLineKeyHandler -Chord Tab -Function MenuComplete
}

# === 别名 ===
Set-Alias ll Get-ChildItem
Set-Alias which Get-Command
Set-Alias touch New-Item

# === 自定义函数 ===
function projects { Set-Location "D:\Projects" }
function port([int]$p) { Get-NetTCPConnection -LocalPort $p -ErrorAction SilentlyContinue | Format-Table -AutoSize }
function sysinfo {
$os = Get-CimInstance Win32_OperatingSystem
[PSCustomObject]@{
Computer = $env:COMPUTERNAME
OS = $os.Caption
FreeMemGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
Uptime = (Get-Date) - $os.LastBootUpTime
} | Format-List
}

# === Git 快捷命令 ===
function gs { git status }
function gl { git log --oneline -15 }
function gp { git push }

Write-Host "Profile loaded - $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor DarkGray
'@

# 写入 Profile
$profileDir = Split-Path $PROFILE -Parent
if (-not (Test-Path $profileDir)) {
New-Item -ItemType Directory -Path $profileDir -Force | Out-Null
}
Set-Content -Path $PROFILE -Value $templateContent -Encoding UTF8
Write-Host "完整 Profile 模板已写入: $PROFILE"

执行结果示例:

1
完整 Profile 模板已写入: C:\Users\dev\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

部署完成后,重新打开 Windows Terminal 或执行 . $PROFILE 即可生效。首次加载时 Oh My Posh 会编译主题缓存,之后启动速度很快。如果遇到图标显示为方块,说明 Nerd Font 未正确安装或 Windows Terminal 未配置使用该字体。

注意事项

  1. Profile 加载顺序:Oh My Posh 初始化应放在 PSReadLine 配置之前,否则预测补全的颜色设置可能被覆盖。
  2. Nerd Font 必须在 Windows Terminal 中指定:仅安装字体不够,还需要在 settings.json 的 profile 中设置 "font": { "face": "FiraCode Nerd Font" }
  3. Profile 修改后别忘重载:修改 Profile 后,在当前会话中执行 . $PROFILE 重新加载,避免关闭重开。
  4. 编码一致性:确保 settings.json、Profile 文件和系统区域设置都使用 UTF-8,否则中文可能显示为乱码。
  5. 备份你的配置:建议将 Profile 文件和 settings.json 纳入 Git 管理,换机器时一键恢复。
  6. PSReadLine 插件模式PredictiveSource HistoryAndPlugin 需要安装补全模块(如 CompletionPredictor),如果未安装则回退到纯历史记录模式,不会报错。