Bagikan melalui


Menambahkan paket pembaruan ke Windows RE

Anda dapat menerapkan pembaruan, baik LCU atau Pembaruan Dinamis OS Aman (DU) ke gambar Windows RE. Langkah-langkah untuk memperbarui gambar WINDOWS RE berbeda tergantung pada apakah Anda memperbarui gambar offline, atau gambar pada sistem yang sedang berjalan.

  • Saat menambahkan LCU: Keduanya sebelum menambahkan pembaruan, dan juga setelah Anda menambahkan pembaruan, periksa nomor versi WinRE untuk memastikan bahwa pembaruan diterapkan dengan benar.
  • Saat menambahkan paket DU: Setelah Anda menambahkan paket, periksa daftar paket dalam gambar untuk memastikan paket berhasil ditambahkan ke gambar.

Memperbarui gambar offline

Langkah-langkah di bawah ini mencakup cara menambahkan paket yang diperbarui ke gambar Windows RE offline .

Memasang gambar Windows Anda

Gambar Windows RE (winre.wim) disertakan di dalam gambar Windows (install.wim) dan akhirnya disalin ke partisi alat Windows RE pada PC atau perangkat tujuan. Untuk memodifikasi gambar WinRE, Anda harus terlebih dahulu memasang gambar Windows, lalu memasang gambar Windows RE. Setelah kedua gambar dipasang, Anda dapat membuat perubahan, melepas gambar WinRE, lalu melepas citra Windows.

  • Buat direktori pemasangan dan pasang install.wim:

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

Pasang gambar WinRE Anda

  • Pasang file Gambar RE Windows dari gambar yang dipasang.

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

    Tip

    Jika winre.wim tidak dapat dilihat di bawah direktori yang ditentukan, gunakan perintah berikut untuk mengatur file yang terlihat:

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

Tambahkan paket Pembaruan ke WinRE

Dengan gambar pemulihan yang dipasang, Anda dapat menambahkan pembaruan untuk memperbaiki masalah.

  1. Unduh paket pembaruan yang diperlukan dan tambahkan ke gambar pemulihan Anda.

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

    or

    Dism /Add-Package /Image:C:\mount\ /PackagePath:"c:\downloadedupdate\dynamicupdate.cab" 
    
  2. Jika Anda menambahkan paket Pembaruan Dinamis, validasi bahwa paket yang Anda tambahkan ada di gambar Anda:

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

    Periksa daftar untuk paket pembaruan yang baru saja Anda tambahkan. Paket harus menyertakan nomor KB, dan akan menunjukkan State seolah-olah Installed telah berhasil ditambahkan:

    Package Identity : Package_for_KB5021041~31bf3856ad364e35~amd64~~22621.815.1.0
    State : Installed
    Release Type : Update
    
  3. Bersihkan gambar pemulihan Anda dan reset dasar komponen yang digantikan:

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

Melepas citra Anda

  1. Tutup semua aplikasi yang mungkin mengakses file dari gambar, termasuk File Explorer.

  2. Terapkan perubahan dan lepaskan gambar Windows RE:

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

    Proses ini memerlukan waktu beberapa menit.

  3. Terapkan perubahan dan lepaskan gambar Windows:

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

    Di mana C adalah huruf kandar drive yang berisi gambar. Proses ini mungkin membutuhkan waktu beberapa menit.

Gambar Windows RE sekarang diperbarui dan bagian dari gambar Windows yang lebih besar.

Menerapkan pembaruan ke PC yang sedang berjalan

Anda dapat menerapkan perbaikan pada gambar Windows Recovery pada PC yang sedang berjalan. Langkah-langkah berikut memanmbing Anda memasang gambar Windows Recovery, menerapkan pembaruan ke gambar tersebut, lalu menyimpan perubahan:

  1. Buka Prompt Perintah sebagai administrator.

  2. Buat direktori tempat Anda dapat memasang gambar pemulihan untuk membuat perubahan pada gambar tersebut.

    md c:\mount 
    
  3. Pasang gambar pemulihan Anda dengan REAgentC:

    ReAgentC.exe /mountre /path c:\mount 
    
  4. Dengan gambar pemulihan yang dipasang, Anda dapat mengunduh dan menambahkan paket pembaruan ke gambar Windows RE.

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

    or

    Dism /Add-Package /Image:C:\mount\ /PackagePath:"c:\downloadedupdate\dynamicupdate.cab" 
    
  5. Jika Anda menambahkan paket Pembaruan Dinamis, validasi bahwa paket yang Anda tambahkan ada di gambar Anda:

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

    Periksa daftar untuk paket pembaruan yang baru saja Anda tambahkan. Paket harus menyertakan nomor KB, dan akan menunjukkan State seolah-olah Installed telah berhasil ditambahkan:

    Package Identity : Package_for_KB5021041~31bf3856ad364e35~amd64~~22621.815.1.0
    State : Installed
    Release Type : Update
    
  6. Bersihkan gambar pemulihan Anda dan reset dasar komponen yang digantikan:

    dism /image:C:\mount /cleanup-image /StartComponentCleanup /ResetBase 
    
  7. Melepas citra pemulihan Windows:

    ReAgentC.exe /unmountre /path c:\mount /commit 
    
  8. Jika disk PC dilindungi oleh BitLocker atau Enkripsi Perangkat: Gunakan ReagentC untuk menonaktifkan lalu mengaktifkan kembali Windows RE. Ini memastikan bahwa gambar Windows RE yang diperbarui diaktifkan dan dikonfigurasi dengan benar untuk penginstalan Windows Anda:

    reagentc /disable
    reagentc /enable 
    

Citra WINDOWS RE pada PC yang sedang berjalan sekarang diperbarui.

Periksa versi gambar WinRE

Anda dapat memeriksa nomor versi gambar WinRE pada penginstalan Windows online dan offline. Ini dapat membantu untuk memeriksa versi WinRE sebelum menambahkan pembaruan, lalu setelah menerapkan pembaruan untuk memverifikasi bahwa pembaruan berhasil ditambahkan.

Catatan

Nomor versi WinRE hanya akan berubah setelah Anda menambahkan LCU. Jika Anda menambahkan paket DU, gunakan DISM /get-packages seperti yang dijelaskan dalam langkah-langkah di atas untuk memastikan bahwa paket telah ditambahkan ke gambar.

Memvalidasi versi WINDOWS RE di OS Windows Online

  1. Gunakan ReagentC untuk menemukan lokasi gambar WinRE yang diinstal dengan menjalankan perintah berikut:

    reagentc /info
    

    Perintah ini mengembalikan lokasi WINDOWS RE yang menyerupai contoh berikut:

    \\?\GLOBALROOT\device\harddisk0\partition4\Recovery\WindowsRE
    
  2. Gunakan DISM untuk mendapatkan informasi versi tentang gambar winre.wim yang terletak di jalur yang dikembalikan oleh ReagentC pada langkah sebelumnya. Pastikan untuk menambahkan nama gambar WinRE dan nomor indeks gambar ke jalur saat Anda menjalankan perintah:

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

    Perhatikan versi yang dilaporkan. Contohnya:

    Version : 10.0.22621
    ServicePack Build : 1
    ServicePack Level : 0
    

    Pastikan bahwa ServicePackBuild lebih besar dari atau sama dengan UBR untuk pembaruan yang Anda tambahkan. Misalnya, untuk Windows 11, versi 22H2, pembaruan keamanan November akan ditampilkan 819 sebagai SerivcePack Build, karena nomor versi lengkap untuk pembaruan tersebut adalah 22621.819.

    • Jika versi yang dilaporkan adalah versi yang lebih lama, ini menunjukkan gambar Windows RE tidak diperbarui.
    • Jika versi yang dilaporkan sama atau versi yang lebih baru, tidak ada tindakan yang diperlukan.

Memvalidasi versi WINDOWS RE di OS Windows Offline

  1. Pasang gambar Windows ke folder lokal, misalnya C:\mount\windows:

    mkdir C:\mount\windows
    Dism /Mount-Image /ImageFile:C:\mount\install.wim /Index:1 /MountDir:C:\mount\windows
    
  2. Gunakan DISM untuk mendapatkan informasi versi tentang gambar winre.wim yang terletak di Windows\system32\recovery folder. Pastikan untuk menentukan nomor indeks gambar saat Anda menjalankan perintah:

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

    Perhatikan versi yang dilaporkan. Contohnya:

    Version : 10.0.22621
    ServicePack Build : 1
    ServicePack Level : 0
    

    Pastikan bahwa ServicePackBuild lebih besar dari atau sama dengan UBR untuk pembaruan yang Anda tambahkan. Misalnya, untuk Windows 11, versi 22H2, pembaruan keamanan November akan ditampilkan 819 sebagai SerivcePack Build, karena nomor versi lengkap untuk pembaruan tersebut adalah 22621.819.

    • Jika versi yang dilaporkan adalah versi yang lebih lama, ini menunjukkan gambar Windows RE tidak diperbarui.
    • Jika versi yang dilaporkan sama atau versi yang lebih baru, tidak ada tindakan yang diperlukan.

Memperluas Partisi WINDOWS RE

Contoh skrip di bawah ini dapat digunakan untuk meningkatkan ukuran partisi pemulihan agar berhasil memperbarui Windows Recovery Environment (WinRE). Disarankan untuk memiliki 250MB ruang kosong di partisi pemulihan agar pembaruan WinRE berhasil diinstal. Pada perangkat yang mungkin tidak memiliki ruang kosong yang memadai dalam partisi pemulihan, skrip sampel di bawah ini dapat digunakan untuk memperluas partisi pemulihan sebesar 250 MB.

Reboot komputer Anda sebelum Anda menjalankan skrip. Ini sangat penting karena mungkin ada operasi partisi tertunda yang dipentaskan pada komputer Anda yang perlu diselesaikan sebelum skrip dapat dengan aman meningkatkan ukuran partisi WinRE. Setelah komputer Anda memulai ulang, buka Powershell sebagai admin dan jalankan jalur mkdir <ke direktori> cadangan baru untuk membuat direktori cadangan yang dapat digunakan skrip jika terjadi kegagalan untuk memulihkan partisi asli. Perhatikan lokasi direktori cadangan ini karena skrip akan meminta jalur cadangan Anda. Jika Anda menyebarkan ini dalam skala besar, Anda dapat melewati permintaan skrip dengan menggunakan parameter

"<File> skrip -SkipConfirmation $true -BackupFolder <folder for backup>"

Contohnya,

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")