Keep File Explorer’s restore size in Windows 11

Fix Windows 11 File Explorer opening at full work-area size when Restore Down does nothing. Correct the saved WinPos rectangle safely.
واتسآب
لينكدإن
فيسبوك
تويتر
تليجرام
الإيميل

اقرأ هذا المقال بالعربية

File Explorer · window size

The window opens almost maximized, and Restore Down brings it back to the same rectangle. Editing the numbers once does not last, because closing the window while it is maximized writes those numbers again. From the start, save a normal size, then run a per-user guard that refuses to treat the maximized frame as the restore size.

Hands-on article · 20 October 2026 · Windows 11, one display or an external monitor

Symptoms

This is a common Windows 11 behavior, and it is weaker than the way Windows 10 and Windows 7 remembered a window:

  1. A File Explorer window opens covering almost the whole desktop, and the middle caption button is Restore Down.
  2. Restore Down leaves the window large, because the saved “normal” rectangle is the work area or the maximized frame.
  3. If you resize the window and close it while it is not maximized, the next window remembers that size.
  4. If you maximize it and close it while it is large, the good size is replaced by the large frame. The problem returns even after a manual registry edit.
  5. After a restart, especially on a laptop with an external display, a new window can open large again.

Why Restore fails, and why the size comes back

File Explorer stores the size and position of the last window you closed. It does not keep a separate size for every folder. For your account, that rectangle lives here:

HKEY_CURRENT_USERSoftwareClassesLocal SettingsSoftwareMicrosoftWindowsShellBagsAllFoldersShell

Each display arrangement has four values:

WinPos1920x1080x96(1).left
WinPos1920x1080x96(1).top
WinPos1920x1080x96(1).right
WinPos1920x1080x96(1).bottom
  • Primary screen resolution, such as 1920x1080. Two 1920×1080 monitors still use 1920x1080. The name does not become 3840x1080.
  • The DPI number for your scale: 100% = 96, 125% = 120, 150% = 144, 175% = 168, 200% = 192.
  • The number in parentheses, such as (1) or (2), separates display arrangements Windows has seen. With two monitors the open window uses slot (2). Slot (1) is used when Windows sees one display, including the moment at startup before the external screen is ready.

The four numbers are the restore rectangle in pixels. Restore Down shows that rectangle as stored. When it equals the work area, or the frame of a maximized window, the window stays large.

The dashed frame is the work area. The inner frame is the last normal size Restore should keep.

A real 1920×1080, 100% scale machine

The first screen’s work area was 0,0 → 1920,1032. That rectangle makes Restore a no-op.

After a maximize on the second screen, Explorer stored a real maximized frame: 1911,3 → 3847,1051, a few pixels outside the panel because of the invisible border.

The last normal size was 155,305 → 1471,870.

One shared value, ShowCmd, sits beside those edges:

ValueHow the next window opens
1At the WinPos rectangle
3Maximized, using WinPos when you click Restore Down

On Windows 10, closing a maximized window kept the previous restore rectangle. On Windows 11, the current frame is written into WinPos. ShowCmd often stays 1, so the next window opens large immediately and Restore has no smaller rectangle to return to.

Correcting the numbers once therefore fixes only the current open. The next close while maximized writes the large frame again, into the two-monitor slot or into the one-monitor slot at shutdown. Very large MinPos and MaxPos numbers such as 4294967295 are an unused internal position. Leave them alone.

What the complete fix does

The fix has two parts, in this order. The first plants the size you want. The second stops a maximized close from replacing it.

What you doWhat is kept as the restore size
Close the window at a normal sizeThat size becomes the restore size
Maximize, then close it while it is largeThe large frame is discarded. The last normal size stays
Restart the PCThe guard starts again at sign-in and applies the same rule

The guard is a small program in your account. It watches the WinPos values only. A normal rectangle is remembered. A rectangle that matches the work area or the maximized frame, within about 24 pixels, is replaced with the last normal size a moment later. It also copies that normal size onto other slots for the same resolution and scale, including the one-monitor slot read early in startup.

The guard’s own memory is stored in HKEY_CURRENT_USERSoftwareExplorerRestoreGuard. It does not change ShowCmd, delete folder history, restart explorer.exe, or touch system files. Maximize still works. What it refuses is storing the large frame as the restore size.

What to leave alone

Do not delete the Bags or BagMRU keys. Deleting them clears remembered folder views and is unnecessary for this fix. Close folder windows before you read the registry, so a later close does not overwrite the size you just saved. A mistyped size only makes Explorer open at the size of the last window you closed while it was not maximized.

Apply the fix from the start

Follow this order. Closing once at a normal size plants the number the last step will protect.

1. Close one window at the size you want

  1. Open File Explorer.
  2. If the window covers the screen, click Restore Down. If it stays large, drag an edge or corner. If an edge is off-screen, press Alt+Space, choose Size, nudge it with the arrow keys, and press Enter.
  3. Set the width, height, and position. Leave the window restored, not maximized.
  4. Close it with the Close button, and close any other Explorer windows.

That writes the good size into the slot for the monitors connected right now.

2. Back up the key

  1. Press Win+R, type regedit, and press Enter.
  2. Paste this path into the address bar:
ComputerHKEY_CURRENT_USERSoftwareClassesLocal SettingsSoftwareMicrosoftWindowsShellBagsAllFoldersShell
  1. Right-click Shell and choose Export.
  2. Save the file on the desktop as Explorer-WinPos-backup.reg.

3. Confirm a real size is stored

Open Settings → System → Display. Note the resolution and Scale, and match Scale to the DPI number in the value name:

ScaleNumber in the value name
100%96
125%120
150%144
175%168
200%192

On a 1920×1080 screen at 100%, look at names that start with WinPos1920x1080x96. This command only reads:

$path = 'HKCU:SoftwareClassesLocal SettingsSoftwareMicrosoftWindowsShellBagsAllFoldersShell'
Get-ItemProperty $path |
  ForEach-Object { $_.PSObject.Properties } |
  Where-Object { $_.Name -like 'WinPos*' -or $_.Name -eq 'ShowCmd' } |
  Sort-Object Name |
  Select-Object Name, Value |
  Format-Table -AutoSize
  • A good slot is clearly smaller than the screen. It is usually the size you closed in step 1.
  • A bad slot matches the work area, or sticks out past the screen by about 7 to 24 pixels. The second-monitor example is 1911, 3, 3847, 1051.

You do not type the numbers yourself when at least one slot is already a real size. When the guard starts, it copies that size onto any other slot for the same resolution and DPI that still fills the screen.

If every slot for your current scale is full-screen, repeat step 1 and close the window while it is not maximized. If you cannot drag the edges, type a window centered in the work area in Registry Editor and choose base Decimal. For a 1920×1032 work area and a 1200×800 window:

left   = (1920 - 1200) / 2 = 360
top    = (1032 - 800)  / 2 = 116
right  = 360 + 1200        = 1560
bottom = 116 + 800         = 916

Set ShowCmd to 1 so Explorer opens at that size directly.

4. Start the guard that ignores a maximized close

Press Win+R, paste %LOCALAPPDATA%ExplorerRestoreGuard, and press Enter. Create the folder if it is missing. Save two files there with these exact names. In Notepad, choose Save as type “All files” so it does not add .txt.

The first file is ExplorerRestoreGuard.ps1:

# Keeps File Explorer's restore rectangle when a window is closed while maximized.
# Windows 11 writes the maximized frame into WinPos. This watcher puts the last
# normal size back and remembers that size for the next close.
$ErrorActionPreference = 'Stop'

$mutex = New-Object System.Threading.Mutex($false, 'LocalExplorerRestoreGuard')
if (-not $mutex.WaitOne(0)) { exit 0 }

$ShellRel = 'SoftwareClassesLocal SettingsSoftwareMicrosoftWindowsShellBagsAllFoldersShell'
$GuardRel = 'SoftwareExplorerRestoreGuard'
$LogPath = Join-Path $env:LOCALAPPDATA 'ExplorerRestoreGuardguard.log'
$EdgeSlack = 24

Add-Type -AssemblyName System.Windows.Forms
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public static class ExplorerGuardNative {
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int RegNotifyChangeKeyValue(
        SafeHandle hKey, bool bWatchSubtree, uint dwNotifyFilter, IntPtr hEvent, bool fAsynchronous);
}
"@

function Write-Log([string]$message) {
    $line = '{0:yyyy-MM-dd HH:mm:ss} {1}' -f (Get-Date), $message
    Add-Content -Path $LogPath -Value $line -Encoding UTF8
    if ((Get-Item $LogPath).Length -gt 65536) {
        $tail = Get-Content $LogPath -Tail 80
        Set-Content -Path $LogPath -Value $tail -Encoding UTF8
    }
}

function Convert-ToInt([object]$value) {
    $n = [int64]$value
    if ($n -gt 2147483647) { $n -= 4294967296 }
    return [int]$n
}

function Get-Monitors {
    $list = New-Object System.Collections.Generic.List[object]
    foreach ($screen in [System.Windows.Forms.Screen]::AllScreens) {
        $work = $screen.WorkingArea
        $bounds = $screen.Bounds
        $list.Add([pscustomobject]@{
            WL = $work.Left; WT = $work.Top; WR = $work.Right; WB = $work.Bottom
            ML = $bounds.Left; MT = $bounds.Top; MR = $bounds.Right; MB = $bounds.Bottom
        }) | Out-Null
    }
    return $list
}

function Test-Near([int]$a, [int]$b) {
    return [Math]::Abs($a - $b) -le $EdgeSlack
}

function Test-PoisonedRect([int]$left, [int]$top, [int]$right, [int]$bottom, $monitors) {
    $width = $right - $left
    $height = $bottom - $top
    if ($width -lt 400 -or $height -lt 300) { return $false }
    foreach ($m in $monitors) {
        $workWidth = $m.WR - $m.WL
        $workHeight = $m.WB - $m.WT
        $monWidth = $m.MR - $m.ML
        $monHeight = $m.MB - $m.MT
        $nearWork = (Test-Near $left $m.WL) -and (Test-Near $top $m.WT) -and (Test-Near $right $m.WR) -and (Test-Near $bottom $m.WB)
        $nearMonitor = (Test-Near $left $m.ML) -and (Test-Near $top $m.MT) -and (Test-Near $right $m.MR) -and (Test-Near $bottom $m.MB)
        $coversWork = ($width -ge ($workWidth - $EdgeSlack)) -and ($height -ge ($workHeight - $EdgeSlack)) -and (Test-Near $left $m.WL) -and (Test-Near $top $m.WT)
        $coversMonitor = ($width -ge ($monWidth - $EdgeSlack)) -and ($height -ge ($monHeight - $EdgeSlack)) -and (Test-Near $left $m.ML) -and ($top -le ($m.MT + $EdgeSlack))
        if ($nearWork -or $nearMonitor -or $coversWork -or $coversMonitor) { return $true }
    }
    return $false
}

function Get-GuardKey {
    return [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey($GuardRel)
}

function Read-Groups {
    $shell = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($ShellRel, $true)
    $groups = @{}
    foreach ($name in $shell.GetValueNames()) {
        if ($name -notmatch '^WinPos(.+).(left|top|right|bottom)$') { continue }
        $id = $Matches[1]
        $edge = $Matches[2]
        if (-not $groups.ContainsKey($id)) {
            $groups[$id] = @{ left = $null; top = $null; right = $null; bottom = $null }
        }
        $groups[$id][$edge] = Convert-ToInt $shell.GetValue($name)
    }
    return @{ Shell = $shell; Groups = $groups }
}

function Save-Good([string]$id, [int]$left, [int]$top, [int]$right, [int]$bottom) {
    $guard = Get-GuardKey
    $guard.SetValue("$id.left", $left, 'DWord')
    $guard.SetValue("$id.top", $top, 'DWord')
    $guard.SetValue("$id.right", $right, 'DWord')
    $guard.SetValue("$id.bottom", $bottom, 'DWord')
}

function Get-SavedGood([string]$id) {
    $guard = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($GuardRel, $false)
    if ($null -eq $guard) { return $null }
    $edges = @('left', 'top', 'right', 'bottom')
    $rect = @{}
    foreach ($edge in $edges) {
        $raw = $guard.GetValue("$id.$edge")
        if ($null -eq $raw) { return $null }
        $rect[$edge] = Convert-ToInt $raw
    }
    return $rect
}

function Get-SiblingGood([string]$id, $groups, $monitors) {
    $prefix = ($id -replace '(d+)$', '')
    foreach ($other in ($groups.Keys | Sort-Object)) {
        if ($other -eq $id) { continue }
        if (-not $other.StartsWith($prefix)) { continue }
        $g = $groups[$other]
        if ($null -eq $g.left) { continue }
        if (Test-PoisonedRect $g.left $g.top $g.right $g.bottom $monitors) { continue }
        return $g
    }
    return $null
}

function Write-Rect($shell, [string]$id, $rect) {
    $shell.SetValue("WinPos$id.left", [int]$rect.left, 'DWord')
    $shell.SetValue("WinPos$id.top", [int]$rect.top, 'DWord')
    $shell.SetValue("WinPos$id.right", [int]$rect.right, 'DWord')
    $shell.SetValue("WinPos$id.bottom", [int]$rect.bottom, 'DWord')
}

function Repair-Positions {
    $monitors = @(Get-Monitors)
    if ($monitors.Count -eq 0) { return }
    $state = Read-Groups
    $shell = $state.Shell
    $groups = $state.Groups

    foreach ($id in @($groups.Keys)) {
        $g = $groups[$id]
        if ($null -eq $g.left -or $null -eq $g.top -or $null -eq $g.right -or $null -eq $g.bottom) { continue }
        if (Test-PoisonedRect $g.left $g.top $g.right $g.bottom $monitors) { continue }
        Save-Good $id $g.left $g.top $g.right $g.bottom
    }

    foreach ($id in @($groups.Keys)) {
        $g = $groups[$id]
        if ($null -eq $g.left -or $null -eq $g.top -or $null -eq $g.right -or $null -eq $g.bottom) { continue }
        if (-not (Test-PoisonedRect $g.left $g.top $g.right $g.bottom $monitors)) { continue }

        $good = Get-SavedGood $id
        if ($null -ne $good -and (Test-PoisonedRect $good.left $good.top $good.right $good.bottom $monitors)) {
            $good = $null
        }
        if ($null -eq $good) { $good = Get-SiblingGood $id $groups $monitors }
        if ($null -eq $good) {
            $work = $monitors[0]
            $width = 1200
            $height = 800
            $workWidth = $work.WR - $work.WL
            $workHeight = $work.WB - $work.WT
            if ($width -gt $workWidth - 80) { $width = $workWidth - 80 }
            if ($height -gt $workHeight - 80) { $height = $workHeight - 80 }
            $left = $work.WL + [int](($workWidth - $width) / 2)
            $top = $work.WT + [int](($workHeight - $height) / 2)
            $good = @{ left = $left; top = $top; right = ($left + $width); bottom = ($top + $height) }
        }

        Write-Rect $shell $id $good
        Save-Good $id $good.left $good.top $good.right $good.bottom
        Write-Log ("restored WinPos{0} from {1},{2},{3},{4} to {5},{6},{7},{8}" -f $id, $g.left, $g.top, $g.right, $g.bottom, $good.left, $good.top, $good.right, $good.bottom)
    }
}

Write-Log 'started'
Repair-Positions

$notifyEvent = New-Object System.Threading.AutoResetEvent($false)
$shellKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($ShellRel, $false)
$useNotify = $false
try {
    $hr = [ExplorerGuardNative]::RegNotifyChangeKeyValue($shellKey.Handle, $false, 4, $notifyEvent.SafeWaitHandle.DangerousGetHandle(), $true)
    $useNotify = ($hr -eq 0)
    Write-Log ("notify registration {0}" -f $hr)
} catch {
    Write-Log ("notify unavailable: {0}" -f $_.Exception.Message)
}

while ($true) {
    if ($useNotify) {
        $signaled = $notifyEvent.WaitOne(5000)
        if ($signaled) { Start-Sleep -Milliseconds 450 }
        $hr = [ExplorerGuardNative]::RegNotifyChangeKeyValue($shellKey.Handle, $false, 4, $notifyEvent.SafeWaitHandle.DangerousGetHandle(), $true)
        if ($hr -ne 0) { $useNotify = $false }
    } else {
        Start-Sleep -Seconds 1
    }
    try {
        Repair-Positions
    } catch {
        Write-Log ("repair error: {0}" -f $_.Exception.Message)
    }
}

The second file, in the same folder, is start.vbs. It starts the guard without a console window:

Set shell = CreateObject("Wscript.Shell")
script = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "ExplorerRestoreGuard.ps1"
shell.Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File """ & script & """", 0, False

Then, from PowerShell, with Explorer windows closed, install it for sign-in and start it now:

$dir = Join-Path $env:LOCALAPPDATA 'ExplorerRestoreGuard'
$startup = Join-Path $env:APPDATA 'MicrosoftWindowsStart MenuProgramsStartupExplorerRestoreGuard.vbs'
Copy-Item (Join-Path $dir 'start.vbs') $startup -Force
Start-Process wscript.exe -ArgumentList '//B', (Join-Path $dir 'start.vbs')
Start-Sleep -Seconds 2
Get-Content (Join-Path $dir 'guard.log') -Tail 20

A started line means the guard is running. A restored WinPos... line means it found a full-screen slot and put the last normal size back. notify registration 0 means it is waiting for Explorer’s next write.

Check both behaviors

  1. Open Explorer, change the size a little while it is not maximized, and close it. The next window opens at that new size, because a normal close is kept.
  2. Maximize the window and close it while it is large. Within about a second the WinPos numbers return to the previous normal size, and a new window opens at that size. guard.log names the large edges that were rejected and the edges that were restored.
  3. Restart the PC and open Explorer. The guard starts at sign-in, and the normal size is still the restore size, including the one-monitor slot.
The fix is complete when both are true a normal close updates the restore size, and a close while the window is large does not. Changing Scale later moves Windows to another set, such as x120 or x144. Close one window at the size you want on the new scale, and the guard covers the rest.

Turn the guard off and undo

  1. Press Win+R, paste shell:startup, and delete ExplorerRestoreGuard.vbs.
  2. In Task Manager, end the powershell.exe process whose command line contains ExplorerRestoreGuard.ps1.
  3. To clear the guard’s memory, delete HKEY_CURRENT_USERSoftwareExplorerRestoreGuard and the folder %LOCALAPPDATA%ExplorerRestoreGuard.
  4. To put the window numbers back as they were before any edit, double-click Explorer-WinPos-backup.reg and confirm.
In short Restore Down shows the WinPos rectangle. Windows 11 replaces it with the maximized frame on close. Close Explorer once at the size you want, then leave the guard in your account to put that size back whenever the full-screen frame is written. A maximized close is not counted as the restore size.

A local how-to for Windows 11. The sample numbers come from a two-monitor 1920×1080 desktop at 100% scale. The guard reads your own screens. It only needs one close at a normal size before you start it.

بامكانك تثبيت التطبيق A7meD KaMeL من جوجل بلاي او App Store لتتمكن من تحميل الملفات المرفقة بسهولة بعد تسجيل الدخول في التطبيق.
أو قم بالتسجيل او تسجيل الدخول للتحميل من الموقع الآن
أحدث المقالات

قد يعجبك أيضاً

شرح إصلاح فتح مستكشف ملفات ويندوز 11 بحجم الشاشة، ولماذا لا يغيّر زر Restore الحجم، مع خطوات آمنة دون حذف إعدادات المجلدات.

حجم استعادة مستكشف الملفات في ويندوز 11 يبقى كما اخترته

ويندوز 11 يكتب إطار النافذة المكبرة مكان حجم Restore في مستكشف الملفات. الخطوات تثبّت آخر حجم عادي، ثم تشغّل حماية في حسابك تتجاهل أي إغلاق
How to Fix the "Duplicate Display Not Working" Issue in Windows

How to Fix the “Duplicate Display Not Working” Issue in Windows

Many Windows users face a frustrating problem when trying to use the Duplicate Display option to show the same screen on both a laptop and

حل مشكلة عدم عمل خيار تكرار الشاشة (Duplicate Display) في ويندوز

حل مشكلة عدم عمل خيار تكرار الشاشة (Duplicate Display) في ويندوز

يواجه العديد من مستخدمي أنظمة تشغيل ويندوز مشكلة عند محاولة استخدام خيار Duplicate Display (تكرار العرض) لعرض نفس الصورة على شاشة الحاسوب المحمول والشاشة الخارجية

تحميل ويندوز 11 برو (Windows 11 Professional) 2025 - ملف ISO مُفعّل مسبقًا

تحميل ويندوز 11 برو (Windows 11 Professional) 2025 – ملف ISO مُفعّل مسبقًا

هل تبحث عن تحميل ويندوز 11 برو Download windows 11 Pro جاهز ومفعّل مسبقًا؟ نقدم لك اليوم النسخة الأحدث لعام 2025، بصيغة ISO متعددة اللغات

How to Install MS Office 365 with Lifetime Activation تثبيت وتفعيل برامج ميكروسوفت اوفيس 365 مدى الحياة
مميز

شرح تثبيت برامج ميكروسوفت أوفيس 365 لعام 2025 مع التفعيل

في تلك المقالة شرح كامل بالفيديو لكيفية تثبيت برامج ميكروسوفت أوفيس 365 بأحدث الإصدارات لعام 2025 وبشكل رسمي 100% من موقع ميكروسوفت الرسمي. وأيضا شرح

تفعيل ويندوز 10 جميع الاصدارات في خطوة واحدة - ملف تفعيل

تفعيل ويندوز 10 جميع الاصدارات في خطوة واحدة – ملف تفعيل

يحتاج منا الكثير الى ملف تفعيل ويندوز 10، تفعيل حقيقي وبدون أية اضرار على جهاز الكمبيوتر او اللابتوب. نوفر لك هنا ملف تفعيل حقيقي بعيد