[i=s] 本帖最后由 MinecraftTAO 于 2026-7-14 15:51 编辑 [/i]
对于 eNSP 强制关闭 Windows 视觉特效的自动化恢复实现
1. 现象与背景
长期以来,运行华为 eNSP 模拟器会伴随一个固定的系统行为:软件启动时,会强行修改 Windows 的性能选项(即“高级系统设置”中的“视觉效果”)。
直观表现为:
- 窗口拖动时不再显示内容,仅显示虚线边框。
- 整个 Windows 系统的菜单、窗口阴影等 UI 特效消失。
对于习惯了现代操作系统流畅体验的用户来说,这种十多年前为了节省系统资源而采取的“优化”策略,目前已成为一种干扰。通常的做法是在运行 eNSP 后,手动去高级系统设置中重新勾选并应用,过程繁琐且重复。
2. 实现思路
为了使修复过程静默且自动化,可以通过脚本监听 eNSP 进程的启动,并在其执行完环境降级后,通过调用底层的 Win32 API 强制将系统的视觉状态反转回来,并向全系统广播更新,从而免去手动点击设置面板的麻烦。
核心步骤如下:
- 调用
user32.dll 中的 SystemParametersInfo 函数,修改 SPI_SETDRAGFULLWINDOWS 和 SPI_SETUIEFFECTS。
- 借用
SendMessageTimeout 发送 WM_SETTINGCHANGE 广播,强制 DWM(桌面窗口管理器)和 Explorer 重新校准渲染状态。
3. 源码实现 (PowerShell)
坦白讲,我对 PowerShell 的复杂语法和底层的 Win32 API 并不精通。这仅仅是一次纯粹的 “AI 辅助编程” 实践。
在这其中,我的工作仅仅是发现痛点、梳理出环境检测与进程监听的修复逻辑,然后交由 AI 完成具体的代码构建。相比于那些真正手写底层脚本的技术大牛,这只是一次简单的实现。
代码本身应当是一种无主的信息流动,任何人都可以自由地复制、修改、二次编译或重新分发,无需标明出处。
以下是未经过任何混淆的 PowerShell 源码:
# 定义 Windows 底层全量视觉广播 API(新增 GET 读取接口)
$code = @'
using System;
using System.Runtime.InteropServices;
public class WinVisualFixer {
// 设置状态的 API
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);
// 新增:专门用于【读取】当前系统状态的探针 API
[DllImport("user32.dll", EntryPoint = "SystemParametersInfo", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfoGet(uint uiAction, uint uiParam, out int pvParam, uint fWinIni);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out IntPtr lpdwResult);
public const uint SPI_SETDRAGFULLWINDOWS = 0x0025;
public const uint SPI_GETDRAGFULLWINDOWS = 0x0026; // 新增:读取拖动窗口状态常量
public const uint SPI_SETUIEFFECTS = 0x103F;
public const uint WM_SETTINGCHANGE = 0x001A;
public const uint HWND_BROADCAST = 0xFFFF;
public const uint SMTO_ABORTIFHUNG = 0x0002;
}
'@
Add-Type -TypeDefinition $code
# ==================== 1. 启动 eNSP ====================
# 先强制系统特效开启,给 eNSP 准备一个干净的“靶子”
[WinVisualFixer]::SystemParametersInfo([WinVisualFixer]::SPI_SETDRAGFULLWINDOWS, 1, [IntPtr]0, 3)
$enspPath = "C:\Program Files\Huawei\eNSP\eNSP_Client.exe"
Start-Process -FilePath $enspPath
# ==================== 2. 部署探针死盯系统内存 ====================
Write-Host "底层探针已部署,正在监控 eNSP 的篡改行为..."
$retryCount = 0
# 最多监控 40 秒 (每 0.5 秒扫描一次内存),完美应对老电脑第一次极慢的冷启动
while ($retryCount -lt 80) {
$status = 0
# 读取当前系统的拖拽特效状态
[WinVisualFixer]::SystemParametersInfoGet([WinVisualFixer]::SPI_GETDRAGFULLWINDOWS, 0, [ref]$status, 0)
# 状态变成 0,说明捕捉到了 eNSP 的阉割行为!
if ($status -eq 0) {
Write-Host "捕捉到特效被关闭!准备执行反杀..."
# 捕捉到后,多给它 1.5 秒让它把剩下的菜单阴影也破坏完,方便我们一次性全量反杀
Start-Sleep -Seconds 1.5
break
}
Start-Sleep -Milliseconds 500
$retryCount++
}
# ==================== 3. 致命反击:全量强刷内存 ====================
Write-Host "开始全量恢复视觉效果..."
# 恢复:拖动时显示窗口内容
[WinVisualFixer]::SystemParametersInfo([WinVisualFixer]::SPI_SETDRAGFULLWINDOWS, 1, [IntPtr]0, 3)
# 恢复:鼠标阴影/缩略图等全局 UI 特效
[WinVisualFixer]::SystemParametersInfo([WinVisualFixer]::SPI_SETUIEFFECTS, 0, [IntPtr]1, 3)
$result = [IntPtr]::Zero
[WinVisualFixer]::SendMessageTimeout(
[IntPtr][WinVisualFixer]::HWND_BROADCAST,
[WinVisualFixer]::WM_SETTINGCHANGE,
[IntPtr]0,
"WindowMetrics",
[WinVisualFixer]::SMTO_ABORTIFHUNG,
5000,
[ref]$result
)
Write-Host "全量视觉特效已强制恢复!窗口同步拖动、阴影、缩略图已固若金汤。"
Start-Sleep -Seconds 2
4. 封装与部署方案
考虑到每次右键运行 PowerShell 会有黑框闪烁,且交互不够直接。为了更方便地使用,我已经将上述脚本打包。
处理流程说明:
- 使用
ps2exe 将上述 .ps1 脚本转换为不带控制台黑框的静默可执行文件。
- 借用 NSIS (Nullsoft Scriptable Install System) 编写了安装脚本。该安装包会在执行前自动检测
$PROGRAMFILES\Huawei\eNSP 目录下是否存在 eNSP_Client.exe,以此避免未安装 eNSP 的用户误操作,并在桌面建立指向该补丁的快捷方式。
有动手能力的,完全可以根据上面的源码和思路自己用 NSIS 编译一份。
如果图省事,也可以直接下载我编译好的成品包。以后启动 eNSP 时,只需双击桌面上的 eNSP(优化版)快捷方式,拖拽无内容的现象将会在启动 2 秒后自动消失。
成品文件下载:
https://leon.lanzoue.com/iV08g3wd9nne