Zhang's Notes

WindowsDeveloperConfig:用一套 PowerShell 脚本快速配置 Windows 开发环境

cover

图片来自 https://www.pexels.com/zh-cn/photo/4709286/

TLDR : Read here


最近看到微软的 WindowsDeveloperConfig 项目,感觉它比较适合重新安装 Windows 之后使用。

它做的事情其实很直接:

把一台刚安装好的 Windows 11,配置成一台可以直接开始写代码的开发机。

它不只是安装几个软件,而是把 开发工具、Windows 系统设置、Windows Terminal、PowerShell、字体、GitHub Copilot、WSL + Ubuntu 一起处理掉。

而且它不是简单地执行一遍命令。

整个流程设计成了:

  • 已经安装的东西不重复安装
  • 已经修改好的设置不重复修改
  • 某一步失败可以继续重跑
  • WSL 安装需要重启时,可以自动保存进度
  • 重启登录后可以继续执行
  • 生产版本的 PowerShell 脚本带 Microsoft Authenticode 签名验证
  • 最后会给出哪些项目修改了、哪些已经正常、哪些失败的汇总

目前仓库的 windows-dev-config 已经是一个相对完整的 PowerShell 自动化安装器,而不是单独的一份配置文件。微软官方文档也把 Windows Developer Config 定义为用于将全新 Windows 配置成开发环境的一套开源配置。(GitHub )


一、先说它到底会做什么

如果直接运行 Full 配置,它大概会按照下面的顺序执行:

text
准备环境
    ↓
PowerShell 7
    ↓
WinGet
    ↓
安装开发软件
    ↓
Windows 系统设置
    ↓
文件资源管理器
    ↓
任务栏 / 开始菜单 / 搜索
    ↓
Edge
    ↓
开发字体
    ↓
Windows Terminal
    ↓
PowerShell Profile
    ↓
GitHub Copilot
    ↓
WSL + Ubuntu
    ↓
重启
    ↓
自动恢复

当前源码把整个过程拆成了 11 个 phase,每一个 phase 对应 steps/ 下面的一个 PowerShell 文件。dev-config.ps1 负责按照固定顺序加载和执行这些 phase。


二、它并不是“无脑执行命令”

这个项目比较值得看的地方,其实是它的执行方式。

普通的安装脚本一般是:

powershell
安装 A
安装 B
修改 C
修改 D

如果执行到 C 的时候失败了,通常只能重新跑一遍。

WindowsDeveloperConfig 则给每一个操作定义了:

text
Check
Apply
Verify

也就是:

text
检查
 ↓
需要修改?
 ↓
执行修改
 ↓
再次检查
 ↓
确认真的成功

例如安装 VS Code。

逻辑不是:

powershell
winget install vscode

然后就认为成功。

而是先检查:

text
VS Code 是否已经安装?
    ↓
是 → already OK
    ↓
否
    ↓
执行安装
    ↓
再次检查
    ↓
确认安装成功

如果执行成功,但是后面的检查发现仍然没有达到目标状态,它会把这个步骤视为失败,而不是简单打印一个“安装成功”。

这个逻辑由:

text
steps/_step-runner.ps1

统一实现。

所以它具备一个比较重要的特点:

重复执行是安全的。


三、入口脚本怎么工作

整个项目最外面的入口是:

text
bootstrap.ps1

它负责的事情不是安装 VS Code、Git 之类的软件。

它更像一个“安装器”。

执行:

powershell
irm https://raw.githubusercontent.com/microsoft/WindowsDeveloperConfig/main/src/windows-dev-config/bootstrap.ps1 | iex

之后,Bootstrap 会:

  1. 解析指定的 branch/tag/commit
  2. 检查当前是不是管理员
  3. 如果不是,则请求 UAC
  4. 下载对应版本的项目
  5. 验证脚本签名
  6. 把脚本安装到:
text
%ProgramData%\CalmOS
  1. 检查安装目录权限
  2. 启动真正的:
text
dev-config.ps1

也就是说:

text
网络上的 bootstrap.ps1
        ↓
验证
        ↓
下载整个项目
        ↓
安装到 %ProgramData%\CalmOS
        ↓
dev-config.ps1
        ↓
真正开始配置电脑

这样做还有一个好处:

WSL 重启以后,脚本还存在。

所以它不是运行一个临时 PowerShell,然后重启以后就找不到东西了。


四、Full、Partial 和 Uninstall

dev-config.ps1 支持三个 Action:

powershell
-Action Full
-Action Partial
-Action Uninstall

Full

完整配置。

包括:

  • 软件
  • Windows 设置
  • Edge
  • Explorer
  • Terminal
  • PowerShell
  • Copilot
  • WSL
  • Ubuntu

Partial

可以理解成比较克制的标准配置。

它会跳过:

  • Sudo
  • Developer Mode
  • Remote Desktop
  • Edge Policies
  • Explorer 推荐/云文件
  • 全局通知关闭
  • Bluetooth 托盘图标
  • Web Search
  • Search Highlights
  • Widgets
  • WinUI Templates

但仍然会安装 WinUI Copilot Plugin。(GitHub )

Uninstall

这个就不是“恢复到你安装 Windows 时的状态”。

它会主动:

  • 删除 Ubuntu
  • 卸载 WSL
  • 删除安装的软件
  • 重置它修改过的注册表设置
  • 删除 Terminal 中它添加的配置
  • 删除 Oh My Posh 配置
  • 删除 WinUI 模板
  • 删除 Copilot Plugin

而且 Ubuntu 的删除是:

powershell
wsl --unregister Ubuntu

所以 Ubuntu 里面的数据也会被删除。(GitHub )


五、Packages:它到底装了什么

软件安装主要集中在:

text
steps/packages.ps1

目前脚本中的主要软件包括:

软件WinGet ID作用
Windows TerminalMicrosoft.WindowsTerminal终端
Intelligent TerminalMicrosoft.IntelligentTerminalIntelligent Terminal
PowerShell 7Microsoft.PowerShell新版 PowerShell
GitGit.GitGit
GitHub CLIGitHub.cligh
Azure CLIMicrosoft.AzureCLIAzure 命令行
GitHub Copilot CLIGitHub.CopilotCopilot CLI
VS CodeMicrosoft.VisualStudioCode编辑器
.NET SDK 10Microsoft.DotNet.SDK.10.NET 开发
Python 3.14Python.Python.3.14Python
Visual C++ RedistributableMicrosoft.VCRedist.2015+.*VC++ Runtime
uvastral-sh.uvPython 包/环境管理
Node.js LTSOpenJS.NodeJS.LTSNode.js
nvm for WindowsCoreyButler.NVMforWindowsNode 版本管理
CoreutilsMicrosoft.CoreutilsWindows 下的 Unix 工具
Oh My PoshJanDeDobbeleer.OhMyPoshPowerShell Prompt
Windows App CLIMicrosoft.WinAppCliWindows App 开发
PowerToysMicrosoft.PowerToysWindows 工具集

这里有一点比较重要:

它不是简单判断“有没有安装”。

当前逻辑会判断软件是否已经是当前版本,如果 WinGet 认为有更新,也可能在重新运行时处理更新。

所以它更接近:

text
确保开发环境达到目标状态

而不是:

text
安装一次软件

六、系统设置

系统级设置在:

text
steps/registry-system.ps1

目前 Full 模式主要包括:

Sudo

启用 Windows Sudo:

text
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo

设置:

text
Enabled = 3

也就是启用 inline 模式。

Developer Mode

启用:

text
Developer Mode

对应:

text
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock

Long Paths

开启 Win32 长路径:

text
LongPathsEnabled = 1

这对于开发环境还是比较实用的。

尤其是:

text
node_modules

或者一些层级比较深的项目目录。

Remote Desktop

Full 模式还会把:

text
Remote Desktop

打开。

对应:

text
fDenyTSConnections = 0

脚本注释也特别说明了:RDP 防火墙规则还需要另外处理。

Partial 模式只保留:

text
LongPaths

七、文件资源管理器

文件资源管理器对应:

text
steps/registry-explorer.ps1

它做的事情比较符合程序员的使用习惯。

默认会:

text
显示文件扩展名
显示隐藏文件
标题栏显示完整路径
打开 Explorer 时进入“此电脑”
关闭常用文件夹
关闭最近文件
关闭推荐/云文件
关闭同步提供商提示
配置 Details Pane

例如:

text
HideFileExt = 0

表示显示:

text
main.kt

而不是:

text
main

隐藏文件也会打开。

另外,它还通过 Windows Shell API 处理部分 Explorer 显示状态,不完全依赖注册表。


八、任务栏、搜索和开始菜单

对应:

text
steps/registry-taskbar-search.ps1

主要包括:

text
关闭通知
隐藏 Bluetooth 托盘图标
启用任务栏右键 End Task
关闭开始菜单 / Search Web Search
关闭 Search Highlights
关闭 Start 推荐
关闭 Start 账户通知
关闭 Widgets

例如:

text
TaskbarEndTask = 1

这样右键任务栏程序的时候可以直接看到:

text
End task

这对于开发时某些卡死程序比较方便。

Partial 模式只保留:

text
EndTask
StartRecommendations
StartAccountNotifications

其它项目会跳过。


九、Microsoft Edge

对应:

text
steps/edge.ps1

实际上只有两个设置:

text
NewTabPageLocation = about:blank

以及:

text
HideFirstRunExperience = 1

也就是:

  • 新标签页使用空白页
  • 不显示 Edge 第一次运行引导

这部分只存在于 Full 配置,Partial 会直接跳过整个 Edge phase。


十、字体

对应:

text
steps/fonts.ps1

这里不是直接调用 Windows 自带字体安装功能,而是从 Microsoft 的 Cascadia Code Release 下载:

text
CascadiaCodeNF.ttf
CascadiaMonoNF.ttf

当前固定版本:

text
2407.24

并且脚本里写死了 SHA-256:

text
E67A68EE3386DB63F48B9054BD196EA752BC6A4EBB4DF35ADCE6733DA50C8474

下载完成之后会:

  1. 校验 SHA-256
  2. 解压字体
  3. 放到 Windows Fonts
  4. 写入字体注册表
  5. 删除可能存在的旧用户字体副本

最后把 Windows Terminal 默认字体设置成:

text
Cascadia Mono NF

所以这一部分实际上是:

text
下载字体
 ↓
校验文件
 ↓
安装字体
 ↓
注册字体
 ↓
Terminal 使用 Cascadia Mono NF

而不是简单地“下载一个 ttf”。


十一、Windows Terminal

对应:

text
steps/terminal.ps1

主要做两个事情。

1. 开启深色模式

修改:

text
AppsUseLightTheme = 0
SystemUsesLightTheme = 0

2. PowerShell 7 设置为默认 Terminal Profile

它会读取:

text
settings.json

然后找到 PowerShell 7 Profile,把:

text
defaultProfile

指向 PowerShell 7。

这里项目还专门写了 Terminal 的公共处理代码,因为 settings.json 实际上比较复杂。


十二、PowerShell Profile

对应:

text
steps/powershell-profile.ps1

作用非常简单:

给 PowerShell 7 加 Oh My Posh。

它会找到:

text
$PROFILE

然后加入:

powershell
oh-my-posh init pwsh

同时设置:

text
InputEncoding = UTF-8
OutputEncoding = UTF-8

所以装完以后,PowerShell 7 的命令行提示符会使用 Oh My Posh,并且中文输入输出编码也会处理。


十三、GitHub Copilot

对应:

text
steps/copilot.ps1

这里实际上做了四件事情。

1. Windows Terminal 增加 Copilot Profile

创建:

text
%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\DevConfig

然后增加:

text
GitHub Copilot

Profile。

它实际执行:

text
pwsh.exe -NoExit -Command "copilot"

所以打开 Windows Terminal 后,Profile 下拉菜单里会多一个:

text
GitHub Copilot

2. 安装 WinUI Templates

执行:

text
dotnet new install Microsoft.WindowsAppSDK.WinUI.CSharp.Templates

这样:

text
dotnet new

就可以使用对应的 WinUI 模板。

3. 添加微软的 Copilot Skills Marketplace

执行:

text
copilot plugin marketplace add microsoft/win-dev-skills

4. 安装 WinUI Plugin

执行:

text
copilot plugin install winui@win-dev-skills

这几个操作都是 BestEffort。

也就是说,即使 Copilot 网络访问失败,也不会因此把整个 Windows 开发环境安装流程直接终止。


十四、WSL + Ubuntu

最后一个 phase:

text
steps/wsl.ps1

故意放在最后。

原因很简单:

WSL 安装可能要求 Windows 重启。

如果把 WSL 放在前面,那么后面的软件和配置可能都要等重启之后才能继续。

所以项目的顺序是:

text
所有普通配置
        ↓
最后安装 WSL
        ↓
需要重启
        ↓
恢复执行

WSL 部分会:

安装 WSL Platform

首先尝试:

powershell
wsl --install --no-distribution

如果失败,则直接使用:

text
VirtualMachinePlatform
Microsoft-Windows-Subsystem-Linux

两个 Windows Optional Features。

如果 WSL 版本比较旧,还会执行:

powershell
wsl --update

安装 Ubuntu

默认发行版:

text
Ubuntu

安装:

powershell
wsl --install -d Ubuntu --no-launch

如果 Microsoft Store 路径失败,则尝试:

powershell
wsl --install -d Ubuntu --no-launch --web-download

而且不会自动启动 Ubuntu。

所以最后你还需要自己打开一次 Ubuntu,创建 Linux 用户名和密码。


十五、为什么重启以后还能继续?

这是这个项目里我觉得比较有意思的一部分。

它会创建:

text
WindowsDevConfigResume

Scheduled Task。

重启之前,把进度保存到:

text
devconfig-tally.json

然后:

text
注册登录任务
 ↓
保存当前进度
 ↓
10 秒倒计时
 ↓
shutdown /r
 ↓
Windows 重启
 ↓
用户重新登录
 ↓
Scheduled Task 启动
 ↓
再次请求 UAC
 ↓
继续执行

而不是重新从头执行。

_reboot-resume.ps1 负责的就是这套机制。


十六、为什么它敢直接从 GitHub 下载 PowerShell?

因为还有一层:

text
steps/_security.ps1

这个脚本会检查:

  • 文件是不是安全目录
  • 有没有 Junction / Symbolic Link
  • 目录是不是 Administrator/SYSTEM 所有
  • 普通用户能不能修改安装文件
  • .ps1 是否具有 Microsoft Corporation 的 Authenticode 签名

生产模式下,如果签名不对,会直接停止。

所以整个流程不是:

text
curl | powershell

然后下载什么就执行什么。

实际上是:

text
下载
 ↓
验证
 ↓
检查目录权限
 ↓
检查 Microsoft 签名
 ↓
安装到受保护目录
 ↓
再次验证
 ↓
执行

这也是为什么官方特别强调:

text
- AllowUnsigned

只应该用于开发/测试。


十七、整个项目最核心的几个脚本

如果不看细节,其实可以把整个项目理解成:

text
bootstrap.ps1
    │
    │ 负责下载、签名、安全目录、UAC
    ↓
dev-config.ps1
    │
    │ 负责调度
    │
    ├── prerequisites.ps1
    ├── packages.ps1
    ├── registry-system.ps1
    ├── registry-explorer.ps1
    ├── registry-taskbar-search.ps1
    ├── edge.ps1
    ├── fonts.ps1
    ├── terminal.ps1
    ├── powershell-profile.ps1
    ├── copilot.ps1
    └── wsl.ps1
             │
             ↓
       _*.ps1 公共函数

所以真正的核心不是某一个安装命令。

而是:

text
bootstrap
+
orchestrator
+
phase
+
step runner
+
helper

这也是这个项目比较适合拿来研究的地方。


十八、最后:每一个脚本到底有什么区别

这一部分直接列出来,方便以后自己看源码。

根目录脚本

脚本作用实际操作
bootstrap.ps1远程入口下载项目、UAC、签名验证、创建安全安装目录、启动 dev-config.ps1
setup-full.ps1Full 快捷入口验证 Bootstrap,然后以 Full 模式启动
setup-standard.ps1Partial 快捷入口验证 Bootstrap,然后以 Partial 模式启动
uninstall.ps1卸载入口验证 Bootstrap,然后以 Uninstall 模式启动
dev-config.ps1总调度器加载所有 phase、控制执行顺序、日志、锁、重启恢复、最终汇总

bootstrap.ps1 是真正的安装入口,而三个 setup-*.ps1 基本只是固定 Action 的安全包装器;真正干活的是 dev-config.ps1。


steps/ 里的实际配置脚本

脚本主要操作
prerequisites.ps1安装/确认 PowerShell 7,准备 WinGet
packages.ps1使用 WinGet 安装/卸载开发软件
registry-system.ps1Sudo、Developer Mode、Long Paths、Remote Desktop
registry-explorer.ps1文件扩展名、隐藏文件、完整路径、Explorer 首页、最近/常用文件等
registry-taskbar-search.ps1通知、Bluetooth 图标、End Task、搜索、Start 推荐、Widgets
edge.ps1Edge 空白新标签页、关闭首次运行体验
fonts.ps1下载并安装 Cascadia Code Nerd Fonts,配置 Terminal 字体
terminal.ps1深色主题、PowerShell 7 默认 Profile
powershell-profile.ps1PowerShell 7 加入 Oh My Posh
copilot.ps1Copilot Terminal Profile、WinUI 模板、win-dev-skills Marketplace、WinUI Plugin
wsl.ps1WSL、VirtualMachinePlatform、Ubuntu、重启恢复,以及卸载

这些文件基本都是“一文件对应一个配置阶段”,dev-config.ps1 会按照固定顺序执行它们。


steps/_*.ps1 公共辅助脚本

这些文件不是独立的配置阶段,而是给上面的脚本提供公共函数。

脚本负责什么
_security.ps1Microsoft 签名验证、目录权限检查、阻止不安全目录/Junction
_step-runner.ps1Check → Apply → Verify 核心执行框架、统计成功/跳过/失败
_elevation.ps1管理员权限、UAC、单实例锁、非管理员任务执行
_reboot-resume.ps1注册重启恢复任务、保存进度、重启 Windows
_registry.ps1注册表读取、写入、Reset
_environment.ps1PATH 刷新、TLS、进程执行、超时、UTF-8 文件读写
_retry.ps1网络/安装操作失败后的重试和指数退避
_terminal.ps1Windows Terminal settings.json 的读取、修改、备份
_winget.ps1WinGet 模块/CLI、软件查询、安装、卸载、更新
_console.ps1日志、Transcript、结束时等待按键
_pwsh-bootstrap.ps1在 Windows PowerShell 5.1 下安装并切换到 PowerShell 7

这些辅助脚本共同解决的是“怎么可靠地执行配置”,而不是“配置什么”。


十九、如果只记住一句话

WindowsDeveloperConfig 可以简单理解成:

text
bootstrap.ps1
    = 下载和安全启动

dev-config.ps1
    = 总调度

steps/*.ps1
    = 每一类具体配置

steps/_*.ps1
    = 所有配置共用的基础设施

step-runner
    = 检查 → 修改 → 再检查

reboot-resume
    = 重启以后接着干

它真正有价值的地方,其实不在于“帮你安装了 VS Code、Git、Python”。

这些事情自己执行几个 winget install 也能做到。

比较值得借鉴的是它把一个 Windows 初始化脚本做成了一个可以重复执行、可以验证结果、可以失败重试、可以跨重启恢复、还有签名和权限保护的配置系统。

对于经常重装 Windows、需要维护多台开发机,或者自己想写一套 Windows 初始化脚本的人,这个项目的结构比单纯复制几条 winget install 命令更值得参考。微软官方仓库目前也明确把它定位为面向 Windows 开发机的可重复、经过 CI 测试的自动化配置方案。(GitHub )

项目地址: Microsoft / WindowsDeveloperConfig