XiaowenBlog/source/_posts/PowerShell.md
wenyongda 194861d3e5 docs: 重构PowerShell美化教程,新增Starship支持并调整结构
将原单美化工具教程扩展为同时支持Oh My Posh和Starship的教程,重构文档结构,调整内容排版,并将扩展模块和通用配置移至文档后半部分。
2026-06-03 15:48:39 +08:00

1125 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: PowerShell
date: 2023-10-07 11:25:08
tags: [PowerShell, Windows, Shell, 命令行]
categories: [开发工具, Windows]
---
# PowerShell 7 提示符美化
> PowerShell 有两个主流的提示符美化工具:[Oh My Posh](https://ohmyposh.dev/) 和 [Starship](https://starship.dev/),二者选其一即可。
## 安装 PowerShell 7
`PowerShell 7` 指的不是系统自带的 `powershell` ,而是新下载的(微软官方出品),当然这个教程也适用于系统自带的 `powershell`
微软官方文档地址https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.2
下载地址https://github.com/PowerShell/PowerShell/releases
或者可通过 Winget 方式下载安装
```powershell
winget search --id Microsoft.PowerShell
```
Output
```powershell
Name Id Version Source
---------------------------------------------------------------
PowerShell Microsoft.PowerShell 7.5.4.0 winget
PowerShell Preview Microsoft.PowerShell.Preview 7.6.0.5 winget
```
使用 `--id` 参数安装 PowerShell 或 PowerShell 预览版
```powershell
winget install --id Microsoft.PowerShell --source winget
```
```powershell
winget install --id Microsoft.PowerShell.Preview --source winget
```
## Oh My Posh
官方文档地址https://ohmyposh.dev/
### 安装
最好在管理员模式下运行 `powershell`
下载安装,在 `powershell` 命令行中输入
```powershell
winget install oh-my-posh
```
`powershell` 命令行中输入下面命令,打开 `$Profile` 进行设置,如果系统提示不存文件,是否创建,请点击创建
```powershell
notepad $Profile
```
将以下命令添加到 `$Profile` 文件中
```powershell
oh-my-posh init pwsh | Invoke-Expression
```
应用修改,则直接在命令行中执行 `. $Profile` ,如果出现错误等问题,请尝试关闭所有 `powershell` 命令窗口,重新打开,一般都会正常显示
### 配置环境变量
配置 `POSH_THEMES_PATH` 环境变量,最好配置成系统级别的,路径在 `C:\Users\<当前登录用户>\AppData\Local\Programs\oh-my-posh\themes` 下面。
### 更改主题
`powerShell` 命令行中输入 `Get-ChildItem $env:POSH_THEMES_PATH` 来获取所有的已安装主题
**预览主题(官方推荐方式):** 由于在终端里一次性渲染所有主题会很卡,官方建议直接去网页上看截图,然后记住名字即可。
- **[Oh My Posh 官方主题预览页 (Themes)](https://ohmyposh.dev/docs/themes)**
编辑 `$Profile` 文件
```powershell
notepad $Profile
```
`oh-my-posh init pwsh ...` 的部分後面加上 `--config "$env:POSH_THEMES_PATH/{主題名稱}.omp.json"`
将其内部文字改为:
```powershell
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/montys.omp.json" | Invoke-Expression
```
## Starship
[Starship](https://starship.dev/) 是跨平台的提示符工具,支持 Windows、Linux、macOS。与 Oh My Posh 功能类似,二者选其一即可。
### 安装
```powershell
winget install --id Starship.Starship
```
### 配置文件位置
Windows 下配置文件路径:`~/.config/starship.toml`
```powershell
# 创建配置目录和文件
mkdir -p ~/.config
New-Item -Path ~/.config/starship.toml -ItemType File -Force
# 用 VSCode 打开编辑
code ~/.config/starship.toml
```
### 初始化
`$PROFILE` 文件中添加:
```powershell
# Starship 初始化(必须放最后)
Invoke-Expression (&starship init powershell)
```
### 完整配置Catppuccin Mocha 主题)
将以下内容粘贴到 `starship.toml` 文件中:
```toml
"$schema" = 'https://starship.rs/config-schema.json'
format = """
[](red)\
$os\
$username\
[](bg:peach fg:red)\
$directory\
[](bg:yellow fg:peach)\
$git_branch\
$git_status\
[](fg:yellow bg:green)\
$c\
$rust\
$golang\
$nodejs\
$bun\
$php\
$java\
$kotlin\
$haskell\
$python\
[](fg:green bg:sapphire)\
$conda\
[](fg:sapphire bg:lavender)\
$time\
[ ](fg:lavender)\
$cmd_duration\
$line_break\
$character"""
palette = 'catppuccin_mocha'
[os]
disabled = false
style = "bg:red fg:crust"
[os.symbols]
Windows = ""
Ubuntu = "󰕈"
SUSE = ""
Raspbian = "󰐿"
Mint = "󰣭"
Macos = "󰀵"
Manjaro = ""
Linux = "󰌽"
Gentoo = "󰣨"
Fedora = "󰣛"
Alpine = ""
Amazon = ""
Android = ""
AOSC = ""
Arch = "󰣇"
Artix = "󰣇"
CentOS = ""
Debian = "󰣚"
Redhat = "󱄛"
RedHatEnterprise = "󱄛"
[username]
show_always = true
style_user = "bg:red fg:crust"
style_root = "bg:red fg:crust"
format = '[ $user]($style)'
[directory]
style = "bg:peach fg:crust"
format = "[ $path ]($style)"
truncation_length = 3
truncation_symbol = "…/"
[directory.substitutions]
"Documents" = "󰈙 "
"Downloads" = " "
"Music" = "󰝚 "
"Pictures" = " "
"Developer" = "󰲋 "
[git_branch]
symbol = ""
style = "bg:yellow"
format = '[[ $symbol $branch ](fg:crust bg:yellow)]($style)'
[git_status]
style = "bg:yellow"
format = '[[($all_status$ahead_behind )](fg:crust bg:yellow)]($style)'
[nodejs]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[bun]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[c]
symbol = " "
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[rust]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[golang]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[php]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[java]
symbol = " "
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[kotlin]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[haskell]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
[python]
symbol = ""
style = "bg:green"
format = '[[ $symbol( $version)(\(#$virtualenv\)) ](fg:crust bg:green)]($style)'
[docker_context]
symbol = ""
style = "bg:sapphire"
format = '[[ $symbol( $context) ](fg:crust bg:sapphire)]($style)'
[conda]
symbol = " "
style = "fg:crust bg:sapphire"
format = '[$symbol$environment ]($style)'
ignore_base = false
[time]
disabled = false
time_format = "%R"
style = "bg:lavender"
format = '[[ $time ](fg:crust bg:lavender)]($style)'
[line_break]
disabled = false
[character]
disabled = false
success_symbol = '[](bold fg:green)'
error_symbol = '[](bold fg:red)'
vimcmd_symbol = '[](bold fg:green)'
vimcmd_replace_one_symbol = '[](bold fg:lavender)'
vimcmd_replace_symbol = '[](bold fg:lavender)'
vimcmd_visual_symbol = '[](bold fg:yellow)'
[cmd_duration]
show_milliseconds = true
format = " in $duration "
style = "bg:lavender"
disabled = false
show_notifications = true
min_time_to_notify = 45000
[palettes.catppuccin_mocha]
rosewater = "#f5e0dc"
flamingo = "#f2cdcd"
pink = "#f5c2e7"
mauve = "#cba6f7"
red = "#f38ba8"
maroon = "#eba0ac"
peach = "#fab387"
yellow = "#f9e2af"
green = "#a6e3a1"
teal = "#94e2d5"
sky = "#89dceb"
sapphire = "#74c7ec"
blue = "#89b4fa"
lavender = "#b4befe"
text = "#cdd6f4"
subtext1 = "#bac2de"
subtext0 = "#a6adc8"
overlay2 = "#9399b2"
overlay1 = "#7f849c"
overlay0 = "#6c7086"
surface2 = "#585b70"
surface1 = "#45475a"
surface0 = "#313244"
base = "#1e1e2e"
mantle = "#181825"
crust = "#11111b"
[palettes.catppuccin_frappe]
rosewater = "#f2d5cf"
flamingo = "#eebebe"
pink = "#f4b8e4"
mauve = "#ca9ee6"
red = "#e78284"
maroon = "#ea999c"
peach = "#ef9f76"
yellow = "#e5c890"
green = "#a6d189"
teal = "#81c8be"
sky = "#99d1db"
sapphire = "#85c1dc"
blue = "#8caaee"
lavender = "#babbf1"
text = "#c6d0f5"
subtext1 = "#b5bfe2"
subtext0 = "#a5adce"
overlay2 = "#949cbb"
overlay1 = "#838ba7"
overlay0 = "#737994"
surface2 = "#626880"
surface1 = "#51576d"
surface0 = "#414559"
base = "#303446"
mantle = "#292c3c"
crust = "#232634"
[palettes.catppuccin_latte]
rosewater = "#dc8a78"
flamingo = "#dd7878"
pink = "#ea76cb"
mauve = "#8839ef"
red = "#d20f39"
maroon = "#e64553"
peach = "#fe640b"
yellow = "#df8e1d"
green = "#40a02b"
teal = "#179299"
sky = "#04a5e5"
sapphire = "#209fb5"
blue = "#1e66f5"
lavender = "#7287fd"
text = "#4c4f69"
subtext1 = "#5c5f77"
subtext0 = "#6c6f85"
overlay2 = "#7c7f93"
overlay1 = "#8c8fa1"
overlay0 = "#9ca0b0"
surface2 = "#acb0be"
surface1 = "#bcc0cc"
surface0 = "#ccd0da"
base = "#eff1f5"
mantle = "#e6e9ef"
crust = "#dce0e8"
[palettes.catppuccin_macchiato]
rosewater = "#f4dbd6"
flamingo = "#f0c6c6"
pink = "#f5bde6"
mauve = "#c6a0f6"
red = "#ed8796"
maroon = "#ee99a0"
peach = "#f5a97f"
yellow = "#eed49f"
green = "#a6da95"
teal = "#8bd5ca"
sky = "#91d7e3"
sapphire = "#7dc4e4"
blue = "#8aadf4"
lavender = "#b7bdf8"
text = "#cad3f5"
subtext1 = "#b8c0e0"
subtext0 = "#a5adcb"
overlay2 = "#9399b7"
overlay1 = "#8087a2"
overlay0 = "#6e738d"
surface2 = "#5b6078"
surface1 = "#494d64"
surface0 = "#363a4f"
base = "#24273a"
mantle = "#1e2030"
crust = "#181926"
```
### 切换主题
修改 `palette` 字段即可切换主题:
```toml
# 可选值catppuccin_mocha默认、catppuccin_frappe、catppuccin_latte、catppuccin_macchiato
palette = 'catppuccin_mocha'
```
### 验证配置
```powershell
# 检查 Starship 版本
starship --version
# 测试配置是否正确
starship config
```
## 扩展模块
### PowerShellGet
> [PowerShellGet](https://github.com/PowerShell/PowerShellGet) 是 Windows 平台上的包管理器,主要用于管理 PowerShell 模块,但也支持其他类型的包。
以系统管理员权限打开**PowerShell**终端,执行以下命令:
```powershell
Install-Module -Name PowerShellGet -Force
```
### [posh-git](https://github.com/dahlbyk/posh-git)
> [posh-git](https://github.com/dahlbyk/posh-git)是一款用于 Windows 系统的 PowerShell 扩展模块,它主要为 Git 提供了更加丰富且人性化的命令行界面体验。
以系统管理员权限打开**PowerShell**终端,执行以下命令:
```powershell
PowerShellGet\Install-Module posh-git -Scope CurrentUser -Force
```
### [PSReadLine](https://github.com/PowerShell/PSReadLine)
> [PSReadLine](https://github.com/PowerShell/PSReadLine)用于增强命令行编辑体验的模块,提供语法高亮/命令预测/历史记录管理以及提供了丰富的快捷键和编辑命令。
以系统管理员权限打开**PowerShell**终端,执行以下命令:
```powershell
Install-Module PSReadLine -Force
```
### [PSFzf](https://github.com/kelleymaureen/PSFzf)
> [PSFzf](https://github.com/kelleymaureen/PSFzf) 是 fzf 的 PowerShell 集成模块,提供模糊搜索历史命令和文件功能。
```powershell
# 安装 PSFzf 模块
Install-Module PSFzf -Scope CurrentUser -Force
# 安装 fzf 本体PSFzf 的底层依赖)
winget install junegunn.fzf
```
## 终端增强配置PSReadLine + PSFzf
> 参考:[PowerShell 终端增强配置指南](https://mp.weixin.qq.com/s/DV-T4Tr4KaonFdgutuzhQQ)
### 前置准备
#### 确认 PowerShell 版本
```powershell
$PSVersionTable.PSVersion
```
- 主版本号为 `5` → 使用 **PS5.1 方案**
- 主版本号为 `7` → 使用 **PS7+ 方案**
#### 确认 Profile 文件路径
```powershell
# 查看路径
echo $PROFILE
# 若文件不存在则创建
if (!(Test-Path $PROFILE)) {
New-Item -ItemType File -Path $PROFILE -Force
}
# 用 VSCode 打开编辑
code $PROFILE
```
> PS5.1 的 Profile 路径通常为:`C:\Users\<用户名>\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`
>
> PS7+ 的 Profile 路径通常为:`C:\Users\<用户名>\Documents\PowerShell\Microsoft.PowerShell_profile.ps1`
>
> 两个版本的 Profile **互相独立**,需分别配置。
#### 设置执行策略(如遇权限报错)
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
### 一次性安装依赖
#### PowerShell 7+ 安装依赖
```powershell
# 1. 信任 PSGallery
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
# 2. 安装最新版 PSReadLine
Install-Module PSReadLine -Force -Scope CurrentUser
# 3. 安装 posh-git
Install-Module posh-git -Scope CurrentUser -Force
# 4. 安装 PSFzf
Install-Module PSFzf -Scope CurrentUser -Force
# 5. 安装 fzf 本体
winget install junegunn.fzf
```
#### PowerShell 5.1 安装依赖
```powershell
# 1. 信任 PSGallery
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
# 2. 安装 PSReadLinePS5.1 最高兼容 2.3.x必须指定版本
Install-Module PSReadLine -RequiredVersion 2.3.4 -Force -Scope CurrentUser -SkipPublisherCheck
# 3. 安装 posh-git
Install-Module posh-git -Scope CurrentUser -Force
# 4. 安装 PSFzf
Install-Module PSFzf -Scope CurrentUser -Force
# 5. 安装 fzf 本体
winget install junegunn.fzf
```
### 完整 Profile 配置
#### PowerShell 7+ Profile
将以下内容完整粘贴到 `$PROFILE` 文件中:
```powershell
# ════════════════════════════════════════════════════════════
# PowerShell 7+ Profile
# 功能:动态窗口标题 + 智能自动补全 + Starship 集成
# ════════════════════════════════════════════════════════════
# ── 模块导入 ─────────────────────────────────────────────────
Import-Module PSReadLine
Import-Module posh-git -ErrorAction SilentlyContinue
Import-Module PSFzf -ErrorAction SilentlyContinue
# ── PSReadLine 配置 ──────────────────────────────────────────
# PS7+ 支持 HistoryAndPlugin结合历史和插件两种来源预测
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
# PS7+ 支持 ListView下拉候选列表比 InlineView 更直观)
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadLineOption -MaximumHistoryCount 10000
Set-PSReadLineOption -Colors @{
Command = 'Cyan'
Parameter = 'DarkCyan'
String = 'Yellow'
Operator = 'Magenta'
Variable = 'Green'
Comment = 'DarkGray'
InlinePrediction = 'DarkGray'
ListPrediction = 'DarkCyan'
}
# ── 快捷键绑定 ───────────────────────────────────────────────
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Key Shift+Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Key Ctrl+Spacebar -Function PossibleCompletions
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
Set-PSReadLineKeyHandler -Key Ctrl+r -Function ReverseSearchHistory
# F2 可在 InlineView 和 ListView 之间实时切换PS7+ 专属)
Set-PSReadLineKeyHandler -Key F2 -Function SwitchPredictionView
# ── PSFzf 配置 ───────────────────────────────────────────────
if (Get-Module PSFzf -ErrorAction SilentlyContinue) {
Set-PSFzfOption -PSReadLineChordProvider 'Ctrl+t'
Set-PSFzfOption -PSReadLineChordReverseHistory 'Ctrl+r'
}
# ── WinGet 补全 ──────────────────────────────────────────────
if (Get-Command winget -ErrorAction SilentlyContinue) {
Register-ArgumentCompleter -Native -CommandName winget -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
# PS7+ 推荐显式设置编码,避免中文路径乱码
[Console]::InputEncoding = [System.Text.Utf8Encoding]::new()
[Console]::OutputEncoding = [System.Text.Utf8Encoding]::new()
$word = $wordToComplete.Replace('"', '""')
$ast = $commandAst.ToString().Replace('"', '""')
winget complete --word="$word" --commandline "$ast" --position $cursorPosition |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
}
# ── 动态窗口标题Starship 钩子)────────────────────────────
# Starship 会在每次渲染 Prompt 前自动调用此函数
function Invoke-Starship-PreCommand {
$dirName = Split-Path -Leaf $PWD.Path
$branch = ""
if (Test-Path ".git" -PathType Container) {
try {
$b = git branch --show-current 2>$null
if ($b) { $branch = " [$b]" }
} catch {}
}
$isAdmin = ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole]::Administrator)
$adminTag = if ($isAdmin) { " ⚡ADMIN" } else { "" }
$host.UI.RawUI.WindowTitle = "PS · $dirName$branch$adminTag"
}
# ── PowerToys CommandNotFound ────────────────────────────────
Import-Module -Name Microsoft.WinGet.CommandNotFound
#f45873b3-b655-43a6-b217-97c00aa0db58
# ── Starship 初始化(必须放最后)────────────────────────────
Invoke-Expression (&starship init powershell)
```
#### PowerShell 5.1 Profile
```powershell
# ════════════════════════════════════════════════════════════
# PowerShell 5.1 Profile
# 功能:动态窗口标题 + 智能自动补全 + Starship 集成
# ════════════════════════════════════════════════════════════
# ── 模块导入 ─────────────────────────────────────────────────
Import-Module PSReadLine
Import-Module posh-git -ErrorAction SilentlyContinue
Import-Module PSFzf -ErrorAction SilentlyContinue
# ── PSReadLine 配置 ──────────────────────────────────────────
# PS5.1 仅支持 History不支持 HistoryAndPlugin
Set-PSReadLineOption -PredictionSource History
# PS5.1 仅支持 InlineView不支持 ListView
Set-PSReadLineOption -PredictionViewStyle InlineView
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadLineOption -MaximumHistoryCount 10000
Set-PSReadLineOption -Colors @{
Command = 'Cyan'
Parameter = 'DarkCyan'
String = 'Yellow'
Operator = 'Magenta'
Variable = 'Green'
Comment = 'DarkGray'
InlinePrediction = 'DarkGray'
}
# ── 快捷键绑定 ───────────────────────────────────────────────
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Key Shift+Tab -Function MenuComplete
Set-PSReadLineKeyHandler -Key Ctrl+Spacebar -Function PossibleCompletions
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
Set-PSReadLineKeyHandler -Key Ctrl+r -Function ReverseSearchHistory
# ── PSFzf 配置 ───────────────────────────────────────────────
if (Get-Module PSFzf -ErrorAction SilentlyContinue) {
Set-PSFzfOption -PSReadLineChordProvider 'Ctrl+t'
Set-PSFzfOption -PSReadLineChordReverseHistory 'Ctrl+r'
}
# ── WinGet 补全 ──────────────────────────────────────────────
if (Get-Command winget -ErrorAction SilentlyContinue) {
Register-ArgumentCompleter -Native -CommandName winget -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$word = $wordToComplete.Replace('"', '""')
$ast = $commandAst.ToString().Replace('"', '""')
winget complete --word="$word" --commandline "$ast" --position $cursorPosition |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
}
# ── 动态窗口标题Starship 钩子)────────────────────────────
function Invoke-Starship-PreCommand {
$dirName = Split-Path -Leaf $PWD.Path
$branch = ""
if (Test-Path ".git" -PathType Container) {
try {
$b = git branch --show-current 2>$null
if ($b) { $branch = " [$b]" }
} catch {}
}
$isAdmin = ([Security.Principal.WindowsPrincipal] `
[Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole]::Administrator)
$adminTag = if ($isAdmin) { " ⚡ADMIN" } else { "" }
$host.UI.RawUI.WindowTitle = "PS · $dirName$branch$adminTag"
}
# ── Starship 初始化(必须放最后)────────────────────────────
Invoke-Expression (&starship init powershell)
```
### 功能说明
#### 动态窗口标题
标题由以下三部分拼接而成:
```
PS · <当前目录名> [<Git分支>] <管理员标识>
```
**示例效果:**
| 场景 | 窗口标题 |
|------|----------|
| 普通目录 | `PS · Downloads` |
| Git 仓库 | `PS · my-project [main]` |
| 管理员身份 | `PS · System32 ⚡ADMIN` |
| 管理员 + Git | `PS · infra [feat/deploy] ⚡ADMIN` |
**实现原理:** 利用 Starship 预留的 `Invoke-Starship-PreCommand` 钩子函数,在每次渲染 Prompt 之前执行,与 Starship 完全兼容,无冲突。
#### 自动补全配置
配置分为四个层次,可按需选择叠加:
| 层次 | 功能 | 说明 |
|------|------|------|
| Layer 1 | PSReadLine 历史预测 | 输入部分命令后,灰色文字实时预测完整命令,按 `→` 接受 |
| Layer 2 | Tab 菜单补全 | 按 `Tab` 弹出候选菜单,上下键选择,`Enter` 确认 |
| Layer 3 | posh-git 补全 | 为 `git` 命令提供子命令、分支名、远程名等补全 |
| Layer 4 | PSFzf 模糊搜索 | `Ctrl+R` 调出交互式历史命令搜索窗口,支持模糊匹配 |
### 快捷键速查
| 快捷键 | 功能 | PS5.1 | PS7+ |
|--------|------|-------|------|
| `→` | 接受行内预测 | ✅ | ✅ |
| `Tab` | 菜单补全,循环切换候选 | ✅ | ✅ |
| `Shift+Tab` | 反向切换候选 | ✅ | ✅ |
| `Ctrl+Space` | 显示所有候选项 | ✅ | ✅ |
| `↑ / ↓` | 按前缀过滤历史记录 | ✅ | ✅ |
| `Ctrl+R` | fzf 模糊历史搜索 | ✅ | ✅ |
| `Ctrl+T` | fzf 模糊文件查找 | ✅ | ✅ |
| `F2` | 切换 InlineView / ListView | ❌ | ✅ |
### 版本功能对照
| 功能 | PS5.1 | PS7+ | 说明 |
|------|-------|------|------|
| `PredictionSource History` | ✅ | ✅ | 基于历史命令预测 |
| `PredictionSource HistoryAndPlugin` | ❌ | ✅ | 额外加入插件预测源 |
| `PredictionViewStyle InlineView` | ✅ | ✅ | 行内灰字预测 |
| `PredictionViewStyle ListView` | ❌ | ✅ | 下拉候选列表 |
| `F2` 切换预测视图 | ❌ | ✅ | 实时切换两种视图 |
| PSReadLine 最高版本 | 2.3.x | 最新版 | 安装时需注意 |
| posh-git | ✅ | ✅ | 版本一致 |
| PSFzf | ✅ | ✅ | 版本一致 |
| WinGet 补全 | ✅ | ✅ | 编码处理略有差异 |
| Starship 钩子 | ✅ | ✅ | 函数名一致 |
| 动态窗口标题 | ✅ | ✅ | 实现方式一致 |
> PS5.1 缺少的 `ListView` 和 `HistoryAndPlugin` 可通过 PSFzf 的 `Ctrl+R` 模糊搜索弥补,日常体验差距不大。
### 常见问题
#### 执行 `. $PROFILE` 报执行策略错误
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
#### 模块安装报 NuGet 错误
```powershell
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
```
#### PSReadLine 安装后不生效
PS5.1 系统自带一个旧版 PSReadLine新版安装在用户目录下需确认加载的是新版
```powershell
Get-Module PSReadLine | Select-Object Name, Version, Path
# Path 应包含 CurrentUser 路径,而非 System32
```
如果仍加载旧版,在 Profile 最顶部显式指定:
```powershell
Remove-Module PSReadLine -ErrorAction SilentlyContinue
Import-Module PSReadLine -RequiredVersion 2.3.4
```
#### fzf / PSFzf 的 Ctrl+R 不弹出窗口
确认 fzf 本体已安装且在 PATH 中:
```powershell
fzf --version
```
如果命令不存在,重新安装并重启终端:
```powershell
winget install junegunn.fzf
```
#### 窗口标题不更新
确认 `Invoke-Starship-PreCommand` 函数定义在 `Invoke-Expression (&starship init powershell)` **之前**,因为 Starship init 会注册对该钩子的调用,函数本身需要提前存在。
#### posh-git 导致启动变慢
posh-git 在大型仓库中可能扫描较慢,可设置跳过未跟踪文件统计:
```powershell
$GitPromptSettings.EnableFileStatus = $false
```
## 编辑oh-my-posh配置文件
打开**PowerShell**终端,执行以下命令编辑配置文件 `code $PROFILE`
```powershell
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete #Tab键会出现自动补全菜单
Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward #上下方向键箭头,搜索历史中进行自动补全
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/jandedobbeleer.omp.json" | Invoke-Expression
Import-Module posh-git # git的自动补全
```
# 文件
## 新建文件
```powershell
New-Item <文件名>.<扩展名后缀>
New-Item my.ini
```
## 删除文件
```powershell
Remove-Item <文件名>.<扩展名后缀>
Remove-Item my.ini
```
## 对文件添加内容
```powershell
Set-Content <文件名>.<扩展名后缀> -value "<内容>"
Set-Content my.ini -value ""
```
## 新建文件夹
```powershell
New-Item data -ItemType Directory
```
# 目录
# 查询版本
```powershell
$PSVersionTable
```
在输出的信息中,查看 **`PSVersion`** 这一行。
**示例输出解读:**
- **Major**: 主版本号(如 5 或 7
- **Minor**: 次版本号。
- 如果显示 `5.1.xxxxx`,这是 Windows 自带的 **Windows PowerShell**
- 如果显示 `7.x.x`,这是跨平台的 **PowerShell (Core)**
仅查看版本号(简洁)
如果你不需要其他详细信息,只想看版本号,可以使用这个命令:
```powershell
$PSVersionTable.PSVersion
```
或者使用宿主查询命令(虽然通常一致,但在某些特殊宿主环境下可能不同):
```powershell
(Get-Host).Version
```
从 CMD (命令提示符) 查看
如果你当前在 CMD 窗口,不想进入 PowerShell 也能查看:
```powershell
powershell -command "$PSVersionTable.PSVersion"
```
### 补充说明:常见的两个主要版本
- **Windows PowerShell 5.1**:这是 Windows 10 和 Windows 11 默认自带的版本(蓝色背景图标)。微软已不再为其开发新功能,仅进行维护。
- **PowerShell 7.x**:这是微软目前主推的跨平台版本(黑色背景图标),性能更强,功能更多。
# 做 sudo 命令
在Windows系统上sudo对应的就是管理员权限了。
一般使用Powershell时并不会管理员启动当执行需要权限的命令比如net start mysql就需要以管理员打开新的窗口。
为了一步到位这里给powershell创建一个`alias` -> `sudo` 来运行需要管理员权限的命令。
在文档目录中(在`powershell`执行`$profile`即可输出此文件路径),新建文件夹`WindowsPowerShell`,新建文件`Microsoft.PowerShell_profile.ps1`
> 此文件是在启动Powershell时执行的脚本。set-alias 在退出后就会失效,所以放到启动脚本中。
追加如下代码,**然后重启Powershell窗口。**
```text
function _sudo {
$ss = "$args ; pause"
Start-Process powershell -Verb runAs -ArgumentList $ss
}
set-alias -name sudo -value _sudo
```
保存后发现无法加载,因为默认不加载外部脚本,管理员权限下 powershell 运行:
```text
set-ExecutionPolicy RemoteSigned
```
# 实用脚本
## 自动延长VS社区版过期时间
> 该脚本作用为 自动检查VS社区版是否在一天内过期如是则自动延长30天
>
> 需事先从Github上Clone开源项目[beatcracker/VSCELicense: PowerShell module to get and set Visual Studio Community Edition license expiration date in registry (github.com)](https://github.com/beatcracker/VSCELicense)
>
> 然后放置在指定目录,并解除脚本执行限制,以管理员身份执行如下命令:
>
> ```powershell
> Set-ExecutionPolicy RemoteSigned
> ```
>
> 输入 A 即可
```powershell
# 加载 VSCELicense 模块
try {
Import-Module -Name 'C:\VSCELicense\VSCELicense.psd1' -ErrorAction Stop
} catch {
Write-Error "无法加载模块 'C:\VSCELicense\VSCELicense.psd1',请确认路径是否正确。错误信息: $_"
exit 1
}
# 获取许可证信息
try {
$output = Get-VSCELicenseExpirationDate -ErrorAction Stop | Out-String
} catch {
Write-Error "执行 Get-VSCELicenseExpirationDate 时出错: $_"
exit 1
}
# 使用正则表达式提取版本号和过期日期
$version = $null
$expDateStr = $null
if ($output -match '(?m)^\s*(\d{4})\s+(\d{2}/\d{2}/\d{4}\s+\d{2}:\d{2}:\d{2})') {
$version = $matches[1].Trim()
$expDateStr = $matches[2].Trim()
Write-Host "找到版本: $version"
Write-Host "过期日期: $expDateStr"
} else {
Write-Error "无法从输出中找到版本和过期日期"
exit 1
}
# 将过期日期字符串解析为 DateTime 对象
try {
$expirationDate = [datetime]::ParseExact($expDateStr, 'dd/MM/yyyy HH:mm:ss', $null)
} catch {
Write-Error "日期格式解析失败: $expDateStr. 错误: $_"
exit 1
}
# 获取当前时间并设置阈值
$currentTime = Get-Date
$threshold = $currentTime.AddDays(1)
Write-Host "当前时间: $currentTime"
Write-Host "过期时间: $expirationDate"
Write-Host "阈值时间(当前时间 + 1天: $threshold"
# 判断是否在1天内过期 -le 表示小于等于 想起了 Mybatis-Plus 条件构造器中的 le
if ($expirationDate -le $threshold) {
Write-Host "许可证即将过期,正在执行 Set-VSCELicenseExpirationDate 命令..."
try {
Set-VSCELicenseExpirationDate -Version $version -ErrorAction Stop
Write-Host "Set-VSCELicenseExpirationDate 命令执行成功。"
} catch {
Write-Error "执行 Set-VSCELicenseExpirationDate 时出错: $_"
exit 1
}
} else {
Write-Host "许可证未在一天内过期,无需操作。"
}
```
输出如下:
![image-20250718112238088](https://rustfs.wenyongdalucky.club:443/hexo/image-20250718112238088.png)
可结合任务计划程序进行使用,免去手动执行的烦恼
![image-20250718142611106](https://rustfs.wenyongdalucky.club:443/hexo/image-20250718142611106.png)
### 🧩 步骤 1打开任务计划程序
1. 按下 `Win + R`,输入 `taskschd.msc`,回车。
2. 在左侧的“任务计划程序库”中,右键选择“创建任务”。
### 🧩 步骤 2设置任务基本信息
- 常规
选项卡:
- 名称:例如 `Check-VS-LicenseExpiration`
- 描述(可选):每天早上 7 点检查许可证过期状态
- 勾选“不管用户是否登录都要运行”
- 勾选“使用最高权限”
![image-20250718142545538](https://rustfs.wenyongdalucky.club:443/hexo/image-20250718142545538.png)
### 🧩 步骤 3设置触发器
1. 切换到 **触发器** 选项卡。
2. 点击 **新建**
3. 设置:
- 开始时间:`07:00:00`
- 每天
- 勾选“启用此触发器”
4. 点击 **确定**
![image-20250718142556458](https://rustfs.wenyongdalucky.club:443/hexo/image-20250718142556458.png)
### 🧩 步骤 4设置操作
1. 切换到 **操作** 选项卡。
2. 点击 **新建**
3. 设置:
- 操作:`启动程序`
- 程序/脚本:`powershell.exe`
- 参数(可选):`-ExecutionPolicy RemoteSigned -File "C:\VSCELicense\Check-VS-LicenseExpiration.ps1`
- 起始于(可选):`C:\VSCELicense`(确保路径正确)
> ✅ **说明**
>
> - `-ExecutionPolicy RemoteSigned`:允许本地脚本运行,避免执行策略限制。
> - `"C:\VSCELicense\Check-VS-LicenseExpiration.ps1"`:替换为你实际的脚本路径。
> - 如果脚本路径包含空格,请用双引号包裹。
### 🧩 步骤 5设置条件可选
1. 切换到 **条件** 选项卡。
2. 可以取消勾选“只有在计算机使用交流电源时才启动此任务”,确保任务在任何电源模式下都能运行。
### 🧩 步骤 6设置设置可选
1. 切换到 **设置** 选项卡。
2. 勾选“如果任务失败,按以下频率重新启动”并设置时间间隔(如每 1 分钟)。
3. 勾选“如果任务运行时间超过以下时间,则停止任务”并设置合理时间(如 1 小时)。
### 🧩 步骤 7保存任务
1. 点击 **确定**
2. 如果弹出用户账户控制UAC提示输入管理员凭据确认。