我们经常遇到安装双系统后,(比如XP和WIN7,XP安装在C盘,WIN7安装在D盘)不管启动哪一个系统,启动后系统所在盘都在C盘。还有一种情况是本来盘符是固定的但,系统故障后盘符变了不能完全运行系统,那我们该怎么办呢?
我们可以用到系统脚本:
@echo off
REM ===============================================================================
REM
REM Script arguments
REM /currentos:<driveletter>
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
)
if /I "%1" == "/?" (
Call :PrintUsage
exit /b 1
)
Call :ParseArgument %1
if "%BadUsage%" == "1" (
goto :HandleBadUsage
)
shift /1
goto :ParseArgumentLoop
: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
)
set %2=%VolumeDeviceValue%
exit /b 0
把以上代码保存为 osletter7.cmd
然后用启动PE系统在命令里运行osletter7.cmd /targetletter:x /currentos:y
这里x是在win7中你想让系统分区所占用的盘符,y是指winpe中win7的windows文件夹所在分区的盘符。
发表评论