Last active
November 23, 2023 21:16
-
-
Save AveYo/2cee207bdb67525e34c45dff76be0b16 to your computer and use it in GitHub Desktop.
FreeStandbyMemory.bat - ninja edits at https://pastebin.com/Kj36ug5h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 2>nul || title FreeStandbyMemory.bat by AveYo v2019.06.01 | |
@echo off|| csc compiling snippet, advanced schedule, builtin add_remove - UPDATE: reliable free memory detection | |
set/a CLEAR_EVERY_MINUTES=1 | |
set/a CLEAR_WHEN_UNDER_MB=512 | |
set/a CLEAR_SYSTEMCACHEWS=0 | |
:: check_admin_rights | |
reg query "HKEY_USERS\S-1-5-20\Environment" /v TEMP >nul 2>nul || ( | |
color 0e & echo. & echo PERMISSION DENIED! Right-click %~nx0 ^& Run as administrator | |
timeout /t -1 & color 0f & title %COMSPEC% & exit/b | |
) | |
:: add_remove whenever script is run again | |
schtasks /query /tn FreeStandbyMemory >nul 2>nul && ( | |
echo. | |
schtasks /Delete /TN "FreeStandbyMemory" /f 2>nul | |
reg delete HKLM\Software\AveYo /v FreeStandbyMemory /f 2>nul | |
del /f /q "%Windir%\FreeStandbyMemory.exe" 2>nul | |
color 0b &echo. &echo REMOVED! Run script again to recompile and add schedule! | |
timeout /t -1 &color 0f &title %COMSPEC% &exit/b | |
) | |
:: compile c# snippet | |
pushd %~dp0 | |
del /f /q FreeStandbyMemory.exe >nul 2>nul | |
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%Windir%\Microsoft.NET\*csc.exe"') do set "csc="%%v"" | |
%csc% /out:FreeStandbyMemory.exe /target:winexe /platform:anycpu /optimize /nologo "%~f0" | |
if not exist FreeStandbyMemory.exe echo ERROR! Failed compiling c# snippet & timeout /t -1 & exit /b | |
echo|set/p=FreeStandbyMemory.exe © /y FreeStandbyMemory.exe "%Windir%\FreeStandbyMemory.exe" &set "OUTDIR=%Windir%" | |
if not exist "%Windir%\FreeStandbyMemory.exe" echo WARNING! Cannot copy FreeStandbyMemory.exe to %Windir%\ &set "OUTDIR=%CD%" | |
:: setup advanced schedule - can afford higher priority after switching from wmi to winapi | |
set "task_run=%OUTDIR%\FreeStandbyMemory.exe %CLEAR_WHEN_UNDER_MB% %CLEAR_SYSTEMCACHEWS%" | |
set "schedule=/Create /RU "System" /NP /RL HIGHEST /F /SD "01/01/2001" /ST "01:00:00" " | |
schtasks %schedule% /SC MINUTE /MO %CLEAR_EVERY_MINUTES% /TN "FreeStandbyMemory" /TR "%task_run%" | |
set "sset=$s=New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Priority 1 -StartWhenAvailable;" | |
set "stopexisting=$s.CimInstanceProperties['MultipleInstances'].Value=3;" | |
powershell -noprofile -c "%sset% %stopexisting% $null=Set-ScheduledTask -TaskName FreeStandbyMemory -Settings $s" | |
:: trigger task, force a manual clear and finish setup | |
schtasks /Run /TN "FreeStandbyMemory" | |
echo. | |
echo Clearing StandbyMemory every %CLEAR_EVERY_MINUTES% minutes ONLY if free memory goes under %CLEAR_WHEN_UNDER_MB% MB | |
echo Can force a clear manually from Command Prompt (Admin) by entering: freestandbymemory | |
echo. | |
echo ADDED! Run "%~nx0" again to remove compiled snippet and schedule! | |
timeout /t -1 | |
exit /b | |
:: Based on idea from "PowerShell wrapper script for clear StandBy memory without RAMMap" by Alexander Korotkov | |
:: Implemented SetSystemFileCacheSize and NtSetSystemInformation suggestions by Maks.K | |
:: Using RtlAdjustPrivilege, GetPerformanceInfo, force clear if no args, stripped output, sanitized by AveYo | |
*/ | |
using System; | |
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
using System.Reflection; | |
[assembly:AssemblyTitle("FreeStandbyMemory")] | |
[assembly:AssemblyCopyrightAttribute("AveYo")] | |
[assembly:AssemblyVersionAttribute("2019.06.01")] | |
namespace FreeStandbyMemory | |
{ | |
class Program | |
{ | |
static bool retv = false; | |
static int MemoryPurgeStandbyList = 0x0004; | |
const int SystemFileCacheInformation = 0x0015; | |
const int SystemMemoryListInformation = 0x0050; | |
const int SE_INCREASE_QUOTA_PRIVILEGE = 0x00000005; | |
const int SE_PROF_SINGLE_PROCESS_PRIVILEGE = 0x0000000d; | |
[StructLayout(LayoutKind.Sequential)] | |
private class PERFINFO | |
{ | |
public int cb; | |
public IntPtr CommitTotal; | |
public IntPtr CommitLimit; | |
public IntPtr CommitPeak; | |
public IntPtr PhysicalTotal; | |
public IntPtr PhysicalAvailable; | |
public IntPtr SystemCache; | |
public IntPtr KernelTotal; | |
public IntPtr KernelPaged; | |
public IntPtr KernelNonpaged; | |
public IntPtr PageSize; | |
public int HandleCount; | |
public int ProcessCount; | |
public int ThreadCount; | |
public PERFINFO() | |
{ | |
this.cb = (int)Marshal.SizeOf(typeof(PERFINFO)); | |
} | |
} | |
[return: MarshalAs(UnmanagedType.Bool)] | |
[DllImport( "psapi.dll", CharSet = CharSet.Auto, SetLastError = true )] | |
static extern bool GetPerformanceInfo([In, Out] PERFINFO pi); | |
[DllImport("psapi.dll")] | |
static extern bool EmptyWorkingSet(IntPtr hwProc); | |
[DllImport("kernel32.dll")] | |
static extern bool SetSystemFileCacheSize(IntPtr MinimumFileCacheSize, IntPtr MaximumFileCacheSize, int Flags); | |
[DllImport("ntdll.dll")] | |
static extern IntPtr RtlAdjustPrivilege(int Privilege, bool Enable, bool CurrentThread, out bool RetValue); | |
[DllImport("ntdll.dll")] | |
static extern IntPtr NtSetSystemInformation(int InfoClass, out int Info, int Length); | |
static void Main(string[] args) | |
{ | |
int target = (args.Length == 0) ? Int32.MaxValue : Convert.ToInt32(args[0]); | |
bool systemcachews = (args.Length == 0 || args.Length >= 2 && args[1] == "1"); | |
Int64 free = 0; | |
PERFINFO pi = new PERFINFO(); | |
if (GetPerformanceInfo(pi)) | |
{ | |
Int64 avail = pi.PhysicalAvailable.ToInt64(); | |
Int64 cache = pi.SystemCache.ToInt64(); | |
Int64 page = pi.PageSize.ToInt64(); | |
free = ( (avail > cache) ? avail - cache : cache - avail ) * page >> 20; | |
/* To debug, change csc /target:winexe to /target:exe and uncomment the Console.WriteLine's */ | |
////Console.WriteLine("Total: {0,5}MB", pi.PhysicalTotal.ToInt64() * page >> 20); | |
////Console.WriteLine("Avail: {0,5}MB", pi.PhysicalAvailable.ToInt64() * page >> 20); | |
////Console.WriteLine("Cache: {0,5}MB", pi.SystemCache.ToInt64() * page >> 20); | |
////Console.WriteLine("Free: {0,5}MB", free); | |
} | |
if (free > target) return; | |
////Console.WriteLine("Target:{0,5}MB - CLEARING!", target); | |
RtlAdjustPrivilege(SE_INCREASE_QUOTA_PRIVILEGE, true, false, out retv); | |
RtlAdjustPrivilege(SE_PROF_SINGLE_PROCESS_PRIVILEGE, true, false, out retv); | |
NtSetSystemInformation(SystemMemoryListInformation, out MemoryPurgeStandbyList, Marshal.SizeOf(MemoryPurgeStandbyList)); | |
if (systemcachews) { | |
SetSystemFileCacheSize(new IntPtr(-1), new IntPtr(-1), 0); | |
Process[] processlist = Process.GetProcesses(); // Also free system processes working sets: | |
foreach(Process p in processlist) if (p.SessionId == 0) try { EmptyWorkingSet(p.Handle); } catch (Exception) {} | |
} | |
} | |
} | |
} | |
/*_*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* text=auto | |
* eol=crlf |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Problem: Scheduled tasks Action with added arguments doesn't perform (eg 4096 0).
Note: Scheduled task Action with no added arguments does perform.
Running Windows 10 Pro 1903 18362.267