本帖最后由 Nsqs 于 2026-4-25 14:16 编辑
- <#
- .SYNOPSIS
- Win11 内存净化器(v 1.0.0)
- .DESCRIPTION
- 适配 PowerShell 5.1 / Win11,提供:
- · 手动模式:三步独立动作
- · 自动模式:循环定时释放
- · 调试模式:通过 -DebugInterval 传入自定义间隔(如 "600"、"1:30"、"1:30:00"),开启调试菜单;使用 -PassThru 无效化调试模式(采用默认值)
- · 自适应单位显示(支持负数,如 -1.32 GB)
- #>
- #Requires -RunAsAdministrator
- param(
- [string]$DebugInterval,
- [switch]$PassThru
- )
- Clear-Host
- # ========== ANSI 色彩 ==========
- $esc = [char]0x1b
- $reset = "$esc[0m"
- $cyan = "$esc[36m"
- $green = "$esc[32m"
- $yellow = "$esc[33m"
- $gray = "$esc[90m"
- $white = "$esc[37m"
- $red = "$esc[31m"
- $blue = "$esc[34m"
- $brightCyan = "$esc[96m"
- $cLine = $cyan
- $cTitle = $green
- $cStep = $yellow
- $cOK = $green
- $cWarn = $yellow
- $cText = $white
- $cDim = $gray
- $cLabel = $blue
- $cBracket = $white
- $cBracketTxt = $brightCyan
- $cTime = $yellow
- # ========== 核心 API 加载 ==========
- Add-Type @"
- using System;
- using System.Runtime.InteropServices;
- public static class NativeMethods
- {
- [DllImport("kernel32.dll")]
- public static extern bool SetProcessWorkingSetSize(IntPtr hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
- [DllImport("ntdll.dll", SetLastError = true)]
- public static extern int NtSetSystemInformation(int SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength);
- public const int SystemMemoryListInformation = 0x50;
- }
- public enum MemoryListCommand : int
- {
- MemoryPurgeStandbyList = 4,
- MemoryPurgeLowPriorityStandbyList = 5
- }
- "@
- # ========== 辅助函数 ==========
- function Format-MemorySize {
- param([long]$Bytes)
- $abs = [Math]::Abs($Bytes)
- $div = if ($abs -ge 1GB) { 1GB }
- elseif ($abs -ge 1MB) { 1MB }
- elseif ($abs -ge 1KB) { 1KB }
- else { 1 }
- $unit = if ($div -eq 1GB) { "GB" }
- elseif ($div -eq 1MB) { "MB" }
- elseif ($div -eq 1KB) { "KB" }
- else { "Byte" }
- $value = $Bytes / $div
- "{0:N2} {1}" -f $value, $unit
- }
- function Get-FreeMemoryBytes {
- (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory * 1024
- }
- function Compress-WorkingSets {
- Get-Process -ErrorAction SilentlyContinue | ForEach-Object {
- try { [NativeMethods]::SetProcessWorkingSetSize($_.Handle, -1, -1) | Out-Null } catch { }
- }
- }
- function Clear-StandbyLists {
- $cmd = [MemoryListCommand]::MemoryPurgeStandbyList
- $ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
- [System.Runtime.InteropServices.Marshal]::WriteInt32($ptr, $cmd)
- [NativeMethods]::NtSetSystemInformation([NativeMethods]::SystemMemoryListInformation, $ptr, 4) | Out-Null
- [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
- $cmd = [MemoryListCommand]::MemoryPurgeLowPriorityStandbyList
- $ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
- [System.Runtime.InteropServices.Marshal]::WriteInt32($ptr, $cmd)
- [NativeMethods]::NtSetSystemInformation([NativeMethods]::SystemMemoryListInformation, $ptr, 4) | Out-Null
- [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
- }
- function Invoke-DotNetGC {
- [System.GC]::Collect()
- [System.GC]::WaitForPendingFinalizers()
- [System.GC]::Collect()
- }
- function Clear-MemoryAll {
- Compress-WorkingSets
- Clear-StandbyLists
- Invoke-DotNetGC
- }
- # ========== 调试模式开关函数 ==========
- function Enable-DebugMode {
- param(
- [string]$Interval,
- [switch]$PassThru
- )
- if ($PassThru) {
- Write-Host "调试模式无效化 (PassThru),使用默认常数值" -ForegroundColor Gray
- return
- }
- $seconds = 0
- if ($Interval -match '^(\d+):(\d{1,2}):(\d{1,2})$') {
- $seconds = [int]$Matches[1]*3600 + [int]$Matches[2]*60 + [int]$Matches[3]
- }
- elseif ($Interval -match '^(\d+):(\d{1,2})$') {
- $seconds = [int]$Matches[1]*60 + [int]$Matches[2]
- }
- elseif ($Interval -match '^\d+$') {
- $seconds = [int]$Interval
- }
- else {
- Write-Host "无法解析时间格式,使用默认15秒" -ForegroundColor Yellow
- $seconds = 15
- }
- if ($seconds -le 0) { $seconds = 15 }
- $global:DebugIntervalSeconds = $seconds
- Write-Host "调试模式已激活,自动释放间隔:$seconds 秒" -ForegroundColor Green
- }
- if ($DebugInterval) {
- Enable-DebugMode -Interval $DebugInterval -PassThru:$PassThru
- }
- # ========== 手动释放差值记录 ==========
- $global:lastManualDelta = $null
- # ========== 手动模式步骤 ==========
- function Invoke-ManualStep {
- param(
- [string]$InProgressText,
- [string]$CompletedText,
- [scriptblock]$Action
- )
- $line = [System.Console]::CursorTop
- Write-Host $InProgressText
- & $Action
- Start-Sleep -Milliseconds 1500
- [System.Console]::SetCursorPosition(0, $line)
- Write-Host "$CompletedText " -NoNewline
- Write-Host ""
- }
- function ManualRun {
- Clear-Host
- [Console]::CursorVisible = $false
- Write-Host "$cLine┌─────────────────────────────────────┐$reset"
- Write-Host "$cLine│$cTitle 手动释放 - 仪式感模式 $cLine│$reset"
- Write-Host "$cLine└─────────────────────────────────────┘$reset`n"
- $before = Get-FreeMemoryBytes
- Write-Host " ${cLabel}当前空闲内存 : ${reset}${cText}$(Format-MemorySize $before)$reset`n"
- $procs = @(Get-Process -ErrorAction SilentlyContinue)
- $procCount = $procs.Count
- Invoke-ManualStep `
- " $cStep⏸️ 正在释放进程闲置内存 ${cBracket}(${cBracketTxt}总计 $procCount 个进程${cBracket})$reset" `
- " $cOK✅ 释放进程闲置内存 完成 ${cBracket}(${cBracketTxt}已处理 $procCount 个进程${cBracket})$reset" `
- { Compress-WorkingSets }
- Invoke-ManualStep `
- " $cStep⏸️ 正在清理系统缓存...$reset" `
- " $cOK✅ 清理系统缓存 完成$reset" `
- { Clear-StandbyLists }
- Invoke-ManualStep `
- " $cStep⏸️ 正在整理托管内存...$reset" `
- " $cOK✅ 整理托管内存 完成$reset" `
- { Invoke-DotNetGC }
- $after = Get-FreeMemoryBytes
- $delta = $after - $before
- Write-Host "`n ${cDim}───────────────────────────────────$reset"
- Write-Host " ${cLabel}优化后空闲内存 : ${reset}${cText}$(Format-MemorySize $after)$reset"
- if ($delta -gt 0) {
- Write-Host " ${cLabel}释放量 : ${reset}${green}+$(Format-MemorySize $delta)$reset"
- } else {
- Write-Host " ${cLabel}释放量 : ${reset}${cDim}内存已处于最佳状态,无需释放$reset"
- }
- if ($null -ne $global:lastManualDelta) {
- $diff = $delta - $global:lastManualDelta
- $diffColor = if ($diff -ge 0) { $green } else { $red }
- $sign = if ($diff -ge 0) { "+" } else { "" }
- Write-Host " ${cLabel}比上次 : ${reset}${diffColor}$sign$(Format-MemorySize $diff)$reset"
- }
- $global:lastManualDelta = $delta
- Write-Host " ${cDim}───────────────────────────────────$reset`n"
- [Console]::CursorVisible = $true
- Write-Host "按任意键返回主菜单..."
- cmd /c pause | Out-Null
- }
- # ========== 自动模式 ==========
- $script:lastDelta = 0
- $script:nextRunTime = Get-Date
- function Show-MarqueCleanup {
- param([scriptblock]$Action)
- $line = [System.Console]::CursorTop
- Write-Host " $cLine┌──────────────────────────────────┐$reset"
- Write-Host " $cLine│$cStep ⏸️ 正在静默释放内存... │$reset"
- Write-Host " $cLine└──────────────────────────────────┘$reset"
- $boxEndLine = [System.Console]::CursorTop - 1
- & $Action
- $spin = @('⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏')
- for ($i=0; $i -lt 20; $i++) {
- [System.Console]::SetCursorPosition(0, $boxEndLine - 1)
- Write-Host " $cLine│$cStep ⏸️ 正在静默释放内存... $($spin[$i % 10]) $cLine│$reset"
- Start-Sleep -Milliseconds 100
- }
- [System.Console]::SetCursorPosition(0, $boxEndLine - 2)
- Write-Host " $cLine┌──────────────────────────────────┐$reset"
- Write-Host " $cLine│$cOK ✅ 静默释放完成 $cLine│$reset"
- Write-Host " $cLine└──────────────────────────────────┘$reset"
- Write-Host ""
- }
- function Draw-IdleBox {
- param([datetime]$NextRun)
- $timeStr = $NextRun.ToString("yyyy.MM.dd HH:mm")
- Write-Host "$cLine┌─────────────────────────────────────┐$reset"
- Write-Host "$cLine│$cText 计划下次在 ${cTime}$timeStr $cLine│$reset"
- Write-Host "$cLine│$cText 静默释放内存 $cLine│$reset"
- Write-Host "$cLine└─────────────────────────────────────┘$reset"
- }
- function AutoRun {
- param([int]$IntervalSeconds)
- Clear-Host
- [Console]::CursorVisible = $false
- Write-Host "$cLine┌─────────────────────────────────────┐$reset"
- Write-Host "$cLine│$cTitle 自动模式(跑马灯) $cLine│$reset"
- Write-Host "$cLine└─────────────────────────────────────┘$reset`n"
- $before = Get-FreeMemoryBytes
- Show-MarqueCleanup { Clear-MemoryAll }
- $after = Get-FreeMemoryBytes
- $delta = $after - $before
- $script:lastDelta = $delta
- Write-Host " ${cLabel}本次释放量 : ${reset}${cText}$(Format-MemorySize $delta)$reset"
- Write-Host " ${cDim}${cBracket}(${cBracketTxt}首次释放,无历史比较${cBracket})$reset`n"
- Start-Sleep -Seconds 1.5
- $script:nextRunTime = (Get-Date).AddSeconds($IntervalSeconds)
- Clear-Host
- [System.Console]::SetCursorPosition(0, 0)
- Draw-IdleBox -NextRun $script:nextRunTime
- while ($true) {
- $waitSeconds = [math]::Max(1, ($script:nextRunTime - (Get-Date)).TotalSeconds)
- Start-Sleep -Seconds ([int]($waitSeconds))
- if ((Get-Date) -ge $script:nextRunTime) {
- Clear-Host
- [System.Console]::SetCursorPosition(0, 0)
- $b = Get-FreeMemoryBytes
- Show-MarqueCleanup { Clear-MemoryAll }
- $a = Get-FreeMemoryBytes
- $d = $a - $b
- Write-Host " ${cLabel}本次释放量 : ${reset}${cText}$(Format-MemorySize $d)$reset"
- if ($script:lastDelta -ne 0) {
- $diff = $d - $script:lastDelta
- $diffColor = if ($diff -ge 0) { $green } else { $red }
- $sign = if ($diff -ge 0) { "+" } else { "" }
- Write-Host " ${cLabel}比上次 : ${reset}${diffColor}$sign$(Format-MemorySize $diff)$reset"
- } else {
- Write-Host " ${cDim}${cBracket}(${cBracketTxt}首次释放,无历史比较${cBracket})$reset"
- }
- $script:lastDelta = $d
- $script:nextRunTime = (Get-Date).AddSeconds($IntervalSeconds)
- Start-Sleep -Seconds 2
- Clear-Host
- [System.Console]::SetCursorPosition(0, 0)
- Draw-IdleBox -NextRun $script:nextRunTime
- }
- }
- }
- # ========== 主菜单 ==========
- function Show-MainMenu {
- while ($true) {
- Clear-Host
- Write-Host "$cLine┌─────────────────────────────────────┐$reset"
- Write-Host "$cLine│$cTitle Win11 内存净化器 $cLine│$reset"
- Write-Host "$cLine└─────────────────────────────────────┘$reset`n"
- Write-Host " ${cText}1. 手动运行 ${cBracket}(${cBracketTxt}三步仪式感${cBracket})$reset"
- Write-Host " ${cText}2. 自动运行 ${cBracket}(${cBracketTxt}定时静默释放${cBracket})$reset"
- Write-Host " ${cText}3. 退出$reset"
- Write-Host ""
- $choice = Read-Host " 请选择 (1/2/3)"
- switch ($choice) {
- '1' { ManualRun }
- '2' {
- Clear-Host
- Write-Host " ${cText}选择自动释放间隔:$reset"
- Write-Host " ${cText}1. ${cBracketTxt}30 分钟$reset"
- Write-Host " ${cText}2. ${cBracketTxt}1 小时$reset"
- Write-Host " ${cText}3. ${cBracketTxt}2 小时$reset"
- Write-Host " ${cText}4. ${cBracketTxt}3 小时$reset"
- Write-Host " ${cText}5. ${cBracketTxt}5 小时$reset"
- if ($global:DebugIntervalSeconds -gt 0) {
- Write-Host " ${cText}6. ${cDim}测试模式 ${cBracket}(${cBracketTxt}当前间隔: $global:DebugIntervalSeconds 秒${cBracket})$reset"
- }
- Write-Host ""
- $sub = Read-Host " 输入数字"
- $interval = switch ($sub) {
- '1' { 30 * 60 }
- '2' { 60 * 60 }
- '3' { 120 * 60 }
- '4' { 180 * 60 }
- '5' { 300 * 60 }
- '6' { if ($global:DebugIntervalSeconds -gt 0) { $global:DebugIntervalSeconds } else { Write-Host "无效选项,返回主菜单"; Start-Sleep 1; continue } }
- default { Write-Host "无效选项,返回主菜单"; Start-Sleep 1; continue }
- }
- AutoRun -IntervalSeconds $interval
- }
- '3' {
- Write-Host "`n ${cText}已退出,愉快!$reset`n"
- exit
- }
- default {
- Write-Host " ${cWarn}无效选项,请重新输入$reset"
- Start-Sleep 1
- }
- }
- }
- }
- <# ========== 入口 ==========
- 调试模式函数参数方法:
- Enable-DebugMode -Interval 600
- Enable-DebugMode -Interval 00:00:05
- Enable-DebugMode -Interval 1:30 -PassThru # Pass 用于采用默认模式
- #>
- Show-MainMenu
复制代码 |