Windows RE에 업데이트 패키지 추가

Windows RE 이미지에 LCU 또는 안전한 OS DU(동적 업데이트)를 적용할 수 있습니다. Windows RE 이미지를 업데이트하는 단계는 오프라인 이미지를 업데이트하는지 또는 실행 중인 시스템에서 이미지를 업데이트하는지에 따라 다릅니다.

  • LCU를 추가하는 경우: 업데이트를 추가하기 전과 업데이트를 추가한 후 WinRE 버전 번호를 확인하여 업데이트가 제대로 적용되었는지 확인합니다.
  • DU 패키지를 추가하는 경우: 패키지를 추가한 후 이미지의 패키지 목록을 확인하여 패키지가 이미지에 성공적으로 추가되었는지 확인합니다.

오프라인 이미지 업데이트

아래 단계에서는 오프라인 Windows RE 이미지에 업데이트된 패키지를 추가하는 방법을 설명합니다.

Windows 이미지 탑재

Windows RE 이미지(winre.wim)는 Windows 이미지(install.wim) 내부에 포함되며 결국 대상 PC 또는 디바이스의 Windows RE 도구 파티션에 복사됩니다. WinRE 이미지를 수정하려면 먼저 Windows 이미지를 탑재한 다음, Windows RE 이미지를 탑재합니다. 두 이미지를 모두 탑재한 후에는 변경 작업을 수행하고 WinRE 이미지를 분리한 다음 Windows 이미지를 분리할 수 있습니다.

  • 탑재 디렉터리를 만들고 install.wim을 탑재합니다.

    md C:\mount\windows
    Dism /Mount-Wim /WimFile:C:\images\install.wim /index:1 /MountDir:C:\mount\windows 
    

WinRE 이미지 탑재

  • 탑재된 이미지에서 Windows RE 이미지 파일을 탑재합니다.

    Md c:\mount\winre 
    Dism /Mount-Wim /WimFile:C:\mount\windows\Windows\System32\Recovery\winre.wim /index:1 /MountDir:C:\mount\winre 
    

    지정된 디렉터리에서 winre.wim을 볼 수 없는 경우 다음 명령을 사용하여 파일을 표시하도록 설정합니다.

    attrib -h -a -s C:\mount\windows\Windows\System32\Recovery\winre.wim
    

WinRE에 업데이트 패키지 추가

복구 이미지가 탑재된 상태에서 업데이트를 추가하여 문제를 해결할 수 있습니다.

  1. 필요한 업데이트 패키지를 다운로드하고 복구 이미지에 추가합니다.

    Dism /Add-Package /Image:C:\mount\winre /PackagePath:"c:\downloadedupdate\update.msu" 
    

    또는

    Dism /Add-Package /Image:C:\mount\ /PackagePath:"c:\downloadedupdate\dynamicupdate.cab" 
    
  2. 동적 업데이트 패키지를 추가한 경우 추가한 패키지가 이미지에 있는지 확인합니다.

     Dism /Image:C:\mount\ /Get-Packages
    

    방금 추가한 업데이트 패키지 목록을 확인합니다. 패키지에는 KB 번호가 포함되어야 하며, 성공적으로 추가된 경우 StateInstalled로 표시됩니다.

    Package Identity : Package_for_KB5021041~31bf3856ad364e35~amd64~~22621.815.1.0
    State : Installed
    Release Type : Update
    
  3. 복구 이미지를 정리하고 대체된 구성 요소의 기준을 다시 설정합니다.

    dism /image:C:\mount /cleanup-image /StartComponentCleanup /ResetBase 
    

이미지 탑재 해제

  1. 파일 탐색기를 포함하여 이미지에서 파일에 액세스할 수 있는 모든 애플리케이션을 닫습니다.

  2. 변경 내용을 커밋하고 Windows RE 이미지를 분리합니다.

    Dism /Unmount-Image /MountDir:"C:\mount\winre" /Commit 
    

    이 프로세스는 몇 분 정도 걸릴 수 있습니다.

  3. 변경 내용을 커밋하고 Windows 이미지를 탑재 해제합니다.

    Dism /Unmount-Image /MountDir:"C:\mount\windows" /Commit 
    

    여기서 C는 이미지가 포함된 드라이브의 드라이브 문자입니다. 이 프로세스에는 몇 분 정도 걸릴 수 있습니다.

이제 Windows RE 이미지가 업데이트되고 더 큰 Windows 이미지의 일부가 됩니다.

실행 중인 PC에 업데이트 적용

실행 중인 PC의 Windows 복구 이미지에 수정 사항을 적용할 수 있습니다. 다음 단계에서는 Windows 복구 이미지를 탑재하고 업데이트를 적용한 다음 변경 내용을 저장하는 방법을 안내합니다.

  1. 관리자 권한으로 명령 프롬프트를 엽니다.

  2. 복구 이미지를 탑재하여 변경할 수 있는 디렉터리를 만듭니다.

    md c:\mount 
    
  3. REAgentC를 사용하여 복구 이미지를 탑재합니다.

    ReAgentC.exe /mountre /path c:\mount 
    
  4. 복구 이미지가 탑재되면 업데이트 패키지를 다운로드하여 Windows RE 이미지에 추가할 수 있습니다.

    Dism /Add-Package /Image:C:\mount\ /PackagePath:"c:\downloadedupdate\update.msu" 
    

    또는

    Dism /Add-Package /Image:C:\mount\ /PackagePath:"c:\downloadedupdate\dynamicupdate.cab" 
    
  5. 동적 업데이트 패키지를 추가한 경우 추가한 패키지가 이미지에 있는지 확인합니다.

     Dism /Image:C:\mount\ /Get-Packages
    

    방금 추가한 업데이트 패키지 목록을 확인합니다. 패키지에는 KB 번호가 포함되어야 하며, 성공적으로 추가된 경우 StateInstalled로 표시됩니다.

    Package Identity : Package_for_KB5021041~31bf3856ad364e35~amd64~~22621.815.1.0
    State : Installed
    Release Type : Update
    
  6. 복구 이미지를 정리하고 대체된 구성 요소의 기준을 다시 설정합니다.

    dism /image:C:\mount /cleanup-image /StartComponentCleanup /ResetBase 
    
  7. Windows 복구 이미지를 분리합니다.

    ReAgentC.exe /unmountre /path c:\mount /commit 
    
  8. PC 디스크가 BitLocker 또는 디바이스 암호화로 보호되는 경우:ReagentC를 사용하여 Windows RE를 사용하지 않도록 설정한 다음 다시 사용하도록 설정합니다. 이렇게 하면 업데이트된 Windows RE 이미지가 켜지고 Windows 설치에 대해 올바르게 구성됩니다.

    reagentc /disable
    reagentc /enable 
    

이제 실행 중인 PC의 Windows RE 이미지가 업데이트되었습니다.

WinRE 이미지 버전 확인

온라인 및 오프라인 Windows 설치 모두에서 WinRE 이미지의 버전 번호를 확인할 수 있습니다. 이는 업데이트를 추가하기 전에 WinRE 버전을 확인하고, 업데이트를 적용한 후 업데이트가 성공적으로 추가되었는지 확인하는 데 유용할 수 있습니다.

참고 항목

WinRE 버전 번호는 LCU를 추가한 후에만 변경됩니다. DU 패키지를 추가하는 경우 위의 단계에 설명된 대로 DISM /get-packages를 사용하여 패키지가 이미지에 추가되었는지 확인합니다.

온라인 Windows OS에서 Windows RE 버전 확인

  1. ReagentC를 사용하여 다음 명령을 실행해 설치된 WinRE 이미지의 위치를 찾습니다.

    reagentc /info
    

    이 명령은 다음 예제와 비슷한 Windows RE 위치를 반환합니다.

    \\?\GLOBALROOT\device\harddisk0\partition4\Recovery\WindowsRE
    
  2. DISM을 사용하여 이전 단계에서 ReagentC가 반환한 경로에 있는 winre.wim 이미지에 대한 버전 정보를 가져옵니다. 명령을 실행할 때 경로에 WinRE 이미지 이름 및 이미지 인덱스 번호를 추가해야 합니다.

    Dism /Get-ImageInfo /ImageFile:\\?\GLOBALROOT\device\harddisk0\partition4\Recovery\WindowsRE\winre.wim /index:1
    

    보고된 버전을 확인합니다. 예시:

    Version : 10.0.22621
    ServicePack Build : 1
    ServicePack Level : 0
    

    ServicePackBuild가 추가한 업데이트의 UBR보다 크거나 같은지 확인합니다. 예를 들어 Windows 11 버전 22H2의 경우 11월 보안 업데이트는 SerivcePack Build819가 표시됩니다(해당 업데이트의 전체 버전 번호는 22621.819임).

    • 보고된 버전이 이전 버전인 경우 Windows RE 이미지가 최신 상태가 아닌 것입니다.
    • 보고된 버전이 동일하거나 이후 버전인 경우 아무 작업도 필요하지 않습니다.

오프라인 Windows OS에서 Windows RE 버전 확인

  1. 로컬 폴더(예: C:\mount\windows)에 Windows 이미지를 탑재합니다.

    mkdir C:\mount\windows
    Dism /Mount-Image /ImageFile:C:\mount\install.wim /Index:1 /MountDir:C:\mount\windows
    
  2. DISM을 사용하여 Windows\system32\recovery 폴더에 있는 winre.wim 이미지의 버전 정보를 가져옵니다. 명령을 실행할 때 이미지의 인덱스 번호를 지정해야 합니다.

    Dism /Get-ImageInfo /ImageFile:c:\mount\windows\windows\system32\recovery\winre.wim /index:1
    

    보고된 버전을 확인합니다. 예시:

    Version : 10.0.22621
    ServicePack Build : 1
    ServicePack Level : 0
    

    ServicePackBuild가 추가한 업데이트의 UBR보다 크거나 같은지 확인합니다. 예를 들어 Windows 11 버전 22H2의 경우 11월 보안 업데이트는 SerivcePack Build819가 표시됩니다(해당 업데이트의 전체 버전 번호는 22621.819임).

    • 보고된 버전이 이전 버전인 경우 Windows RE 이미지가 최신 상태가 아닌 것입니다.
    • 보고된 버전이 동일하거나 이후 버전인 경우 아무 작업도 필요하지 않습니다.

Windows RE 파티션 확장

아래 샘플 스크립트를 사용하여 WinRE(Windows 복구 환경)를 성공적으로 업데이트하기 위해 복구 파티션의 크기를 늘릴 수 있습니다. WinRE 업데이트를 성공적으로 설치하려면 복구 파티션에 250MB의 여유 공간이 있는 것이 좋습니다. 복구 파티션에 충분한 여유 공간이 없을 수 있는 디바이스에서 아래 샘플 스크립트를 사용하여 복구 파티션을 250MB까지 확장할 수 있습니다.

스크립트를 실행하기 전에 컴퓨터를 다시 부팅합니다. 스크립트가 WinRE 파티션 크기를 안전하게 늘리기 전에 완료해야 하는 보류 중인 파티션 작업이 컴퓨터에서 준비될 수 있으므로 이는 매우 중요합니다. 컴퓨터를 다시 부팅한 후 관리자 권한으로 Powershell을 열고 새 백업 디렉터리에> 대한 mkdir <경로를 실행하여 원래 파티션을 복원하지 못한 경우 스크립트에서 사용할 수 있는 백업 디렉터리를 만듭니다. 스크립트가 백업 경로를 요청하기 때문에 이 백업 디렉터리의 위치를 확인합니다. 대규모로 배포하는 경우 매개 변수를 사용하여 스크립트 프롬프트를 무시할 수 있습니다.

" -SkipConfirmation $true -BackupFolder "

예를 들면 다음과 같습니다.

Resize_script.ps1 -SkipConfirmation $true -BackupFolder c:\winre_backup

Param (
[Parameter(Mandatory=$false,HelpMessage="Skip confirmation")][bool]$SkipConfirmation=$false,
[Parameter(Mandatory=$true,HelpMessage="Path to backup old WinRE partition content to")][string]$BackupFolder
)
# ------------------------------------
# Helper functions
# ------------------------------------
# Log message
function LogMessage([string]$message)
{
	$message = "$message"
	Write-Host $message
}
# Extract numbers from string
function ExtractNumbers([string]$str)
{
	$cleanString = $str -replace "[^0-9]"
	return [long]$cleanString
}
# Display partition info using fsutil
# Return an array, the first value is total size and the second value is free space
function DisplayPartitionInfo([string[]]$partitionPath)
{
	$volume = Get-WmiObject -Class Win32_Volume | Where-Object { $partitionPath -contains $_.DeviceID }
	LogMessage("  Partition capacity: " +  $volume.Capacity)
	LogMessage("  Partition free space: " + $volume.FreeSpace)
	return $volume.Capacity, $volume.FreeSpace
} 
# Display WinRE status
function DisplayWinREStatus()
{
	# Get WinRE partition info
	$WinREInfo = Reagentc /info
	foreach ($line in $WinREInfo)
	{
		$params = $line.Split(':')
		if ($params.Count -lt 2)
		{
			continue
		}
		if (($params[1].Trim() -ieq "Enabled") -Or (($params[1].Trim() -ieq "Disabled")))
		{
			$Status = $params[1].Trim() -ieq "Enabled"
			LogMessage($line.Trim())
		}
		if ($params[1].Trim() -like "\\?\GLOBALROOT*")
		{
			$Location = $params[1].Trim()
			LogMessage($line.Trim())
		}
	}
	
	return $Status, $Location
}
# ------------------------------------
# Main execution
# ------------------------------------
# Clear the error
$Error.Clear()
# ------------------------------------
# Examining the system to collect required info 
# for the execution
# Need to check WinRE status, collect OS and WinRE
# partition info
# ------------------------------------
LogMessage("Start time: $([DateTime]::Now)")
LogMessage("Examining the system...")
$NeedShrink = $true
$NeedCreateNew = $false
$NeedBackup = $false
# Get WinRE partition info
$InitialWinREStatus = DisplayWinREStatus
$WinREStatus = $InitialWinREStatus[0]
$WinRELocation = $InitialWinREStatus[1]
if (!$WinREStatus)
{
	LogMessage("Error: WinRE Disabled")
	exit 1
}
# Get System directory and ReAgent xml file
$system32Path = [System.Environment]::SystemDirectory
LogMessage("System directory: " + $system32Path)
$ReAgentXmlPath = Join-Path -Path $system32Path -ChildPath "\Recovery\ReAgent.xml"
LogMessage("ReAgent xml: " + $ReAgentXmlPath)
if (!(Test-Path  $ReAgentXmlPath))
{
	LogMessage("Error: ReAgent.xml cannot be found")
	exit 1
}
# Get OS partition
LogMessage("")
LogMessage("Collecting OS and WinRE partition info...")
$OSDrive = $system32Path.Substring(0,1)
$OSPartition = Get-Partition -DriveLetter $OSDrive
# Get WinRE partition
$WinRELocationItems = $WinRELocation.Split('\\')
foreach ($item in $WinRELocationItems)
{
    if ($item -like "harddisk*")
	{
		$OSDiskIndex = ExtractNumbers($item)
	}
	if ($item -like "partition*")
	{
		$WinREPartitionIndex = ExtractNumbers($item)
	}
}
LogMessage("OS Disk: " + $OSDiskIndex)
LogMessage("OS Partition: " + $OSPartition.PartitionNumber)
LogMessage("WinRE Partition: " + $WinREPartitionIndex)
$WinREPartition = Get-Partition -DiskNumber $OSDiskIndex -PartitionNumber $WinREPartitionIndex
$diskInfo = Get-Disk -number $OSDiskIndex
$diskType = $diskInfo.PartitionStyle
LogMessage("Disk PartitionStyle: " + $diskType)
# Display WinRE partition size info
LogMessage("WinRE partition size info")
$WinREPartitionSizeInfo = DisplayPartitionInfo($WinREPartition.AccessPaths)
LogMessage("WinRE Partition Offset: " + $WinREPartition.Offset)
LogMessage("WinRE Partition Type: " + $WinREPartition.Type)
LogMessage("OS partition size: " + $OSPartition.Size)
LogMessage("OS partition Offset: " + $OSPartition.Offset)
$OSPartitionEnds = $OSPartition.Offset + $OSPartition.Size
LogMessage("OS partition ends at: " + $OSPartitionEnds)
LogMessage("WinRE partition starts at: " + $WinREPartition.Offset)
$WinREIsOnSystemPartition = $false
if ($diskType -ieq "MBR")
{
	if ($WinREPartition.IsActive)
	{
		LogMessage("WinRE is on System partition")
		$WinREIsOnSystemPartition = $true
	}
}
if ($diskType -ieq "GPT")
{
	if ($WinREPartition.Type -ieq "System")
	{
		LogMessage("WinRE is on System partition")
		$WinREIsOnSystemPartition = $true
	}
}
# Checking the BackupFolder parameter
if ($PSBoundParameters.ContainsKey('BackupFolder'))
{
	LogMessage("")
	LogMessage("Backup Directory: [" + $BackupFolder + "]")
	
	$Needbackup = $true
	
	if ($WinREIsOnSystemPartition)
	{
		$Needbackup = $false
		LogMessage("WinRE is on System partition which will be preserved. No need to backup content")
	}
	else
	{
		if (Test-path $BackupFolder)
		{
			$items = Get-ChildItem -Path $BackupFolder
			if ($items)
			{
				LogMessage("Error: Existing backup directory is not empty")
				exit 1
			}
		}
		else
		{
			LogMessage("Creating backup directory...")
			try 
			{
				$item = New-Item -Path $BackupFolder -ItemType Directory -ErrorAction Stop
				if ($item)
				{
					LogMessage("Backup directory created")
				}
				else
				{
					LogMessage("Error: Failed to create backup directory [" + $BackupFolder + "]")
					exit 1
				}
			} catch 
			{
				LogMessage("Error: An error occurred: $_")
				exit 1
			}
		}
	}
}
# ------------------------------------
# Verify whether we meet requirements of execution
# - WinRE cannot be on OS partition for the extension
# - WinRE partition must be the next partition after OS partition
# - If WinRE partition already have >=250MB free space, no need to do repartition
# - If there is enough unallocated space to grow the WinRE partition size, skip shrinking OS
# 
# However, if the WinRE partition is before the OS partition, there is no chance to extend it
# As a result, it's better to create a new WinRE partition after the OS partition
# ------------------------------------
# Perform a few checks
LogMessage("")
LogMessage("Verifying if the WinRE partition needs to be extended or not...")
if (!(($diskType -ieq "MBR") -Or ($diskType -ieq "GPT")))
{
	LogMessage("Error: Got an unexpected disk partition style: " +$diskType)
	exit 1
}
# WinRE partition must be after OS partition for the repartition
if ($WinREPartitionIndex -eq $OSPartition.PartitionNumber)
{
	LogMessage("WinRE and OS are on the same partition, should not perform extension")
	exit 0
}
$supportedSize = Get-PartitionSupportedSize -DriveLetter $OSDrive
# if there is enough free space, skip extension
if ($WinREPartitionSizeInfo[1] -ge 250MB)
{
	LogMessage("More than 250 MB of free space was detected in the WinRE partition, there is no need to extend the partition")
	exit 0
}
if ($WinREPartition.Offset -lt $OSPartitionEnds)
{
	LogMessage("WinRE partition is not after OS partition, cannot perform extension")
	LogMessage("Need to create a new WinRE partition after OS partition")
	$NeedCreateNew = $true
	$NeedShrink = $true
	
	# Calculate the size of repartition
	# Will create a new WinRE partition with current WinRE partition size + 250 MB
	# The OS partition size will be shrunk by the new WinRE partition size
	$targetWinREPartitionSize = $WinREPartitionSizeInfo[0] + 250MB
	$shrinkSize = [Math]::Ceiling($targetWinREPartitionSize / 1MB) * 1MB
	$targetOSPartitionSize = $OSPartition.Size - $shrinkSize
	if ($targetOSPartitionSize -lt $supportedSize.SizeMin)
	{
		LogMessage("Error: The target OS partition size after shrinking is smaller than the supported minimum size, cannot perform the repartition")
		exit 1
	}
}
else
{
	if ($WinREIsOnSystemPartition)
	{
		LogMessage("WinRE parititon is after the OS partition and it's also System partition")
		LogMessage("Error: Got unexpected disk layout, cannot proceed")
		exit 1
	}
	if (!($WinREPartitionIndex -eq ($OSPartition.PartitionNumber + 1)))
	{
		LogMessage("Error: WinRE partition is not right after the OS partition, cannot extend WinRE partition")
		exit 1
	}
	# Calculate the size of repartition
	# Will shrink OS partitition by 250 MB
	$shrinkSize = 250MB
	$targetOSPartitionSize = $OSPartition.Size - $shrinkSize
	$targetWinREPartitionSize = $WinREPartitionSizeInfo[0] + 250MB
	$UnallocatedSpace = $WinREPartition.Offset - $OSPartitionEnds;
	# If there is unallocated space, consider using it
	if ($UnallocatedSpace -ge 250MB)
	{
		$UnallocatedSpace = $WinREPartition.Offset - $OSPartitionEnds;
		LogMessage("Found unallocated space between OS and WinRE partition: " + $UnallocatedSpace)
		LogMessage("There is already enough space to extend WinRE partition without shrinking the OS partition")
		$NeedShrink = $false
		$targetOSPartitionSize = 0
	}
	else
	{
		$shrinkSize = [Math]::Ceiling((250MB - $UnallocatedSpace)/ 1MB) * 1MB
		if ($shrinkSize > 250MB)
		{
			$shrinkSize = 250MB
		}
		$targetOSPartitionSize = $OSPartition.Size - $shrinkSize
		if ($targetOSPartitionSize -lt $supportedSize.SizeMin)
		{
			LogMessage("Error: The target OS partition size after shrinking is smaller than the supported minimum size, cannot perform the repartition")
			exit 1
		}
	}
}
# ------------------------------------
# Report execution plan and ask for user confirmation to continue
# ------------------------------------
# Report the changes planned to be executed, waiting for user confirmation
LogMessage("")
LogMessage("Summary of proposed changes")
if ($NeedCreateNew)
{
	LogMessage("Note: WinRE partition is before OS partition, need to create a new WinRE partition after OS partition")
	LogMessage("Will shrink OS partition by " + $shrinkSize)
	LogMessage("  Current OS partition size: " + $OSPartition.Size)
	LogMessage("  Target OS partition size after shrinking: " + $targetOSPartitionSize)
	LogMessage("New WinRE partition will be created with size: ", $targetWinREPartitionSize)
	if ($WinREIsOnSystemPartition)
	{
		LogMessage("Existing WinRE partition is also system partition, it will be preserved")
	}
	else
	{
		LogMessage("Existing WinRE partition will be deleted")
		LogMessage("  WinRE partition: Disk [" + $OSDiskIndex + "] Partition [" + $WinREPartitionIndex + "]")
		LogMessage("  Current WinRE partition size: " + $WinREPartitionSizeInfo[0])
	}
}
else
{
	if ($NeedShrink)
	{
		LogMessage("Will shrink OS partition by " + $shrinkSize)
		LogMessage("  Current OS partition size: " + $OSPartition.Size)
		LogMessage("  Target OS partition size after shrinking: " + $targetOSPartitionSize)
		if ($UnallocatedSpace -ge 0)
		{
			LogMessage("Unallocated space between OS and WinRE partition that will be used towards the new WinRE partition: " + $UnallocatedSpace)
		}
	}
	else
	{
		LogMessage("Will use 250MB from unallocated space between OS and WinRE partition")
	}
	LogMessage("Will extend WinRE partition size by 250MB")
	LogMessage("  WinRE partition: Disk [" + $OSDiskIndex + "] Partition [" + $WinREPartitionIndex + "]")
	LogMessage("  Current WinRE partition size: " + $WinREPartitionSizeInfo[0])
	LogMessage("  New WinRE partition size:     " + $targetWinREPartitionSize)
	LogMessage("WinRE will be temporarily disabled before extending the WinRE partition and enabled automatically in the end")
	if ($UnallocatedSpace -ge 100MB)
	{
		LogMessage("Warning: More than 100MB of unallocated space was detected between the OS and WinRE partitions")
		LogMessage("Would you like to proceed by using the unallocated space between the OS and the WinRE partitions?")
	}
}
if ($Needbackup)
{
	LogMessage("")
	LogMessage("The contents of the old WinRE partition will be backed up to [" + $BackupFolder + "]")
}
LogMessage("")
LogMessage("Please reboot the device before running this script to ensure any pending partition actions are finalized")
LogMessage("")
if ($SkipConfirmation)
{
	LogMessage("User chose to skip confirmation")
	LogMessage("Proceeding with changes...")
}
else
{
	$userInput = Read-Host -Prompt "Would you like to proceed? Y for Yes and N for No"
		
	if ($userInput -ieq "Y")
	{
		LogMessage("Proceeding with changes...")
	}
	elseif ($userInput -ieq "N")
	{
		LogMessage("Canceling based on user request, no changes were made to the system")
		exit 0
	}
	else
	{
		LogMessage("Error: Unexpected user input: [" + $userInput + "]") 
		exit 0
	}
}
LogMessage("")
LogMessage("Note: To prevent unexpected results, please do not interrupt the execution or restart your system")
# ------------------------------------
# Do the actual execution
# The main flow is:
# 1. Check whether ReAgent.xml has stage location and clear it for repartiion
# 2. Disable WinRE as WinRE partition will be deleted
# 3. Perform the repartition to create a larger WinRE partition
# 4. Re-enable WinRE
# ------------------------------------
LogMessage("")
# Load ReAgent.xml to clear Stage location
LogMessage("Loading [" + $ReAgentXmlPath + "] ...")
$xml = [xml](Get-Content -Path $ReAgentXmlPath)
$node = $xml.WindowsRE.ImageLocation
if (($node.path -eq "") -And ($node.guid -eq "{00000000-0000-0000-0000-000000000000}") -And ($node.offset -eq "0") -And ($node.id -eq "0"))
{
	LogMessage("Stage location info is empty")
}
else
{
	LogMessage("Clearing stage location info...")
	$node.path = ""
	$node.offset = "0"
	$node.guid= "{00000000-0000-0000-0000-000000000000}"
	$node.id="0"
	# Save the change
	LogMessage("Saving changes to [" + $ReAgentXmlPath + "]...")
	$xml.Save($ReAgentXmlPath)
}
# Disable WinRE
LogMessage("Disabling WinRE...")
reagentc /disable
if (!($LASTEXITCODE -eq 0))
{
	LogMessage("Warning: encountered an error when disabling WinRE: " + $LASTEXITCODE)
	exit $LASTEXITCODE
}
# Verify WinRE is under C:\Windows\System32\Recovery\WinRE.wim
$disableWinREPath = Join-Path -Path $system32Path -ChildPath "\Recovery\WinRE.wim"
LogMessage("Verifying that WinRE wim exists in downlevel at default location")
if (!(Test-Path $disableWinREPath))
{
	LogMessage("Error: Cannot find " + $disableWinREPath)
	
	# Re-enable WinRE
	LogMessage("Re-enabling WinRE on error...")
	reagentc /enable
	if (!($LASTEXITCODE -eq 0))
	{
		LogMessage("Warning: encountered an error when enabling WinRE: " + $LASTEXITCODE)
	}
	exit 1
}
# ------------------------------------
# Perform the repartition
# 1. Resize the OS partition
# 2. Delete the WinRE partition
# 3. Create a new WinRE partition
# ------------------------------------
LogMessage("Performing repartition to extend the WinRE partition ...")
# 1. Resize the OS partition
if ($NeedShrink)
{
	LogMessage("Shrinking the OS partition to create a larger WinRE partition")
	LogMessage("Resizing the OS partition to: [" + $targetOSPartitionSize + "]...")
	Resize-Partition -DriveLetter $OSDrive -Size $targetOSPartitionSize
	if ($Error.Count -gt 0) {
		LogMessage("Error: Resize-Partition encountered errors: " + $Error[0].Exception.Message)
		
		# Re-enable WinRE
		LogMessage("Re-enabling WinRE on error...")
		reagentc /enable
		if (!($LASTEXITCODE -eq 0))
		{
			LogMessage("Warning: encountered an error when enabling WinRE: " + $LASTEXITCODE)
		}
		exit 1
	}
	$OSPartitionAfterShrink = Get-Partition -DriveLetter $OSDrive
	LogMessage("Target partition size: " + $targetOSPartitionSize)
	LogMessage("Size of OS partition after shrinking: " + $OSPartitionAfterShrink.Size)
}
# 2. Delete the WinRE partition
LogMessage("")
if ($WinREIsOnSystemPartition)
{
	LogMessage("Existing WinRE partition is System partition, skipping deletion")
}
else
{	
	# If requested by user, backup rest of the content on WinRE partition to backup directory
	if ($Needbackup)
	{
		$sourcePath = $WinREPartition.AccessPaths[0] 
		LogMessage("Copying content on WinRE partition from [" + $sourcePath + "] to [" + $BackupFolder + "]...")
		
		# Copy-Item may have access issue with certain system folders, enumerate the children items and exlcude them
		$items = Get-ChildItem -LiteralPath $sourcePath -Force
		foreach ($item in $items)
		{
			if ($item.Name -ieq "System Volume Information")
			{
				continue
			}
			$sourceItemPath = Join-Path -Path $sourcePath -ChildPath $item.Name
			$destItemPath = Join-Path -Path $BackupFolder -ChildPath $item.Name
			try 
			{
				LogMessage("Copying [" + $sourceItemPath + "] to [" + $destItemPath + "]...")
				Copy-Item -LiteralPath $sourceItemPath -Destination $destItemPath -Recurse -Force
			} catch 
			{
				LogMessage("Error: An error occurred during copy: $_")
				exit 1
			}
		}
		
		LogMessage("Backup completed")
		LogMessage("")
	}
	LogMessage("Deleting WinRE partition: Disk [" + $OSDiskIndex + "] Partition [" + $WinREPartitionIndex + "]...")
	Remove-Partition -DiskNumber $OSDiskIndex -PartitionNumber $WinREPartitionIndex -Confirm:$false
	if ($Error.Count -gt 0) {
		LogMessage("Error: Remove-Partition encountered errors: " + $Error[0].Exception.Message)
		exit 1
	}
}
# A short sleep for the partition change
Sleep 5
# 3. Create a new WinRE partition
LogMessage("")
LogMessage("Creating new WinRE partition...")
LogMessage("Target size: " + $targetWinREPartitionSize)
if ($diskType -ieq "GPT")
{
	$partition = New-Partition -DiskNumber $OSDiskIndex -Size $targetWinREPartitionSize -GptType "{de94bba4-06d1-4d40-a16a-bfd50179d6ac}"
	
	$newPartitionIndex = $partition.PartitionNumber
	# A short sleep to make sure the partition is ready for formatting
	Sleep 2
	LogMessage("Formating the partition...")
	$result = Format-Volume -Partition $partition -FileSystem NTFS -Confirm:$false
	if ($Error.Count -gt 0) {
		LogMessage("Error: Format-Volume encountered errors: " + $Error[0].Exception.Message)
		exit 1
	}
}
else
{
	#$partition = New-Partition -DiskNumber $OSDiskIndex -Size $targetWinREPartitionSize -MbrType 0x27
	$targetWinREPartitionSizeInMb = [int]($targetWinREPartitionSize/1MB)
	$diskpartScript = 
@"
select disk $OSDiskIndex
create partition primary size=$targetWinREPartitionSizeInMb id=27
format quick fs=ntfs label="Recovery"
set id=27
"@
	$TempPath = $env:Temp
	$diskpartSciptFile = Join-Path -Path $TempPath -ChildPath "\ExtendWinRE_MBR_PowershellScript.txt"
	
	LogMessage("Creating temporary diskpart script to create Recovery partition on MBR disk...")
	LogMessage("Temporary diskpart script file: " + $diskpartSciptFile)
	$diskpartScript | Out-File -FilePath $diskpartSciptFile -Encoding ascii
	
	LogMessage("Executing diskpart script...")
	try 
	{
		$diskpartOutput = diskpart /s $diskpartSciptFile
		
		if ($diskpartOutput -match "DiskPart successfully") 
		{
			LogMessage("Diskpart script executed successfully")
		}
		else
		{
			LogMessage("Error executing diskpart script:" + $diskpartOutput)
			exit 1
		}
		LogMessage("Deleting temporary diskpart script file...")
		Remove-Item $diskpartSciptFile
	}
	catch 
	{
		LogMessage("Error executing diskpart script: $_")
		exit 1
	}
	
	$vol = Get-Volume -FileSystemLabel "Recovery"
	$newPartitionIndex = (Get-Partition | Where-Object { $_.AccessPaths -contains $vol.Path } ).PartitionNumber
}
if ($Error.Count -gt 0) 
{
	LogMessage("Error: New-Partition encountered errors: " + $Error[0].Exception.Message)
	exit 1
}
LogMessage("New Partition index: " + $newPartitionIndex)
# Re-enable WinRE
LogMessage("Re-enabling WinRE...")
reagentc /enable
if (!($LASTEXITCODE -eq 0))
{
	LogMessage("Warning: encountered an error when enabling WinRE: " + $LASTEXITCODE)
	exit $LASTEXITCODE
}
# In the end, Display WinRE status to verify WinRE is enabled correctly
LogMessage("")
LogMessage("WinRE Information:")
$FinalWinREStatus = DisplayWinREStatus
$WinREStatus = $FinalWinREStatus[0]
$WinRELocation = $FinalWinREStatus[1]
if (!$WinREStatus)
{
	LogMessage("Warning: WinRE Disabled")
}
$WinRELocationItems = $WinRELocation.Split('\\')
foreach ($item in $WinRELocationItems)
{
	if ($item -like "partition*")
	{
		$WinREPartitionIndex = ExtractNumbers($item)
	}
}
LogMessage("WinRE Partition Index: " + $WinREPartitionIndex)
$WinREPartition = Get-Partition -DiskNumber $OSDiskIndex -PartitionNumber $WinREPartitionIndex
$WinREPartitionSizeInfoAfter = DisplayPartitionInfo($WinREPartition.AccessPaths)
LogMessage("")
LogMessage("OS Information:")
$OSPartition = Get-Partition -DriveLetter $OSDrive
LogMessage("OS partition size: " + $OSPartition.Size)
LogMessage("OS partition Offset: " + $OSPartition.Offset)
if (!($WinREPartitionIndex -eq $newPartitionIndex))
{
	LogMessage("Warning: WinRE is installed to partition [" + $WinREPartitionIndex +"], but the newly created Recovery partition is [" + $newPartitionIndex + "]")
}
LogMessage("End time: $([DateTime]::Now)")
if ($NeedBackup)
{
	LogMessage("")
	LogMessage("The contents of the old WinRE partition has been backed up to [" + $BackupFolder + "]")
}
LogMessage("")
LogMessage("Successfully completed the operation")