-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathwindows-setup.bat
More file actions
352 lines (285 loc) · 9.91 KB
/
Copy pathwindows-setup.bat
File metadata and controls
352 lines (285 loc) · 9.91 KB
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
@echo off
mode con cp select=437 >nul
rem 还原 setup.exe
rename X:\setup.exe.disabled setup.exe
rem 等待 10 秒才自动安装
cls
for /l %%i in (10,-1,1) do (
echo Press Ctrl+C within %%i seconds to cancel the automatic installation.
call :sleep 1000
cls
)
rem win7 find 命令在 65001 代码页下有问题,仅限 win 7
rem findstr 就正常,但安装程序又没有 findstr
rem echo a | find "a"
rem 使用高性能模式
rem https://learn.microsoft.com/windows-hardware/manufacture/desktop/capture-and-apply-windows-using-a-single-wim
rem win8 pe 没有 powercfg
powercfg /s SCHEME_MIN 2>nul
rem 安装 SCSI 驱动
if exist X:\drivers\ (
for /f "delims=" %%F in ('dir /s /b "X:\drivers\*.inf" 2^>nul') do (
call :drvload_if_scsi "%%~F"
)
rem 官网写了可以安装但仅会加载关键驱动
rem Gcore 的 virtio-gpu 在安装时没有显示
rem 即使安装时加载了显卡驱动
rem 进入系统后才有显示
rem find /i "viogpudo" "%%~F" >nul
rem if not errorlevel 1 (
rem drvload "%%~F"
rem )
)
rem 安装自定义 SCSI 驱动
rem 可以用 forfiles /p X:\custom_drivers /m *.inf /c "cmd /c echo @path"
rem 不可以用 for %%F in ("X:\custom_drivers\*\*.inf")
if exist X:\custom_drivers\ (
for /f "delims=" %%F in ('dir /s /b "X:\custom_drivers\*.inf" 2^>nul') do (
call :drvload_if_scsi "%%~F"
)
)
rem 等待加载分区
call :sleep 5000
echo rescan | diskpart
call :sleep 5000
rem 获取 ProductType
rem for /f "tokens=3" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions" /v ProductType') do (
rem set "ProductType=%%a"
rem )
rem 获取 installer 卷 id
for /f "tokens=2" %%a in ('echo list vol ^| diskpart ^| find " installer "') do (
set "VolIndex=%%a"
)
rem 及时退出
if "%VolIndex%"=="" (
echo Error: Cannot find installer partition. >&2
exit /b 1
)
rem 将 installer 分区设为 Y 盘
(echo select vol %VolIndex% & echo assign letter=Y) | diskpart
rem 旧版安装程序会自动在 C 盘设置虚拟内存
rem 新版安装程序(24h2)不会自动设置虚拟内存
rem 在 installer 分区创建虚拟内存,不用白不用
call :createPageFile
rem 查看虚拟内存
rem wmic pagefile
rem 获取主硬盘 id
rem vista pe 没有 wmic,因此用 diskpart
rem 法语版 win7 diskpart 始终输出法语,即使设置了 chcp 437,因此不能用这个方法
rem (echo select vol %VolIndex% & echo list disk) | diskpart | find "* Disk " > X:\disk.txt
rem for /f "tokens=3" %%a in (X:\disk.txt) do (
rem set "DiskIndex=%%a"
rem )
rem PE 下没有 findstr,因此不能从 diskpart 的输出直接选出开头为 * 的行,要用复杂的方法取出磁盘编号
rem 输出 diskpart 结果到文件
(echo select vol %VolIndex% & echo list disk) | diskpart | find "* " > X:\disk.txt
type X:\disk.txt
rem 逐行读取文件
setlocal enabledelayedexpansion
for /f "delims=" %%a in (X:\disk.txt) do (
set "line=%%a"
rem 寻找 * 开头的行
call :is_x_starts_with_char_y "!line!" "*" && (
rem 注意在 for %%b in (!safe_line!) do 中 * 会展开成文件列表,因此要先删除 *
rem 下面用的方法是用 * 作为分割符,获取 * 后面的第一列
rem for /f 会自动忽略行首的分隔符
for /f "tokens=1 delims=*" %%i in ("!line!") do (
set "safe_line=%%i"
)
rem 遍历每一列,找到是数字的那一列,就是磁盘编号
for %%b in (!safe_line!) do (
call :is_number "%%b" && (
set "DiskIndex=%%b"
goto :found_main_disk
)
)
rem 普通 for 是把“一段话”里的“每个词”排成队,让一个变量(%%b)轮流去当这些词
rem for /f 是把“一段话”拆成“几个零件”存在不同的变量里(%%i, %%j...)
)
)
:not_found_main_disk
echo Error: Cannot find main disk. >&2
exit /b 1
:found_main_disk
del X:\disk.txt
endlocal & set "DiskIndex=%DiskIndex%"
rem 判断 efi 还是 bios
rem 或者用 https://learn.microsoft.com/windows-hardware/manufacture/desktop/boot-to-uefi-mode-or-legacy-bios-mode
rem pe 下没有 mountvol
echo list vol | diskpart | find " efi " && (
set BootType=efi
) || (
set BootType=bios
)
rem 这个变量会被 trans.sh 修改
set is4kn=0
if "%is4kn%"=="1" (
set EFISize=260
) else (
set EFISize=100
)
rem 重新分区/格式化
(if "%BootType%"=="efi" (
echo select disk %DiskIndex%
rem del
echo select part 1
echo delete part override
echo select part 2
echo delete part override
echo select part 3
echo delete part override
rem 1
echo create part efi size=%EFISize%
echo format fs=fat32 quick
rem 2
echo create part msr size=16
rem 3
echo create part primary
echo format fs=ntfs quick
rem echo assign letter=Z
) else (
echo select disk %DiskIndex%
rem del
echo select part 1
echo delete part override
rem 1
echo create part primary
echo format fs=ntfs quick
echo active
rem echo assign letter=Z
)) > X:\diskpart.txt
rem 使用 diskpart /s ,出错后不会执行剩下的 diskpart 命令
rem 但是返回值始终是 0
diskpart /s X:\diskpart.txt
del X:\diskpart.txt
rem 盘符
rem X boot.wim (ram)
rem Y installer
rem Z os
rem 获取 BuildNumber
for /f "tokens=3" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CurrentBuildNumber') do (
set "BuildNumber=%%a"
)
rem 旧版安装程序会自动在C盘设置虚拟内存,新版安装程序(24h2)不会
rem 如果不创建虚拟内存,1g 内存的机器安装时会报错/杀进程
if %BuildNumber% GEQ 26040 (
rem 已经在 installer 分区创建了虚拟内存,约等于 boot.wim 的大小,因此这步不需要
rem vista/2008 没有删除 boot.wim,200M预留空间-(文件系统占用+驱动占用)后,实测能创建1个64M虚拟内存文件
rem call :createPageFileOnZ
)
rem 设置应答文件的主硬盘 id
set "file=X:\windows.xml"
set "tempFile=X:\tmp.xml"
set "search=%%disk_id%%"
set "replace=%DiskIndex%"
(for /f "delims=" %%i in (%file%) do (
set "line=%%i"
setlocal EnableDelayedExpansion
echo !line:%search%=%replace%!
endlocal
)) > %tempFile%
move /y %tempFile% %file%
rem https://github.com/pbatard/rufus/issues/1990
for %%a in (RAM TPM SecureBoot) do (
reg add HKLM\SYSTEM\Setup\LabConfig /t REG_DWORD /v Bypass%%aCheck /d 1 /f
)
rem 设置
set ForceOldSetup=0
set EnableUnattended=1
set EnableEMS=0
rem 运行 ramdisk X:\setup.exe 的话
rem vista 会找不到安装源
rem server 23h2 会无法运行
rem 使用 /installfrom 可以解决?
rem 有的精简版 iso install.wim 根目录没有 setup.exe
rem https://github.com/bin456789/reinstall/issues/578
if "%ForceOldSetup%"=="1" if exist Y:\sources\setup.exe (
set setup=Y:\sources\setup.exe
goto :SetupExeFound
)
if exist Y:\setup.exe (
set setup=Y:\setup.exe
) else if exist Y:\sources\setup.exe (
set setup=Y:\sources\setup.exe
) else if exist X:\setup.exe (
set setup=X:\setup.exe
) else (
echo "Error: setup.exe not found." >&2
exit /b 1
)
:SetupExeFound
if "%EnableUnattended%"=="1" (
set Unattended=/unattend:X:\windows.xml
)
rem 新版安装程序默认开了 Compact OS
rem 新版安装程序不会创建 BIOS MBR 引导
rem 因此要回退到旧版,或者手动修复 MBR
rem server 2025 + bios 也是
rem 但是 server 2025 官网写支持 bios
rem TODO: 使用 ms-sys 可以不修复?
if %BuildNumber% GEQ 26040 if "%BootType%"=="bios" (
rem set ForceOldSetup=1
bootrec /fixmbr
)
rem 旧版安装程序不会创建 winre 分区
rem 新版安装程序会创建 winre 分区
rem winre 分区创建在 installer 分区前面
rem 禁止 winre 分区后,winre 储存在 C 盘,依然有效
if %BuildNumber% GEQ 26040 if "%ForceOldSetup%"=="0" (
set ResizeRecoveryPartition=/ResizeRecoveryPartition Disable
)
rem 为 windows server 打开 EMS/SAC
rem 普通 windows 没有自带 SAC 组件,暂不处理
rem 现在通过 trans.sh 准确检测系统是否有 SAC 组件,有则修改 EnableEMS 变量打开 EMS
if "%EnableEMS%"=="1" (
rem set EMS=/EMSPort:UseBIOSSettings /EMSBaudRate:115200
set EMS=/EMSPort:COM1 /EMSBaudRate:115200
)
echo on
%setup% %ResizeRecoveryPartition% %EMS% %Unattended%
exit /b
:is_number
rem 尝试转换字符串为数字,如果转换失败则说明不是数字
rem 如果转换失败,num 是 0
rem 这不影响参数是 0 时的判断
set /a "num=%~1" >nul 2>nul
if "%num%"=="%~1" (
exit /b 0
)
exit /b 1
:is_x_starts_with_char_y
set "tempStr=%~1"
if "%tempStr:~0,1%"=="%~2" (
exit /b 0
)
exit /b 1
:sleep
rem 没有加载网卡驱动,无法用 ping 来等待
rem 没有 timeout 命令
rem timeout /t 10 /nobreak
echo wscript.sleep(%~1) > X:\sleep.vbs
cscript //nologo X:\sleep.vbs
del X:\sleep.vbs
exit /b
:createPageFile
rem 尽量填满空间,pagefile 默认 64M
for /l %%i in (1, 1, 100) do (
wpeutil CreatePageFile /path=Y:\pagefile%%i.sys >nul 2>nul && echo Created pagefile%%i.sys || exit /b
)
exit /b
:createPageFileOnZ
wpeutil CreatePageFile /path=Z:\pagefile.sys /size=512
exit /b
:drvload_if_scsi
rem 不要查找 Class=SCSIAdapter 因为有些驱动等号两边有空格
find /i "SCSIAdapter" "%~1" >nul
if not errorlevel 1 (
rem 有 N 种方法安装驱动
rem 1. dism /online /add-driver /driver:"%~1" # PE 不支持 /online 添加驱动
rem 2. pnputil -i -a "%~1"
rem 3. devcon
rem 4. dpinst
rem 5. drvload 官方推荐 https://learn.microsoft.com/windows-hardware/manufacture/desktop/drvload-command-line-options
drvload "%~1"
)
exit /b