前 言
 
文章转译自Native VHD boot Windows 7 or Server 2008 R2 from an external USB drive,作者Garry Martin,原文链接在此。 想必大伙已经对Windows 7中的VHD启动功能兴奋不已,再这个基础之上,我们来试验如何从USB外置设备上直接启动VHD中的Windows。下面的这些步骤是不被微软技术支持认可的,你在操作之前,需求确保自己数据和设备的安全(放心,U盘不会爆炸),同时,即便你试验成功,也不推荐在生产环境中使用。
 
背 景

为了能够顺利地让Windows从U盘启动,我们必须先理解相关的设备驱动程序,和它们在启动过程中被加载的顺序。 Windows在启动时,即插即用管理器(PnP Manager)先从系统的Root Device驱动程序开始,然后加载这些Root Device的Child Devices驱动程序,并一层一层的展开,这个顺序是默认配置好的。如果不改变这个配置,从U盘启动VHD Windows后,会出现蓝屏错误,这个原因就是在特定的启动阶段,USB设备的驱动程序还没有被正确加载,导致系统出现蓝屏。为了改变这个默认的驱动程序加载过程,我们需要修改修改USB设备相关的驱动INF文件,主要是INF文件的StartType和LoadOrderGroup段落。
 
即插即用设备的启动类型默认是SERVICE_DEMAND_START (0×3),这表示系统在发现设备时,PnP Manager加载其驱动程序,大部分的USB设备驱动,都属于这样的类型。但如,如果对于系统启动过程中需要使用的设备,此设备的启动类型应该为SERVICE_BOOT_START (0×0),否则在启动的某一个环节中(应该是Bootmgr转交控制权给Windows内核时),会重新加载启动设备的驱动程序,导致系统蓝屏。
 
在启动时,启动组件会在把控制权转交给Windows之前,把所有启动类型为SERVICE_BOOT_START (0×0)的设备驱动程序加载完成,Windows内核在获得控制权时,这些关键设备的驱动程序已经驻留在内存中,不需要再次重新加载。对于启动过程中使用的设备,你可以通过修改INF文件的LoadOrderGroup来改变它们的驱动加载方式,另外,注册表HKLM/SYSTEM/CurrentControlSet/Control/ServiceGroupOrder有对此部分的详细描述。
 
为了从USB设备启动VHD上的Windows,我们需要改变6种USB相关设备驱动的加载方式,这6种设备是:
 
usbccgp - Microsoft USB Generic Parent Driver
usbehci - Microsoft USB 2.0 Enhanced Host Controller Miniport Driver
usbohci - Microsoft USB Open Host Controller Miniport Driver
usbuhci - Microsoft Universal Host Controller Miniport Driver
usbhub - Microsoft USB Standard Hub Driver
usbstor - USB Mass Storage Driver
 
或者
 
usbccgp - Boot Bus Extender
usbehci - Boot Bus Extender
usbohci - Boot Bus Extender
usbuhci - Boot Bus Extender
usbhub - System Bus Extender

usbstor - SCSI Miniport
这仅是交代一个“理论”背景,为了能够成功启动,我们需要修改INF文件中的StartType和LoadOrderGroup,同时,确保这些修改不会被Windows自动还原。
 
需 求
 
硬件
一台安装Windows 7(企业版或者旗舰版)或者Windows Server 2008 R2的计算机
USB设备,可以是大容量的U盘,也可以是USB硬盘,如果你用一个16GB的SD卡,也许会更加拉风。把这个U盘格式化,插上计算机,我们假设它的盘符是M盘
软件
Windows 7(企业版或者旗舰版)的安装光盘或者镜像文件,可以在这里下载试用版;
Windows Automated Installation Kit (WAIK) for Windows 7,可以在这里下载;
PsExec.exe 这个工具在Sysinternal工具包中,下载地址在此
Horst Schaeffer’s INI File Tool,这是一个INF文件编辑工具,下载地址在此
 
过 程
 
好,如果你所有的备料都已经收集齐了,我们开始炒这道菜。首先申明一下:这是一个手把手的实验步骤,但是也需要操作者有足够的计算机知识和足够的细心,误操作可能会损坏试验计算机的注册表和驱动程序,甚至导致计算机无法启动,请务必认真谨慎。
首先,我们需要制作一个VHD文件,容量是8GB,把它保存在M:根目录,并为这个VHD盘分配盘符R盘。步骤如下:
 
diskpart
create vdisk file=M:\new.vhd maximum=8000 type=fixed
select vdisk file=M:\new.vhd
attach vdisk
create partition primary
assign letter=r
format quick label=vhd
exit
 
注意:运行Diskpart需要管理员权限,在启动命令行的时候,鼠标右键选择“Run As Admin”,下同。
接下来,我们把Windows 7的光盘放入光驱,或者虚拟光驱,然后把安装文件的镜像,灌入到这个VHD中。
 
p_w_picpathx /apply F:\sources\install.wim  5  r:\
 
注意:1)p_w_picpathx工具在WAIK中有提供,请查找到对应的目录;2)假设光盘盘符是F盘;5)索引值“5”对应的是Windows 7的旗舰版,但也可能不是,你需要运行p_w_picpathx info F:\sources\install.wim确认它旗舰版的Index值。
VHD文件制作完毕,可以运行如下命令把VHD文件离线,备用。
 
diskpart
select vdisk file=M:\new.vhd
detach vdisk
exit
 
好,请大家摒住呼吸,我们开始玩一些高级的。到此为止,我们已经有一个VHD文件,和这个VHD文件中的Windows 7系统。这个Windows 7系统虽然没有启动过,但是她的注册表、驱动结构等已经按照默认配置部署完毕,我们需要在Windows启动之前,对她的注册表和驱动进行“离线编辑”。
 
运行如下命令使VHD文件上线
 
DISKPART
SELECT VDISK FILE="M:new.vhd"
ATTACH VDISK
ASSIGN LETTER=R
EXIT
 
我们可以通过文件浏览器,查看到R盘中已经存在的Windows文件。我们使用REG命令,对这个R盘中的Windows注册表进行编辑修改,在管理员身份下执行如下命令:
 
REG LOAD HKLM\TEMP R:\WINDOWS\SYSTEM32\CONFIG\SYSTEM
REG ADD HKLM\TEMP\ControlSet001\services\usbccgp /v Group /t REG_SZ /d "Boot Bus Extender" /f
REG ADD HKLM\TEMP\ControlSet001\services\usbccgp /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbehci /v Group /t REG_SZ /d "Boot Bus Extender" /f
REG ADD HKLM\TEMP\ControlSet001\services\usbehci /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbhub /v Group /t REG_SZ /d "Boot Bus Extender" /f
REG ADD HKLM\TEMP\ControlSet001\services\usbhub /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbohci /v Group /t REG_SZ /d "Boot Bus Extender" /f
REG ADD HKLM\TEMP\ControlSet001\services\usbohci /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\USBSTOR /v Group /t REG_SZ /d "Boot Bus Extender" /f
REG ADD HKLM\TEMP\ControlSet001\services\USBSTOR /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\usbuhci /v Group /t REG_SZ /d "Boot Bus Extender" /f
REG ADD HKLM\TEMP\ControlSet001\services\usbuhci /v Start /t REG_DWORD /d 0 /f
REG ADD HKLM\TEMP\ControlSet001\services\FsDepends\Parameters /v VirtualDiskExpandOnMount /t REG_DWORD /d 4 /f
REG UNLOAD HKLM\TEMP
 
注意:这一大串命令不用自己一个一个的敲进去,写一个bat文件即可,不过别忘了run as admin,下同。通过上面的修改,我们已经把注册表中的USB设备驱动方式进行了调整,接下来,我们需要修改INF文件。对INF的修改需要更高的权限,仅仅启动cmd是不够的。我们要通过运行psexec.exe,来获得一个最高的SYSTEM帐号身份,来执行对INF的修改。psexec.exe的运行方式如下:
 
PSEXEC -i -d -s C:\Windows\System32\cmd.exe
 
在弹出的窗口中,使用INIFILE工具,修改R盘中Windows系统的INF文件,具体命令如下。如果你把这些命令写成bat批处理,需要在psexec弹出的窗口中执行这个bat,不能点鼠标直接运行,否则权限不对。
 
INIFILE R:\Windows\inf\usb.inf [StandardHub.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usb.inf [StandardHub.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usb.inf [CommonClassParent.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usb.inf [CommonClassParent.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [EHCI.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [EHCI.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [OHCI.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [OHCI.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [UHCI.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [UHCI.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbport.inf [ROOTHUB.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbport.inf [ROOTHUB.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\usbstor.inf [USBSTOR.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\usbstor.inf [USBSTOR.AddService] LoadOrderGroup = Boot Bus Extender
INIFILE R:\Windows\inf\brmfcsto.inf [USBSTOR.AddService] StartType   = 0                  ; SERVICE_BOOT_START
INIFILE R:\Windows\inf\brmfcsto.inf [USBSTOR.AddService] LoadOrderGroup = Boot Bus Extender
 
接下来,我们需要把系统默认的INF删除,并用我们自己修改的文件替代之。INF文件的路径针对x64和x86系统有所不同,分别如下:
如果你的Windows 7安装光盘是x64的,执行如下命令:
 
DEL /Q R:\Windows\inf\usb.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usb.inf_amd64_neutral_e2b28ecac19a29af\usb.pnf
DEL /Q R:\Windows\winsxs\amd64_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_26ed589d28235a16\usb.pnf
DEL /Q R:\Windows\inf\usbport.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbport.inf_amd64_neutral_5a41ca742f7973cc\usbport.pnf
DEL /Q R:\Windows\winsxs\amd64_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_19b7511a1d3ea7fd\usbport.pnf
DEL /Q R:\Windows\inf\usbstor.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_amd64_neutral_c301b770e0bfb179\usbstor.pnf
DEL /Q R:\Windows\winsxs\amd64_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_a47b405db18421ea\usbstor.pnf
DEL /Q R:\Windows\inf\brmfcsto.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_amd64_neutral_2d7208355536945e\brmfcsto.pnf
DEL /Q R:\Windows\winsxs\amd64_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_7fe64f7a6167bcf6\brmfcsto.pnf
COPY /Y R:\Windows\inf\usb.inf R:\Windows\System32\DriverStore\FileRepository\usb.inf_amd64_neutral_e2b28ecac19a29af
COPY /Y R:\Windows\inf\usb.inf R:\Windows\winsxs\amd64_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_26ed589d28235a16
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\System32\DriverStore\FileRepository\usbport.inf_amd64_neutral_5a41ca742f7973cc
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\winsxs\amd64_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_19b7511a1d3ea7fd
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_amd64_neutral_c301b770e0bfb179
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\winsxs\amd64_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_a47b405db18421ea
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_amd64_neutral_2d7208355536945e
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\winsxs\amd64_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_7fe64f7a6167bcf6
EXIT
 
如果你的Windows 7安装光盘是x86的,执行如下命令:
 
DEL /Q R:\Windows\inf\usb.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usb.inf_x86_neutral_e24d8d3fec6e4567\usb.pnf
DEL /Q R:\Windows\winsxs\x86_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_cacebd196fc5e8e0\usb.pnf
DEL /Q R:\Windows\inf\usbport.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbport.inf_x86_neutral_ba59fa32fc6a596d\usbport.pnf
DEL /Q R:\Windows\winsxs\x86_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_bd98b59664e136c7\usbport.pnf
DEL /Q R:\Windows\inf\usbstor.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_x86_neutral_83027f5d5b2468d3\usbstor.pnf
DEL /Q R:\Windows\winsxs\x86_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_485ca4d9f926b0b4\usbstor.pnf
DEL /Q R:\Windows\inf\brmfcsto.pnf
DEL /Q R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_x86_neutral_39ae61431a44cded\brmfcsto.pnf
DEL /Q R:\Windows\winsxs\x86_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_23c7b3f6a90a4bc0\brmfcsto.pnf
COPY /Y R:\Windows\inf\usb.inf R:\Windows\System32\DriverStore\FileRepository\usb.inf_x86_neutral_e24d8d3fec6e4567
COPY /Y R:\Windows\inf\usb.inf R:\Windows\winsxs\x86_usb.inf_31bf3856ad364e35_6.1.7600.16385_none_cacebd196fc5e8e0
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\System32\DriverStore\FileRepository\usbport.inf_x86_neutral_ba59fa32fc6a596d
COPY /Y R:\Windows\inf\usbport.inf R:\Windows\winsxs\x86_usbport.inf_31bf3856ad364e35_6.1.7600.16385_none_bd98b59664e136c7
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\System32\DriverStore\FileRepository\usbstor.inf_x86_neutral_83027f5d5b2468d3
COPY /Y R:\Windows\inf\usbstor.inf R:\Windows\winsxs\x86_usbstor.inf_31bf3856ad364e35_6.1.7600.16385_none_485ca4d9f926b0b4
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\System32\DriverStore\FileRepository\brmfcsto.inf_x86_neutral_39ae61431a44cded
COPY /Y R:\Windows\inf\brmfcsto.inf R:\Windows\winsxs\x86_brmfcsto.inf_31bf3856ad364e35_6.1.7600.16385_none_23c7b3f6a90a4bc0
EXIT
 
到这一步,我们已经完成了对Windows USB设备驱动程序加载顺序的修改。接下来,我们为了方便试验,创建一个差异VHD文件,把之前做好的new.vhd作为只读文件,避免对它造成损坏。差异VHD的创建过程如下:
 
DISKPART
SELECT VDISK FILE="M:\new.vhd"
DETACH VDISK
CREATE VDISK FILE="M:\diff.vhd" PARENT="M:\new.vhd"
SELECT VDISK FILE="M:\diff.vhd"
ATTACH VDISK
LIST VOLUME
ASSIGN LETTER=R
EXIT
 
好了,有关VHD的准备工作,我们已经全部完成了,下面,我们需要把U盘配置为可以启动,并且让它自动从VHD文件启动,执行如下的命令:
 
BOOTSECT /NT60 M: /FORCE
BCDBOOT R:\WINDOWS /S M:
BCDEDIT /STORE M:\BOOT\BCD /COPY {default} /d "Windows Server 2008 R2 Enterprise"
BCDEDIT /STORE M:\BOOT\BCD /SET {5aaa2c7a-a627-11de-83c7-001372bf1815} DEVICE VHD=[LOCATE]\BootVHDs\W2K8R2ENT_DIFF.vhd
BCDEDIT /STORE M:\BOOT\BCD /SET {5aaa2c7a-a627-11de-83c7-001372bf1815} OSDEVICE VHD=[LOCATE]\BootVHDs\W2K8R2ENT_DIFF.vhd
BCDEDIT /STORE M:\BOOT\BCD /SET {5aaa2c7a-a627-11de-83c7-001372bf1815} DETECTHAL ON
 
注意:在第一次运行BCDEDIT命令后,系统会返回一个长长的GUID,你需要用系统返回的GUID,替换{5aaa2c7a-a627-11de-83c7-001372bf1815}大括号中的内容。
 
好了,That is it。重新启动计算机,选择从U盘启动,你会看到熟悉的Windows 7启动画面。因为是第一次启动,它需要一些时间完成系统的初始化,根据设备类型的不同,这个时间可长(超过1小时)可短(5分钟)。 还有一个注意事项: 既然装在U盘中了,能否拔下来在其他计算机上启动?答案是不一定,如果计算机的硬件都完全一样,是可以启动的。如果不一样的硬件,需要先执行sysprep命令,把系统重新初始化。
 
好了,其他的我就不多说了,留给大家自己慢慢琢磨吧。