云计算百科
云计算领域专业知识百科平台

10、【MOD开发】【骑砍2】运行内存:三个 bat 脚本的分工与执行顺序

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

10、【MOD开发】【骑砍2】运行内存:三个 bat 脚本的分工与执行顺序

背景

上篇 【MOD开发】【骑砍2】运行内存:OOM 现场与虚拟内存术语 把现场和术语讲清楚了:OOM(Out of Memory,内存耗尽)的直接原因是提交量耗尽,不是某个 MOD(Modification,模组)抛了 C# 异常;16GB 内存加约 13GB 页面文件,提交限制只有约 30GB;游戏约 11GB、Steam 与 steamwebhelper 约 4.5GB,再叠加其他进程,页面文件只剩 270MB;此时申请 2.3MB 也会失败,0xC0000005 只是失败后的兜底崩溃。

判断清楚之后,剩下的是把“扩页面文件”变成可重复执行的操作。本篇给出三个 bat 脚本:一个写入配置,一个验证结果,一个负责回滚。脚本全文放在本篇,语法细节留到下一篇拆解。


骑砍2

🧩 三个脚本的分工

维度结果用途
pagefile-apply.bat 关闭自动管理,写入 C 盘 8GB、D 盘 32GB 首次修复;管理员运行,之后重启
pagefile-check.bat 检查配置、实际分配、提交余量、提交量最高的进程和 2004 事件 重启后验证;普通权限即可
pagefile-restore.bat 恢复自动管理,删除自定义页面文件配置 需要回滚;管理员运行,之后重启

三个脚本的分工是“写入 → 重启 → 验证”,回滚是独立路径。不要把 restore 和 apply 连续执行,否则会把刚写入的配置又清掉。


🛠️ pagefile-apply.bat

apply 只做三件事:确认管理员权限、关闭自动管理并写入 PagingFiles、打印修改前后的配置。脚本内容如下:

@echo off
setlocal
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Please run as Administrator.
pause
exit /b 1
)

echo ============================================================
echo BEFORE
echo ============================================================
powershell -NoProfile -Command "Get-CimInstance Win32_ComputerSystem | Select-Object AutomaticManagedPagefile | Format-List; Get-CimInstance Win32_PageFileSetting | Select-Object Name,InitialSize,MaximumSize | Format-Table -AutoSize; $mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; 'PagingFiles registry:'; (Get-ItemProperty -Path $mm -Name PagingFiles).PagingFiles"

echo.
echo Applying C: 8192 MB and D: 32768 MB via PagingFiles registry …
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop'; $mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; $cs=Get-CimInstance Win32_ComputerSystem; if($cs.AutomaticManagedPagefile){ $cs | Set-CimInstance -Property @{AutomaticManagedPagefile=$false} }; try { Get-CimInstance Win32_PageFileSetting | Remove-CimInstance -ErrorAction Stop } catch { }; Set-ItemProperty -Path $mm -Name PagingFiles -Value @('C:\\pagefile.sys 8192 8192','D:\\pagefile.sys 32768 32768') -Type MultiString; 'Applied.'"

echo.
echo ============================================================
echo AFTER (effective after reboot)
echo ============================================================
powershell -NoProfile -Command "$mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; Get-CimInstance Win32_ComputerSystem | Select-Object AutomaticManagedPagefile | Format-List; 'PagingFiles registry:'; (Get-ItemProperty -Path $mm -Name PagingFiles).PagingFiles; 'Win32_PageFileSetting (may lag until reboot):'; Get-CimInstance Win32_PageFileSetting | Select-Object Name,InitialSize,MaximumSize | Format-Table -AutoSize"

echo.
echo DONE. Reboot Windows, then run pagefile-check.bat.
pause

脚本执行后,AFTER 段应看到 AutomaticManagedPagefile 为 False,PagingFiles 为两行:

C:\\pagefile.sys 8192 8192
D:\\pagefile.sys 32768 32768

这里的 8192 和 32768 单位是 MB,两个数字分别是初始大小和最大大小。C: 保留 8GB 是为了兼顾系统盘的内核转储需求;D: 放 32GB 是为了把提交限制抬高。两个值都不是固定公式,而是按本次峰值和磁盘空间取的折中。

配置写入注册表后不会立刻改变磁盘上的 pagefile.sys。必须重启 Windows,系统才会按新配置创建或调整页面文件。不要在写入后直接看任务管理器里的“提交大小”就判断失败;重启前的数字仍然是旧配置。


🔍 pagefile-check.bat

check 负责回答三个问题:配置写对了吗、系统实际分配了吗、当前提交余量够不够。脚本内容如下:

@echo off
setlocal

echo ============================================================
echo Configuration
echo ============================================================
powershell -NoProfile -Command "$mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; $cs=Get-CimInstance Win32_ComputerSystem; 'AutomaticManagedPagefile = ' + $cs.AutomaticManagedPagefile; 'PagingFiles registry:'; (Get-ItemProperty -Path $mm -Name PagingFiles).PagingFiles; 'Win32_PageFileSetting:'; Get-CimInstance Win32_PageFileSetting | Select-Object Name,InitialSize,MaximumSize | Format-Table -AutoSize"

echo ============================================================
echo Validation
echo ============================================================
powershell -NoProfile -Command "$s=Get-CimInstance Win32_PageFileSetting; $c=$s | Where-Object {$_.Name -eq 'C:\\pagefile.sys'}; if(-not $c){ Write-Host 'WARNING: C:\\pagefile.sys setting missing.' -ForegroundColor Yellow } elseif($c.InitialSize -ne 8192 -or $c.MaximumSize -ne 8192){ Write-Host ('WARNING: C: setting is ' + $c.InitialSize + '/' + $c.MaximumSize + ', expected 8192/8192.') -ForegroundColor Yellow }; $d=$s | Where-Object {$_.Name -eq 'D:\\pagefile.sys'}; if(-not $d){ Write-Host 'WARNING: D:\\pagefile.sys setting missing or has a malformed name.' -ForegroundColor Yellow } elseif($d.InitialSize -ne 32768 -or $d.MaximumSize -ne 32768){ Write-Host ('WARNING: D: setting is ' + $d.InitialSize + '/' + $d.MaximumSize + ', expected 32768/32768.') -ForegroundColor Yellow }"

echo ============================================================
echo Actual allocation
echo ============================================================
powershell -NoProfile -Command "$u=Get-CimInstance Win32_PageFileUsage; $u | Select-Object Name,AllocatedBaseSize,CurrentUsage,PeakUsage | Format-Table -AutoSize; $du=$u | Where-Object {$_.Name -eq 'D:\\pagefile.sys'}; if(-not $du){ Write-Host 'WARNING: D: pagefile is not active. Reboot first.' -ForegroundColor Yellow } elseif($du.AllocatedBaseSize -ne 32768){ Write-Host ('WARNING: D: allocated ' + $du.AllocatedBaseSize + 'MB, expected 32768MB.') -ForegroundColor Yellow }"

echo ============================================================
echo Commit / headroom
echo ============================================================
powershell -NoProfile -Command "$l=(Get-Counter '\\Memory\\Commit Limit').CounterSamples.CookedValue; $c=(Get-Counter '\\Memory\\Committed Bytes').CounterSamples.CookedValue; $a=(Get-Counter '\\Memory\\Available MBytes').CounterSamples.CookedValue; 'CommitLimitGB = {0:N2}' -f ($l/1GB); 'CommittedGB = {0:N2}' -f ($c/1GB); 'HeadroomGB = {0:N2}' -f (($l-$c)/1GB); 'AvailableMB = {0}' -f $a"

echo ============================================================
echo Top 8 processes by commit
echo ============================================================
powershell -NoProfile -Command "Get-Process | Sort-Object PagedMemorySize64 -Descending | Select-Object -First 8 Name,Id,@{n='CommitMB';e={[math]::Round($_.PagedMemorySize64/1MB)}} | Format-Table -AutoSize"

echo ============================================================
echo Low-memory events 2004 (last 3 days)
echo ============================================================
powershell -NoProfile -Command "Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Resource-Exhaustion-Detector'; StartTime=(Get-Date).AddDays(-3)} -ErrorAction SilentlyContinue | Select-Object TimeCreated,Id | Format-Table -AutoSize"

pause

Configuration 段读的是“配置”,Actual allocation 段读的是“系统实际创建出来的页面文件”。两者要同时看:配置正确但未重启时,AllocatedBaseSize 仍然是旧值;只有重启后两者一致,才说明配置真正生效。

一次正常的验证输出大致如下:

AutomaticManagedPagefile = False
PagingFiles registry:
C:\\pagefile.sys 8192 8192
D:\\pagefile.sys 32768 32768

Win32_PageFileUsage:
C:\\pagefile.sys 8192
D:\\pagefile.sys 32768

CommitLimitGB = 55.34
CommittedGB = 7.53
HeadroomGB = 47.81

CommitLimitGB 是当前上限,HeadroomGB 是剩余空间。空闲时余量大不代表游戏峰值时也够;验证要在进入战场后再看一次,或者至少确认 2004 事件不再出现。


🧪 预期结果与失败处理

check 出现异常时,先按现象对照原因,不要直接重跑 apply:

现象原因处理
AutomaticManagedPagefile = True apply 没有以管理员运行,或没有生效 以管理员身份重跑 apply
D: allocated 9216MB 旧 WMIC 配置残留,或写入后没有重启 用注册表方式重写并重启
AllocatedBaseSize 仍是旧值 配置已写入,但系统还没有重启 重启后再运行 check
WARNING: D: pagefile is not active D 盘没有创建页面文件,或空间不足 检查 D 盘空间和 PagingFiles
HeadroomGB 长期低于 1GB 后台程序太多,或游戏峰值过高 关后台、降 BattleSize、再评估

D 盘 32GB 页面文件会直接占用 32GB 空间。脚本不检查剩余空间,执行前要确认 D 盘至少有 33GB 空闲;如果 D 盘空间不足,页面文件无法扩展到目标大小,check 会显示实际分配不符。


↩️ pagefile-restore.bat

restore 把配置恢复成 Windows 自动管理。脚本内容如下:

@echo off
setlocal
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Please run as Administrator.
pause
exit /b 1
)

echo ============================================================
echo BEFORE
echo ============================================================
powershell -NoProfile -Command "Get-CimInstance Win32_ComputerSystem | Select-Object AutomaticManagedPagefile | Format-List; Get-CimInstance Win32_PageFileSetting | Select-Object Name,InitialSize,MaximumSize | Format-Table -AutoSize; $mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; 'PagingFiles registry:'; (Get-ItemProperty -Path $mm -Name PagingFiles).PagingFiles"

echo.
echo Restoring original state (automatic, C: only) …
powershell -NoProfile -ExecutionPolicy Bypass -Command "$ErrorActionPreference='Stop'; $mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; $cs=Get-CimInstance Win32_ComputerSystem; if($cs.AutomaticManagedPagefile){ $cs | Set-CimInstance -Property @{AutomaticManagedPagefile=$false} }; try { Get-CimInstance Win32_PageFileSetting | Remove-CimInstance -ErrorAction Stop } catch { }; Set-ItemProperty -Path $mm -Name PagingFiles -Value @('?:\\pagefile.sys') -Type MultiString; $cs2=Get-CimInstance Win32_ComputerSystem; $cs2 | Set-CimInstance -Property @{AutomaticManagedPagefile=$true}; 'Restored.'"

echo.
echo ============================================================
echo AFTER (effective after reboot)
echo ============================================================
powershell -NoProfile -Command "$mm='HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management'; Get-CimInstance Win32_ComputerSystem | Select-Object AutomaticManagedPagefile | Format-List; 'PagingFiles registry:'; (Get-ItemProperty -Path $mm -Name PagingFiles).PagingFiles; 'Win32_PageFileSetting:'; Get-CimInstance Win32_PageFileSetting | Select-Object Name,InitialSize,MaximumSize | Format-Table -AutoSize"

echo.
echo DONE. Reboot Windows.
echo If D:\\pagefile.sys still exists after reboot, delete it manually.
pause

?:\\pagefile.sys 表示由系统按默认策略在启动卷上管理页面文件;同时把 AutomaticManagedPagefile 设回 True。重启后如果 D:\\pagefile.sys 仍然存在,可以在确认系统没有使用它之后手动删除。


📌 执行顺序

在这里插入图片描述

图 1 页面文件修复流程

  • 关闭游戏、启动器和 Steam。
  • 以管理员身份运行 pagefile-apply.bat,确认 AFTER 段的两行 PagingFiles。
  • 重启 Windows。
  • 运行 pagefile-check.bat,确认 D:\\pagefile.sys 的 AllocatedBaseSize 为 32768。
  • 进入同一场战斗复测;仍出现 OOM 才考虑二分 MOD。
  • 需要回滚时运行 pagefile-restore.bat,再重启。

  • ⚠️ 使用前检查

    • 以管理员身份运行 apply 和 restore;check 不需要管理员。
    • 退出游戏和 Steam,避免文件被占用。
    • D 盘至少保留 33GB 空闲空间,其中 32GB 给页面文件,1GB 作为余量。
    • 确认 C 盘仍有足够空间;脚本把 C 盘页面文件设为 8GB,不会无限增长。
    • 写入配置后必须重启,否则 AllocatedBaseSize 不会变化。
    • 不要把 wmic pagefileset create 作为写入方式;它的双反斜杠问题会在下一篇展开。

    🧩 脚本复用

    三个脚本的分工可以复用到其他机器:apply 改盘符和大小,check 在重启后验证,restore 回滚。复用时不要照搬 8GB + 32GB;先测峰值,再按磁盘空间调整。页面文件放在系统盘还是数据盘,也要结合内核转储需求判断。


    📌 小结

    • apply 负责写入配置,check 负责验证,restore 负责回滚。
    • 配置写入注册表后必须重启,配置值和实际分配值要分开看。
    • 提交限制由物理内存和页面文件共同决定,页面文件只是后备存储。
    • 验证要看 AllocatedBaseSize、CommitLimitGB 和 2004 事件,不能只看注册表。
    • 页面文件解决的是提交余量,不是物理内存不足,也不是性能问题。

    下一篇拆解脚本里的 bat 与 PowerShell 语法,重点讲 PagingFiles 的 REG_MULTI_SZ 格式,以及 wmic pagefileset create 为什么会留下双反斜杠。


    OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog 【MOD开发】【骑砍2】运行内存:bat 与 PowerShell 语法逐行拆解

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 10、【MOD开发】【骑砍2】运行内存:三个 bat 脚本的分工与执行顺序
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!