查看: 267|回复: 4

对于 eNSP 强制关闭 Windows 视觉特效的自动化恢复实现

1

主题

28

回帖

7535

积分

金牌会员

Rank: 6Rank: 6

积分
7535
[i=s] 本帖最后由 MinecraftTAO 于 2026-7-14 15:51 编辑 [/i]

对于 eNSP 强制关闭 Windows 视觉特效的自动化恢复实现

1. 现象与背景

长期以来,运行华为 eNSP 模拟器会伴随一个固定的系统行为:软件启动时,会强行修改 Windows 的性能选项(即“高级系统设置”中的“视觉效果”)。
直观表现为:

  1. 窗口拖动时不再显示内容,仅显示虚线边框。
  2. 整个 Windows 系统的菜单、窗口阴影等 UI 特效消失。

对于习惯了现代操作系统流畅体验的用户来说,这种十多年前为了节省系统资源而采取的“优化”策略,目前已成为一种干扰。通常的做法是在运行 eNSP 后,手动去高级系统设置中重新勾选并应用,过程繁琐且重复。

2. 实现思路

为了使修复过程静默且自动化,可以通过脚本监听 eNSP 进程的启动,并在其执行完环境降级后,通过调用底层的 Win32 API 强制将系统的视觉状态反转回来,并向全系统广播更新,从而免去手动点击设置面板的麻烦。

核心步骤如下:

  1. 调用 user32.dll 中的 SystemParametersInfo 函数,修改 SPI_SETDRAGFULLWINDOWS 和 SPI_SETUIEFFECTS。
  2. 借用 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 会有黑框闪烁,且交互不够直接。为了更方便地使用,我已经将上述脚本打包。

处理流程说明:

  1. 使用 ps2exe 将上述 .ps1 脚本转换为不带控制台黑框的静默可执行文件。
  2. 借用 NSIS (Nullsoft Scriptable Install System) 编写了安装脚本。该安装包会在执行前自动检测 $PROGRAMFILES\Huawei\eNSP 目录下是否存在 eNSP_Client.exe,以此避免未安装 eNSP 的用户误操作,并在桌面建立指向该补丁的快捷方式。

有动手能力的,完全可以根据上面的源码和思路自己用 NSIS 编译一份。
如果图省事,也可以直接下载我编译好的成品包。以后启动 eNSP 时,只需双击桌面上的 eNSP(优化版)快捷方式,拖拽无内容的现象将会在启动 2 秒后自动消失。

成品文件下载:

https://leon.lanzoue.com/iV08g3wd9nne

回复

使用道具 举报

0

主题

347

回帖

14万

积分

富可敌国

积分
141726
发表于 2026-7-12 09:18:45 | 显示全部楼层
多谢分享 多谢分享 多谢分享

回复

使用道具 举报

1

主题

37

回帖

1925

积分

高级会员

Rank: 4

积分
1925
发表于 2026-7-13 10:08:45 | 显示全部楼层

老哥,每次打开自带的cmd输入法都是中文,要手动切换英文,有没有脚本自动切换呢lol

回复

使用道具 举报

1

主题

28

回帖

7535

积分

金牌会员

Rank: 6Rank: 6

积分
7535
 楼主| 发表于 2026-7-13 14:07:42 | 显示全部楼层
[quote][size=2][url=forum.php?mod=redirect&goto=findpost&pid=91675&ptid=2377][color=#999999]zjb0702 发表于 2026-7-13 10:08[/color][/url][/size] 老哥,每次打开自带的cmd输入法都是中文,要手动切换英文,有没有脚本自动切换呢 ...[/quote]

如果你非要用脚本,技术上是完全可以实现的:可以通过修改注册表的 HKCU\Software\Microsoft\Command Processor\AutoRun,让 CMD 每次启动时静默运行一段脚本,调用 user32.dll 的 LoadKeyboardLayout 强制把当前窗口切成英文。

但我强烈不建议这么做。

因为 CMD 的核心优势就是“秒开”。如果挂载了这段 API 脚本,每次打开 CMD 都会有 0.5 到 1 秒的卡顿(因为要等待底层 API 注入)。为了不按一下 Shift 而牺牲 CMD 的启动速度,得不偿失。

针对这个问题,其实不需要脚本,系统层面有 3 种更优雅、零性能损耗的解决方案,按推荐程度排序:

方案一:开启 Windows 的“输入法记忆”功能(最省事)
打开 Windows 的 设置 -> 时间和语言 -> 语言 -> 键盘。
勾选 “允许我为每个应用窗口设置不同的输入法”。
勾选之后,你只要在 CMD 里切过一次英文,系统就会单独记住这个进程。下次再开 CMD,它就是英文,而你切回微信/浏览器,依然是中文,互不干扰。

方案二:程序员的终极方案(全局默认英文)
这是绝大多数开发的终极选择:在语言设置里,添加一个纯正的 【英语(美国)】 语言包,并在高级设置里把它设为“默认输入法”。
这样电脑开机、打开任何软件(包括 CMD、VSCode),默认全是纯英文环境,敲命令再也不会打出中文字符。需要聊天打字时,按 Win + Space(空格) 临时切回中文即可。

方案三:抛弃 CMD,拥抱 Windows Terminal
CMD 已经是上个世纪的产物了。建议直接去微软商店免费下载官方的 Windows Terminal。它不仅支持多标签页,而且对输入法的兼容性、环境变量的适配极佳,体验会直接提升一个时代。

回复

使用道具 举报

1

主题

37

回帖

1925

积分

高级会员

Rank: 4

积分
1925
发表于 2026-7-15 09:51:25 | 显示全部楼层
MinecraftTAO 发表于 2026-7-13 14:07
如果你非要用脚本,技术上是完全可以实现的:可以通过修改注册表的 HKCU\Software\Microsoft\Command Pro ...

感谢老哥,方案一只有默认的微软输入法可以
回复

使用道具 举报

本版积分规则

Copyright   ©2015-2026  EmulatedLab  Powered by Discuz!©   ( 浙ICP备2021010423号-1 )
快速回复 返回列表 返回顶部