这个功能提取自NT6快速安装器里的osletter7.cmd脚本,此脚本可用于部署一个WIM映像后,在重新启动前更改其系统盘占位盘符,尤其是用了vhdx安装或者Windows To Go的用户,不想导致系统盘默认是C导致本地硬盘盘符全部变化很有必要。
命令格式:
OsLetter.CMD /TargetLetter:将要占位的盘符 /CurrentOS:当前所在分区盘符
参数说明:
/TargetLetter:盘符
指定刚部署的系统盘启动后将要占位的盘符
/CurrentOS:盘符
指定要个更改盘符的系统当前所在分区盘符(比如WinPE下)
举例说明:
osletter /targetletter:x /currentos:t
执行脚本,将当前T盘下的系统占用盘符更改为X盘。
osletter /targetletter:x /currentos:t > t:\dl.log
执行脚本,将当前T盘下的系统占用盘符更改为X盘,并将执行结果输出到日志文件T:\dl.log中。
源代码:
@echo off
REM ===============================================================================
REM
REM Script arguments
REM /currentos:
REM Specify the current drive letter (under WinPE) of the OS partition REQUIRED
REM
REM NOTE: The log is printed to console by default. To write log to file, please
REM redirect the output to a log file. For example:
REM osletter7.bat /targetletter:s /currentos:t > t:\osletter7.log
REM
REM -------------------------------------------------------------------------------
setlocal
set BadUsage=
set CurrentOsDriveLetter=
set TargetSystemDriveLetter=
set NewOSDriveLetter=
set TempOutFile=%TEMP%\osletter7.bat.temp1.out
set ValidDriveLetters=C D E F G H I J K L M N O P Q R S T U V W X Y Z
if /I "%1" == "" (
Call :PrintUsage
exit /b 1
)
if /I "%1" == "/?" (
Call :PrintUsage
exit /b 1
)
REM ----- Print log file header ------
echo.
echo Script processing started for command: "%0 %*".
echo Parsing arguments...
REM ----- parse command line arguments ------
:ParseArgumentLoop
if /I "%1" == "" (
goto :ParseArgumentLoopEnd
)
REM ----- argument checks ------
Call :ValidateArgument
if "%BadUsage%" == "1" (
goto :HandleBadUsage
)
if not exist %CurrentOsDriveLetter%:\Windows\System32\Config\SYSTEM (
echo ERROR - Drive "%CurrentOsDriveLetter%" is not a valid OS drive - OS image not found.
goto :HandleBadUsage
)
REM Output command arguments to log file
echo -----------------------------------------------------------------------
echo ---------------Executing with the following arguments------------------
echo -----------------------------------------------------------------------
echo Current OS partition: %CurrentOsDriveLetter%
echo Target system partition letter: %TargetSystemDriveLetter%
echo -----------------------------------------------------------------------
REM ----- Main script processing ----
Call :FixRegistry
if "%BadUsage%" == "1" (
goto :HandleBadUsage
)
if ERRORLEVEL 1 (
goto :Failure
)
REM --------------------------------------------------------------------------------------
REM End of the main function (in case of success)
REM --------------------------------------------------------------------------------------
if exist %TempOutFile% del /q %TempOutFile%
echo Script completed successfully.
exit /b 0
REM --------------------------------------------------------------------------------------
REM Exit the script in case of failure.
REM --------------------------------------------------------------------------------------
:Failure
if exist %TempOutFile% del /q %TempOutFile%
echo Script failed!
exit/b 1
REM --------------------------------------------------------------------------------------
REM Function - Parse an argument
REM Output: set BadUsage=1 if parsing failed
REM --------------------------------------------------------------------------------------
:ParseArgument
set ArgumentName=
set ArgumentValue=
for /F "delims=: tokens=1" %%i in ("%1") do set ArgumentName=%%i
for /F "delims=: tokens=2" %%i in ("%1") do set ArgumentValue=%%i
for /F "delims=: tokens=3" %%i in ("%1") do (
if not "%%1" == "" (
REM This is the error case that there are more than two tokens in the
REM argument string (e.g. "currentsystem:s:abc")
echo Error - Invalid syntax: %1
set BadUsage=1
exit /b 1
)
)
if /I "%ArgumentName%" == "/Targetletter" (
set TargetSystemDriveLetter=%ArgumentValue%
) else (
if /I "%ArgumentName%" == "/CurrentOS" (
set CurrentOsDriveLetter=%ArgumentValue%
) else (
echo Error - Invalid syntax: %1
set BadUsage=1
exit /b 1
)
)
exit /b 0
REM --------------------------------------------------------------------------------------
REM Function - Check arguments for requiered options.
REM Input:
REM Output: set BadUsage=1 if validation failed
REM --------------------------------------------------------------------------------------
:ValidateArgument
if "%TargetSystemDriveLetter%" == "" (
echo ERROR - No /targetLetter option specified on the command line.
set BadUsage=1
) else (
Call :IsValidDriveLetter TargetLetter %TargetSystemDriveLetter% TargetSystemDriveLetter
)
if "%CurrentOsDriveLetter%" == "" (
echo ERROR - No /currentos option specified on the command line.
set BadUsage=1
) else (
Call :IsValidDriveLetter CurrentOS %CurrentOsDriveLetter% CurrentOsDriveLetter
)
exit /b 0
REM --------------------------------------------------------------------------------------
REM Function - Display usage for help.
REM Input:
REM Output:
REM --------------------------------------------------------------------------------------
:PrintUsage
echo This script can be used to change the OS drive letters when
echo deploying a WIM image before reboot.
echo.
echo osletter7[.cmd] /TargetLetter:^<DriveLetter^> /CurrentOS:^<DriveLetter^>
echo.
echo /TargetLetter:^<DriveLetter^>
echo Specify the OS drive letter under the system
echo.
echo /CurrentOS:^<DriveLetter^>
echo Specify the current drive letter (under WinPE) of the OS partition
echo.
echo Examples:
echo osletter7 /targetletter:s /currentos:t
echo Execute the script.
echo.
echo osletter7 /targetletter:s /currentos:t ^> t:\dl.log
echo Execute the script and redirect output to a log file.
echo.
exit /b 0
REM --------------------------------------------------------------------------------------
REM Function - Print help message in case of bad usage
REM Input:
REM Output:
REM --------------------------------------------------------------------------------------
:HandleBadUsage
echo.
echo Type "DriveLetter /?" for help.
exit /b 1
REM --------------------------------------------------------------------------------------
REM Function - Check whether a drive letter from a command line argument is valid or not.
REM Input: %1 - Name of the command line argument (e.g. CurrentSystem)
REM %2 - the drive letter (e.g. C)
REM %3 - Name of the global variable to set (e.g. CurrentSystemDriveLetter)
REM Output: set BadUsage=1 and errorlevel=1 if the input drive letter is invalid
REM --------------------------------------------------------------------------------------
:IsValidDriveLetter
for %%i in (%ValidDriveLetters%) do (
if /I "%%i" == "%2" (
set %3=%%i
exit /b 0
)
)
echo ERROR - Invalid drive letter "%2" entered for the command line argument "%1"
set BadUsage=1
exit /b 1
REM --------------------------------------------------------------------------------------
REM Function - Check whether a drive letter is valid or not.
REM Input: %1 - the drive letter
REM Output: set errorlevel=1 if the drive letter is invalid
REM --------------------------------------------------------------------------------------
:IsValidDriveLetter2
for %%i in (%ValidDriveLetters%) do (
if /I "%%i" == "%1" (
exit /b 0
)
)
exit /b 1
REM --------------------------------------------------------------------------------------
REM Function - Fix drive letters in registry
REM Input: arguments in global variables
REM Output:
REM Return: set errorlevel to 1 in case of failure
REM --------------------------------------------------------------------------------------
:FixRegistry
set SystemHiveLoaded=
set FixRegistryErrorLevel=
echo Fixing drive letters in registry...
Call :GetNewOsDriveLetter
if errorlevel 1 (
goto :FixRegistryExitWithFailure
)
echo Preparing to fix registry entries...
Call :FindVolumeEntryByDriveLetter %CurrentOsDriveLetter% OSVolumeValue
if errorlevel 1 (
goto :FixRegistryExitWithFailure
)
REM -- At this point, OSVolumeValue is something like 000000080014E70400000000.
reg.exe load HKU\TEMP %CurrentOsDriveLetter%:\Windows\System32\Config\SYSTEM > %TempOutFile%
if ERRORLEVEL 1 (
echo Command failed: reg.exe load HKU\TEMP %CurrentOsDriveLetter%:\Windows\System32\Config\SYSTEM
goto :FixRegistryExitWithFailure
) else (
set SystemHiveLoaded=1
)
REM -- create the key first so that we can successfully
REM -- delete, in case it did not exist.
reg add HKU\TEMP\MountedDevices /f > %TempOutFile%
if ERRORLEVEL 1 (
echo Command failed: reg add HKU\TEMP\MountedDevices /f
goto :FixRegistryExitWithFailure
)
reg delete HKU\TEMP\MountedDevices /f > %TempOutFile%
if ERRORLEVEL 1 (
echo Command failed: reg delete HKU\TEMP\MountedDevices /f
goto :FixRegistryExitWithFailure
)
reg add HKU\TEMP\MountedDevices /f > %TempOutFile%
if ERRORLEVEL 1 (
echo Command failed: reg add HKU\TEMP\MountedDevices /f
goto :FixRegistryExitWithFailure
)
reg add HKU\TEMP\MountedDevices /v \DosDevices\%NewOSDriveLetter%: /t REG_BINARY /d %OSVolumeValue% /f > %TempOutFile%
if ERRORLEVEL 1 (
echo Command failed: reg add HKU\TEMP\MountedDevices /v \DosDevices\%NewOSDriveLetter%: /t REG_BINARY /d %OSVolumeValue% /f
echo ERROR - Failed to write to System registry hive
goto :FixRegistryExitWithFailure
) else (
echo Successfully wrote OS volume device with the new drive letter.
)
reg.exe unload HKU\TEMP > %TempOutFile%
if ERRORLEVEL 1 (
echo ERROR - Failed to save the System registry hive: %CurrentOsDriveLetter%:\Windows\System32\Config\SYSTEM.
goto :FixRegistryExitWithFailure
) else (
echo Successfully saved registry hive.
set SystemHiveLoaded=
)
goto :FixRegistryEnd
:FixRegistryExitWithFailure
set FixRegistryErrorLevel=1
:FixRegistryEnd
if "%SystemHiveLoaded%" == "1" (
reg.exe unload HKU\TEMP > %TempOutFile%
if ERRORLEVEL 1 (
echo Failed unload the SYSTEM hive, error ignored.
)
)
exit /b %FixRegistryErrorLevel%
REM --------------------------------------------------------------------------------------
REM Function - Read offline register SOFTWARE\Microsoft\Windows NT\CurrentVersion RegValue
REM "PathName", and parse the new OS driveletter from it.
REM
REM Input:
REM Output: set NewOSDriveLetter to the new OS driveletter
REM Return: set errorlevel to 1 in case of failure
REM --------------------------------------------------------------------------------------
:GetNewOsDriveLetter
set NewOSDriveLetter=%TargetSystemDriveLetter%
Call :IsValidDriveLetter2 %NewOSDriveLetter%
if ERRORLEVEL 1 (
echo Failed to parse the new OS drive letter.
exit /b 1
) else (
echo Valid OS drive letter.
)
exit /b 0
REM --------------------------------------------------------------------------------------
REM Function - Search HKLM\SYSTEM\MountedDevices, find the volume device name and value by driveletter.
REM
REM Input: %1 - The drive letter
REM %2 - Name of the variable to be set to the volume device value
REM Output: set variable %3
REM Return: set errorlevel to 1 in case of failure
REM --------------------------------------------------------------------------------------
:FindVolumeEntryByDriveLetter
set %2=
set VolumeDeviceValue=
set DeviceDriveName=\DosDevices\%1:
reg query HKLM\SYSTEM\MountedDevices /v %DeviceDriveName% > %TempOutFile%
if ERRORLEVEL 1 (
echo Command failed: reg query HKLM\SYSTEM\MountedDevices /v %DeviceDriveName%
goto :FindVolumeEntryByDriveLetterEnd
)
for /F "skip=2 tokens=3" %%i in (%TempOutFile%) do (
REM -- set VolumeDeviceValue to the REG_BINARY value (something like
REM -- 000000080014E70400000000) of the volume device.
set VolumeDeviceValue=%%i
goto :FindVolumeEntryByDriveLetterEnd
)
:FindVolumeEntryByDriveLetterEnd
if "%VolumeDeviceValue%" == "" (
echo Error - Failed to get registry drive mapping for drive: %1
exit /b 1
)
这个功能提取自NT6快速安装器里的osletter7.cmd脚本,此脚本可用于部署一个WIM映像后,在重新启动前更改其系统盘占位盘符,尤其是用了vhdx安装或者Windows To Go的用户,不想导致系统盘默认是C导致本地硬盘盘符全部变化很有必要。 命令格式: OsLetter.CMD /TargetLetter:将要占位的盘符 /CurrentOS:当前所在分区盘符 参数说明: /TargetLetter:盘符 指定刚部署的系统盘启动后将要占位的盘符 /CurrentOS:盘符 指定要个更改盘符的系统当前所在分区盘符(比如WinPE下) 举例说明: osletter /targetletter:x /currentos:t 执行脚本,将当前T盘下的系统占用盘符更改为X盘。 osletter /targetletter:x /currentos:t > t:\dl.log 执行脚本,将当前T盘下的系统占用盘符更改为X盘,并将执行结果输出到日志文件T:\dl.log中。 源代码: @echo off REM =============================================================================== REM REM Script arguments REM /currentos:
REM Specify the current drive letter (under WinPE) of the OS partition REQUIRED
REM
REM NOTE: The log is printed to console by default. To write log to file, please
REM redirect the output to a log file. For example:
REM osletter7.bat /targetletter:s /currentos:t > t:\osletter7.log
REM
REM -------------------------------------------------------------------------------
setlocal set BadUsage= set CurrentOsDriveLetter= set TargetSystemDriveLetter= set NewOSDriveLetter= set TempOutFile=%TEMP%\osletter7.bat.temp1.out set ValidDriveLetters=C D E F G H I J K L M N O P Q R S T U V W X Y Z
if /I "%1" == "" ( Call :PrintUsage exit /b 1 )
if /I "%1" == "/?" ( Call :PrintUsage exit /b 1 )
REM ----- Print log file header ------ echo. echo Script processing started for command: "%0 %*". echo Parsing arguments...
REM ----- parse command line arguments ------ :ParseArgumentLoop if /I "%1" == "" ( goto :ParseArgumentLoopEnd )
:ParseArgumentLoopEnd
REM ----- argument checks ------ Call :ValidateArgument if "%BadUsage%" == "1" ( goto :HandleBadUsage )
if not exist %CurrentOsDriveLetter%:\Windows\System32\Config\SYSTEM ( echo ERROR - Drive "%CurrentOsDriveLetter%" is not a valid OS drive - OS image not found. goto :HandleBadUsage )
REM Output command arguments to log file echo ----------------------------------------------------------------------- echo ---------------Executing with the following arguments------------------ echo ----------------------------------------------------------------------- echo Current OS partition: %CurrentOsDriveLetter% echo Target system partition letter: %TargetSystemDriveLetter% echo -----------------------------------------------------------------------
REM ----- Main script processing ---- Call :FixRegistry if "%BadUsage%" == "1" ( goto :HandleBadUsage ) if ERRORLEVEL 1 ( goto :Failure )
REM -------------------------------------------------------------------------------------- REM End of the main function (in case of success) REM -------------------------------------------------------------------------------------- if exist %TempOutFile% del /q %TempOutFile% echo Script completed successfully. exit /b 0
REM -------------------------------------------------------------------------------------- REM Exit the script in case of failure. REM -------------------------------------------------------------------------------------- :Failure if exist %TempOutFile% del /q %TempOutFile% echo Script failed! exit/b 1
REM -------------------------------------------------------------------------------------- REM Function - Parse an argument REM Output: set BadUsage=1 if parsing failed REM -------------------------------------------------------------------------------------- :ParseArgument set ArgumentName= set ArgumentValue= for /F "delims=: tokens=1" %%i in ("%1") do set ArgumentName=%%i for /F "delims=: tokens=2" %%i in ("%1") do set ArgumentValue=%%i for /F "delims=: tokens=3" %%i in ("%1") do ( if not "%%1" == "" ( REM This is the error case that there are more than two tokens in the REM argument string (e.g. "currentsystem:s:abc") echo Error - Invalid syntax: %1 set BadUsage=1 exit /b 1 ) )
REM -------------------------------------------------------------------------------------- REM Function - Check arguments for requiered options. REM Input: REM Output: set BadUsage=1 if validation failed REM -------------------------------------------------------------------------------------- :ValidateArgument if "%TargetSystemDriveLetter%" == "" ( echo ERROR - No /targetLetter option specified on the command line. set BadUsage=1 ) else ( Call :IsValidDriveLetter TargetLetter %TargetSystemDriveLetter% TargetSystemDriveLetter )
REM -------------------------------------------------------------------------------------- REM Function - Display usage for help. REM Input: REM Output: REM -------------------------------------------------------------------------------------- :PrintUsage echo This script can be used to change the OS drive letters when echo deploying a WIM image before reboot. echo. echo osletter7[.cmd] /TargetLetter:^<DriveLetter^> /CurrentOS:^<DriveLetter^> echo. echo /TargetLetter:^<DriveLetter^> echo Specify the OS drive letter under the system echo. echo /CurrentOS:^<DriveLetter^> echo Specify the current drive letter (under WinPE) of the OS partition echo. echo Examples: echo osletter7 /targetletter:s /currentos:t echo Execute the script. echo. echo osletter7 /targetletter:s /currentos:t ^> t:\dl.log echo Execute the script and redirect output to a log file. echo. exit /b 0
REM -------------------------------------------------------------------------------------- REM Function - Print help message in case of bad usage REM Input: REM Output: REM -------------------------------------------------------------------------------------- :HandleBadUsage echo. echo Type "DriveLetter /?" for help. exit /b 1
REM -------------------------------------------------------------------------------------- REM Function - Check whether a drive letter from a command line argument is valid or not. REM Input: %1 - Name of the command line argument (e.g. CurrentSystem) REM %2 - the drive letter (e.g. C) REM %3 - Name of the global variable to set (e.g. CurrentSystemDriveLetter) REM Output: set BadUsage=1 and errorlevel=1 if the input drive letter is invalid REM -------------------------------------------------------------------------------------- :IsValidDriveLetter for %%i in (%ValidDriveLetters%) do ( if /I "%%i" == "%2" ( set %3=%%i exit /b 0 ) )
REM -------------------------------------------------------------------------------------- REM Function - Check whether a drive letter is valid or not. REM Input: %1 - the drive letter REM Output: set errorlevel=1 if the drive letter is invalid REM -------------------------------------------------------------------------------------- :IsValidDriveLetter2 for %%i in (%ValidDriveLetters%) do ( if /I "%%i" == "%1" ( exit /b 0 ) ) exit /b 1
REM -------------------------------------------------------------------------------------- REM Function - Fix drive letters in registry REM Input: arguments in global variables REM Output: REM Return: set errorlevel to 1 in case of failure REM -------------------------------------------------------------------------------------- :FixRegistry set SystemHiveLoaded= set FixRegistryErrorLevel=
:FixRegistryExitWithFailure set FixRegistryErrorLevel=1 :FixRegistryEnd if "%SystemHiveLoaded%" == "1" ( reg.exe unload HKU\TEMP > %TempOutFile% if ERRORLEVEL 1 ( echo Failed unload the SYSTEM hive, error ignored. ) )
REM -------------------------------------------------------------------------------------- REM Function - Read offline register SOFTWARE\Microsoft\Windows NT\CurrentVersion RegValue REM "PathName", and parse the new OS driveletter from it. REM REM Input: REM Output: set NewOSDriveLetter to the new OS driveletter REM Return: set errorlevel to 1 in case of failure REM -------------------------------------------------------------------------------------- :GetNewOsDriveLetter set NewOSDriveLetter=%TargetSystemDriveLetter%
REM -------------------------------------------------------------------------------------- REM Function - Search HKLM\SYSTEM\MountedDevices, find the volume device name and value by driveletter. REM REM Input: %1 - The drive letter REM %2 - Name of the variable to be set to the volume device value REM Output: set variable %3 REM Return: set errorlevel to 1 in case of failure REM -------------------------------------------------------------------------------------- :FindVolumeEntryByDriveLetter set %2= set VolumeDeviceValue= set DeviceDriveName=\DosDevices\%1:
:FindVolumeEntryByDriveLetterEnd if "%VolumeDeviceValue%" == "" ( echo Error - Failed to get registry drive mapping for drive: %1 exit /b 1 )