C#; PS; Очистка StandBy памяти; no RAMMap
Когда люди городят что-то подобное http://infostart.ru/public/237919/, меня немного передергивает. Как демонстрация работы с AutoIT — очень даже, но как решение задачи — костыль (Хотя все это и есть один большой костыль). А тут еще и коллега скинул данную ссылку, мол — «скажи, что можно сделать по нормальному, не так…».
Попросил Александра Короткова набросать мне соответствующий код на C#, а сам его бесцеремонно скопи—пастил и завернул в PowerShell.
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(` [Security.Principal.WindowsBuiltInRole] "Administrator")) { Write-Warning “You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!” Break } $Source = @" using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Security.Principal; namespace ClearStandbyList { public class Program { const int SE_PRIVILEGE_ENABLED = 2; const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege"; const string SE_PROFILE_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"; const int SystemFileCacheInformation = 0x0015; const int SystemMemoryListInformation = 0x0050; const int MemoryPurgeStandbyList = 4; [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); [DllImport("ntdll.dll")] public static extern UInt32 NtSetSystemInformation(int InfoClass, IntPtr Info, int Length); public static bool Is64BitMode() { return Marshal.SizeOf(typeof(IntPtr)) == 8; } static void Main(string[] args) { ClearFileSystemCache(true); } public static void ClearFileSystemCache(bool ClearStandbyCache) { try { if (SetIncreasePrivilege(SE_INCREASE_QUOTA_NAME)) { uint num1; int SystemInfoLength; GCHandle gcHandle; if (!Is64BitMode()) { SYSTEM_CACHE_INFORMATION cacheInformation = new SYSTEM_CACHE_INFORMATION(); cacheInformation.MinimumWorkingSet = uint.MaxValue; cacheInformation.MaximumWorkingSet = uint.MaxValue; SystemInfoLength = Marshal.SizeOf(cacheInformation); gcHandle = GCHandle.Alloc(cacheInformation, GCHandleType.Pinned); num1 = NtSetSystemInformation(SystemFileCacheInformation, gcHandle.AddrOfPinnedObject(), SystemInfoLength); gcHandle.Free(); } else { SYSTEM_CACHE_INFORMATION_64_BIT information64Bit = new SYSTEM_CACHE_INFORMATION_64_BIT(); information64Bit.MinimumWorkingSet = -1L; information64Bit.MaximumWorkingSet = -1L; SystemInfoLength = Marshal.SizeOf(information64Bit); gcHandle = GCHandle.Alloc(information64Bit, GCHandleType.Pinned); num1 = NtSetSystemInformation(SystemFileCacheInformation, gcHandle.AddrOfPinnedObject(), SystemInfoLength); gcHandle.Free(); } if (num1 != 0) throw new Exception("NtSetSystemInformation(SYSTEMCACHEINFORMATION) error: ", new Win32Exception(Marshal.GetLastWin32Error())); } if (ClearStandbyCache && SetIncreasePrivilege(SE_PROFILE_SINGLE_PROCESS_NAME)) { int SystemInfoLength = Marshal.SizeOf(MemoryPurgeStandbyList); GCHandle gcHandle = GCHandle.Alloc(MemoryPurgeStandbyList, GCHandleType.Pinned); uint num2 = NtSetSystemInformation(SystemMemoryListInformation, gcHandle.AddrOfPinnedObject(), SystemInfoLength); gcHandle.Free(); if (num2 != 0) throw new Exception("NtSetSystemInformation(SYSTEMMEMORYLISTINFORMATION) error: ", new Win32Exception(Marshal.GetLastWin32Error())); } } catch (Exception ex) { Console.Write(ex.ToString()); } } private static bool SetIncreasePrivilege(string privilegeName) { using (WindowsIdentity current = WindowsIdentity.GetCurrent(TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges)) { TokPriv1Luid newst; newst.Count = 1; newst.Luid = 0L; newst.Attr = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValue(null, privilegeName, ref newst.Luid)) throw new Exception("Error in LookupPrivilegeValue: ", new Win32Exception(Marshal.GetLastWin32Error())); int num = AdjustTokenPrivileges(current.Token, false, ref newst, 0, IntPtr.Zero, IntPtr.Zero) ? 1 : 0; if (num == 0) throw new Exception("Error in AdjustTokenPrivileges: ", new Win32Exception(Marshal.GetLastWin32Error())); return num != 0; } } } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct SYSTEM_CACHE_INFORMATION { public uint CurrentSize; public uint PeakSize; public uint PageFaultCount; public uint MinimumWorkingSet; public uint MaximumWorkingSet; public uint Unused1; public uint Unused2; public uint Unused3; public uint Unused4; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct SYSTEM_CACHE_INFORMATION_64_BIT { public long CurrentSize; public long PeakSize; public long PageFaultCount; public long MinimumWorkingSet; public long MaximumWorkingSet; public long Unused1; public long Unused2; public long Unused3; public long Unused4; } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } } "@ Add-Type -TypeDefinition $Source -Language CSharp [ClearStandbyList.Program]::ClearFileSystemCache($true)
Александр мне и экзешничек скомпилировал, но т.к. сам я экзешнички не люблю, выкладывать его не буду.
Весь крипт можно скачать с TechNet-а: Скрипт на c# + PowerShell для очистки StandBy памяти без использования RAMMap
Или тут: Clear-StandByMemory.ps1
После загрузки не забудьте разблокировать файл (Свойство файла / Разблокировать).
Запускать с повышением прав (Run as administrator):
powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned -File "C:\Path\To\Clear-StandByMemory.ps1"
Update 2016-12-27:
Обновили скрипт и код для поддержки Windows 7 / Powershell 2.0. Должен работать и на Vista / 2008 но проверить не на чем.
Недавние комментарии