aveyo

FreeStandbyMemory

May 28th, 2018
23,005
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Batch 6.53 KB | None | 0 0
  1. /* 2>nul || title FreeStandbyMemory.bat by AveYo v2019.06.01
  2. @echo off|| csc compiling snippet, advanced schedule, builtin add_remove - UPDATE: reliable free memory detection
  3.  
  4. set/a CLEAR_EVERY_MINUTES=1
  5. set/a CLEAR_WHEN_UNDER_MB=512
  6. set/a CLEAR_SYSTEMCACHEWS=0
  7.  
  8. :: check_admin_rights
  9. reg query "HKEY_USERS\S-1-5-20\Environment" /v TEMP >nul 2>nul || (
  10.  color 0e & echo. & echo  PERMISSION DENIED! Right-click %~nx0 ^& Run as administrator
  11.  timeout /t -1 & color 0f & title %COMSPEC% & exit/b
  12. )
  13.  
  14. :: add_remove whenever script is run again
  15. schtasks /query /tn FreeStandbyMemory >nul 2>nul && (
  16.  echo.
  17.  schtasks /Delete /TN "FreeStandbyMemory" /f 2>nul
  18.  reg delete HKLM\Software\AveYo /v FreeStandbyMemory /f 2>nul
  19.  del /f /q "%Windir%\FreeStandbyMemory.exe" 2>nul
  20.  color 0b &echo. &echo REMOVED! Run script again to recompile and add schedule!
  21.  timeout /t -1 &color 0f &title %COMSPEC% &exit/b
  22. )
  23.  
  24. :: compile c# snippet
  25. pushd %~dp0
  26. del /f /q FreeStandbyMemory.exe >nul 2>nul
  27. for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%Windir%\Microsoft.NET\*csc.exe"') do set "csc="%%v""
  28. %csc% /out:FreeStandbyMemory.exe /target:winexe /platform:anycpu /optimize /nologo "%~f0"
  29. if not exist FreeStandbyMemory.exe echo ERROR! Failed compiling c# snippet & timeout /t -1 & exit /b
  30. echo|set/p=FreeStandbyMemory.exe &copy /y FreeStandbyMemory.exe "%Windir%\FreeStandbyMemory.exe" &set "OUTDIR=%Windir%"
  31. if not exist "%Windir%\FreeStandbyMemory.exe" echo WARNING! Cannot copy FreeStandbyMemory.exe to %Windir%\ &set "OUTDIR=%CD%"
  32.  
  33. :: setup advanced schedule - can afford higher priority after switching from wmi to winapi
  34. set "task_run=%OUTDIR%\FreeStandbyMemory.exe %CLEAR_WHEN_UNDER_MB% %CLEAR_SYSTEMCACHEWS%"
  35. set "schedule=/Create /RU "System" /NP /RL HIGHEST /F /SD "01/01/2001" /ST "01:00:00" "
  36. schtasks %schedule% /SC MINUTE /MO %CLEAR_EVERY_MINUTES% /TN "FreeStandbyMemory" /TR "%task_run%"
  37. set "sset=$s=New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Priority 1 -StartWhenAvailable;"
  38. set "stopexisting=$s.CimInstanceProperties['MultipleInstances'].Value=3;"
  39. powershell -noprofile -c "%sset% %stopexisting% $null=Set-ScheduledTask -TaskName FreeStandbyMemory -Settings $s"
  40.  
  41. :: trigger task, force a manual clear and finish setup
  42. schtasks /Run /TN "FreeStandbyMemory"
  43. echo.
  44. echo  Clearing StandbyMemory every %CLEAR_EVERY_MINUTES% minutes ONLY if free memory goes under %CLEAR_WHEN_UNDER_MB% MB
  45. echo  Can force a clear manually from Command Prompt (Admin) by entering: freestandbymemory
  46. echo.
  47. echo ADDED! Run "%~nx0" again to remove compiled snippet and schedule!
  48. timeout /t -1
  49. exit /b
  50.  
  51. :: Based on idea from "PowerShell wrapper script for clear StandBy memory without RAMMap" by Alexander Korotkov
  52. :: Implemented SetSystemFileCacheSize and NtSetSystemInformation suggestions by Maks.K
  53. :: Using RtlAdjustPrivilege, GetPerformanceInfo, force clear if no args, stripped output, sanitized by AveYo
  54. */
  55. using System;
  56. using System.Diagnostics;
  57. using System.Runtime.InteropServices;
  58. using System.Reflection;
  59.  
  60. [assembly:AssemblyTitle("FreeStandbyMemory")]
  61. [assembly:AssemblyCopyrightAttribute("AveYo")]
  62. [assembly:AssemblyVersionAttribute("2019.06.01")]
  63.  
  64. namespace FreeStandbyMemory
  65. {
  66.   class Program
  67.   {
  68.     static bool retv = false;
  69.     static int MemoryPurgeStandbyList = 0x0004;
  70.     const int SystemFileCacheInformation = 0x0015;
  71.     const int SystemMemoryListInformation = 0x0050;
  72.     const int SE_INCREASE_QUOTA_PRIVILEGE = 0x00000005;
  73.     const int SE_PROF_SINGLE_PROCESS_PRIVILEGE = 0x0000000d;
  74.     [StructLayout(LayoutKind.Sequential)]
  75.     private class PERFINFO
  76.     {
  77.       public int cb;
  78.       public IntPtr CommitTotal;
  79.       public IntPtr CommitLimit;
  80.       public IntPtr CommitPeak;
  81.       public IntPtr PhysicalTotal;
  82.       public IntPtr PhysicalAvailable;
  83.       public IntPtr SystemCache;
  84.       public IntPtr KernelTotal;
  85.       public IntPtr KernelPaged;
  86.       public IntPtr KernelNonpaged;
  87.       public IntPtr PageSize;
  88.       public int HandleCount;
  89.       public int ProcessCount;
  90.       public int ThreadCount;
  91.       public PERFINFO()
  92.       {
  93.         this.cb = (int)Marshal.SizeOf(typeof(PERFINFO));
  94.       }        
  95.     }
  96.     [return: MarshalAs(UnmanagedType.Bool)]
  97.     [DllImport( "psapi.dll", CharSet = CharSet.Auto, SetLastError = true )]
  98.     static extern bool GetPerformanceInfo([In, Out] PERFINFO pi);
  99.     [DllImport("psapi.dll")]
  100.     static extern bool EmptyWorkingSet(IntPtr hwProc);
  101.     [DllImport("kernel32.dll")]
  102.     static extern bool SetSystemFileCacheSize(IntPtr MinimumFileCacheSize, IntPtr MaximumFileCacheSize, int Flags);
  103.     [DllImport("ntdll.dll")]
  104.     static extern IntPtr RtlAdjustPrivilege(int Privilege, bool Enable, bool CurrentThread, out bool RetValue);
  105.     [DllImport("ntdll.dll")]
  106.     static extern IntPtr NtSetSystemInformation(int InfoClass, out int Info, int Length);
  107.  
  108.     static void Main(string[] args)
  109.     {
  110.       int target = (args.Length == 0) ? Int32.MaxValue : !!()
  111.       bool systemcachews = (args.Length == 0 || args.Length >= 2 && args[1] == "1");
  112.       Int64 free = 0;
  113.       PERFINFO pi = new PERFINFO();
  114.       if (GetPerformanceInfo(pi))
  115.       {
  116.         Int64 avail = pi.PhysicalAvailable.ToInt64();
  117.         Int64 cache = pi.SystemCache.ToInt64();
  118.         Int64 page = pi.PageSize.ToInt64();
  119.         free = ( (avail > cache) ? avail - cache : cache - avail ) * page >> 20;
  120.         /* To debug, change csc /target:winexe to /target:exe and uncomment the Console.WriteLine's */
  121.         ////Console.WriteLine("Total: {0,5}MB", pi.PhysicalTotal.ToInt64() * page >> 20);
  122.         ////Console.WriteLine("Avail: {0,5}MB", pi.PhysicalAvailable.ToInt64() * page >> 20);
  123.         ////Console.WriteLine("Cache: {0,5}MB", pi.SystemCache.ToInt64() * page >> 20);
  124.         ////Console.WriteLine("Free:  {0,5}MB", free);
  125.       }
  126.       if (free > target) return;
  127.       ////Console.WriteLine("Target:{0,5}MB - CLEARING!", target);
  128.       RtlAdjustPrivilege(SE_INCREASE_QUOTA_PRIVILEGE,      true, false, out retv);
  129.       RtlAdjustPrivilege(SE_PROF_SINGLE_PROCESS_PRIVILEGE, true, false, out retv);
  130.       NtSetSystemInformation(SystemMemoryListInformation, out MemoryPurgeStandbyList, Marshal.SizeOf(MemoryPurgeStandbyList));
  131.       if (systemcachews) {
  132.         SetSystemFileCacheSize(new IntPtr(-1), new IntPtr(-1), 0);
  133.         Process[] processlist = Process.GetProcesses(); // Also free system processes working sets:
  134.         foreach(Process p in processlist) if (p.SessionId == 0) try { EmptyWorkingSet(p.Handle); } catch (Exception) {}
  135.       }
  136.     }
  137.   }
  138. }
  139. /*_*/
Add Comment
Please, Sign In to add comment