View difference between Paste ID: tDeuS2LV and Kj36ug5h
SHOW: | | - or go back to the newest paste.
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 : Convert.ToInt32(args[0]);
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
/*_*/