MinecraftTAO 发表于 2026-7-12 08:24:22

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

本帖最后由 MinecraftTAO 于 2026-7-14 15:51 编辑

<h1>对于 eNSP 强制关闭 Windows 视觉特效的自动化恢复实现</h1>
<h3>1. 现象与背景</h3>
<p>长期以来,运行华为 eNSP 模拟器会伴随一个固定的系统行为:软件启动时,会强行修改 Windows 的性能选项(即“高级系统设置”中的“视觉效果”)。<br />
直观表现为:</p>
<ol>
<li>窗口拖动时不再显示内容,仅显示虚线边框。</li>
<li>整个 Windows 系统的菜单、窗口阴影等 UI 特效消失。</li>
</ol>
<p>对于习惯了现代操作系统流畅体验的用户来说,这种十多年前为了节省系统资源而采取的“优化”策略,目前已成为一种干扰。通常的做法是在运行 eNSP 后,手动去高级系统设置中重新勾选并应用,过程繁琐且重复。</p>
<h3>2. 实现思路</h3>
<p>为了使修复过程静默且自动化,可以通过脚本监听 eNSP 进程的启动,并在其执行完环境降级后,通过调用底层的 Win32 API 强制将系统的视觉状态反转回来,并向全系统广播更新,从而免去手动点击设置面板的麻烦。</p>
<p>核心步骤如下:</p>
<ol>
<li>调用 <code>user32.dll</code> 中的 <code>SystemParametersInfo</code> 函数,修改 <code>SPI_SETDRAGFULLWINDOWS</code> 和 <code>SPI_SETUIEFFECTS</code>。</li>
<li>借用 <code>SendMessageTimeout</code> 发送 <code>WM_SETTINGCHANGE</code> 广播,强制 DWM(桌面窗口管理器)和 Explorer 重新校准渲染状态。</li>
</ol>
<h3>3. 源码实现 (PowerShell)</h3>
<p>坦白讲,我对 PowerShell 的复杂语法和底层的 Win32 API 并不精通。这仅仅是一次纯粹的 <strong>“AI 辅助编程”</strong> 实践。</p>
<p>在这其中,我的工作仅仅是发现痛点、梳理出环境检测与进程监听的修复逻辑,然后交由 AI 完成具体的代码构建。相比于那些真正手写底层脚本的技术大牛,这只是一次简单的实现。</p>
<p>代码本身应当是一种无主的信息流动,任何人都可以自由地复制、修改、二次编译或重新分发,无需标明出处。</p>
<p>以下是未经过任何混淆的 PowerShell 源码:</p>
<pre><code class="language-powershell"># 定义 Windows 底层全量视觉广播 API(新增 GET 读取接口)
$code = @'
using System;
using System.Runtime.InteropServices;

public class WinVisualFixer {
    // 设置状态的 API
   
   
    public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);

    // 新增:专门用于【读取】当前系统状态的探针 API
   
   
    public static extern bool SystemParametersInfoGet(uint uiAction, uint uiParam, out int pvParam, uint fWinIni);

   
    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 准备一个干净的“靶子”
::SystemParametersInfo(::SPI_SETDRAGFULLWINDOWS, 1, 0, 3)

$enspPath = &quot;C:\Program Files\Huawei\eNSP\eNSP_Client.exe&quot;
Start-Process -FilePath $enspPath

# ==================== 2. 部署探针死盯系统内存 ====================
Write-Host &quot;底层探针已部署,正在监控 eNSP 的篡改行为...&quot;

$retryCount = 0
# 最多监控 40 秒 (每 0.5 秒扫描一次内存),完美应对老电脑第一次极慢的冷启动
while ($retryCount -lt 80) {
    $status = 0
    # 读取当前系统的拖拽特效状态
    ::SystemParametersInfoGet(::SPI_GETDRAGFULLWINDOWS, 0, $status, 0)
   
    # 状态变成 0,说明捕捉到了 eNSP 的阉割行为!
    if ($status -eq 0) {
      Write-Host &quot;捕捉到特效被关闭!准备执行反杀...&quot;
      # 捕捉到后,多给它 1.5 秒让它把剩下的菜单阴影也破坏完,方便我们一次性全量反杀
      Start-Sleep -Seconds 1.5
      break
    }
   
    Start-Sleep -Milliseconds 500
    $retryCount++
}

# ==================== 3. 致命反击:全量强刷内存 ====================
Write-Host &quot;开始全量恢复视觉效果...&quot;

# 恢复:拖动时显示窗口内容
::SystemParametersInfo(::SPI_SETDRAGFULLWINDOWS, 1, 0, 3)

# 恢复:鼠标阴影/缩略图等全局 UI 特效
::SystemParametersInfo(::SPI_SETUIEFFECTS, 0, 1, 3)

$result = ::Zero
::SendMessageTimeout(
    ::HWND_BROADCAST,
    ::WM_SETTINGCHANGE,
    0,
    &quot;WindowMetrics&quot;,
    ::SMTO_ABORTIFHUNG,
    5000,
    $result
)

Write-Host &quot;全量视觉特效已强制恢复!窗口同步拖动、阴影、缩略图已固若金汤。&quot;
Start-Sleep -Seconds 2
</code></pre>
<h3>4. 封装与部署方案</h3>
<p>考虑到每次右键运行 PowerShell 会有黑框闪烁,且交互不够直接。为了更方便地使用,我已经将上述脚本打包。</p>
<p><strong>处理流程说明:</strong></p>
<ol>
<li>使用 <code>ps2exe</code> 将上述 <code>.ps1</code> 脚本转换为不带控制台黑框的静默可执行文件。</li>
<li>借用 NSIS (Nullsoft Scriptable Install System) 编写了安装脚本。该安装包会在执行前自动检测 <code>$PROGRAMFILES\Huawei\eNSP</code> 目录下是否存在 <code>eNSP_Client.exe</code>,以此避免未安装 eNSP 的用户误操作,并在桌面建立指向该补丁的快捷方式。</li>
</ol>
<p>有动手能力的,完全可以根据上面的源码和思路自己用 NSIS 编译一份。<br />
如果图省事,也可以直接下载我编译好的成品包。以后启动 eNSP 时,只需双击桌面上的 <code>eNSP(优化版)</code>快捷方式,拖拽无内容的现象将会在启动 2 秒后自动消失。</p>
<p><strong>成品文件下载:</strong></p>
<blockquote>
<p><a href="https://leon.lanzoue.com/iV08g3wd9nne">https://leon.lanzoue.com/iV08g3wd9nne</a></p>
</blockquote>

iminsh 发表于 2026-7-12 09:18:45

多谢分享 多谢分享 多谢分享

zjb0702 发表于 2026-7-13 10:08:45

<p>老哥,每次打开自带的cmd输入法都是中文,要手动切换英文,有没有脚本自动切换呢<img alt="lol" class="emoji" src="https://www.emulatedlab.com/static/image/smiley/default/lol.gif" title="lol" /></p>

MinecraftTAO 发表于 2026-7-13 14:07:42

zjb0702 发表于 2026-7-13 10:08
老哥,每次打开自带的cmd输入法都是中文,要手动切换英文,有没有脚本自动切换呢
...

<p>如果你非要用脚本,技术上是完全可以实现的:可以通过修改注册表的 <code>HKCU\Software\Microsoft\Command Processor\AutoRun</code>,让 CMD 每次启动时静默运行一段脚本,调用 <code>user32.dll</code> 的 <code>LoadKeyboardLayout</code> 强制把当前窗口切成英文。</p>
<p><strong>但我强烈不建议这么做。</strong></p>
<p>因为 CMD 的核心优势就是“秒开”。如果挂载了这段 API 脚本,每次打开 CMD 都会有 0.5 到 1 秒的卡顿(因为要等待底层 API 注入)。为了不按一下 Shift 而牺牲 CMD 的启动速度,得不偿失。</p>
<p>针对这个问题,其实不需要脚本,系统层面有 3 种更优雅、零性能损耗的解决方案,按推荐程度排序:</p>
<p><strong>方案一:开启 Windows 的“输入法记忆”功能(最省事)</strong><br />
打开 Windows 的 <code>设置</code> -&gt; <code>时间和语言</code> -&gt; <code>语言</code> -&gt; <code>键盘</code>。<br />
勾选 <strong>“允许我为每个应用窗口设置不同的输入法”</strong>。<br />
勾选之后,你只要在 CMD 里切过一次英文,系统就会单独记住这个进程。下次再开 CMD,它就是英文,而你切回微信/浏览器,依然是中文,互不干扰。</p>
<p><strong>方案二:程序员的终极方案(全局默认英文)</strong><br />
这是绝大多数开发的终极选择:在语言设置里,添加一个纯正的 <strong>【英语(美国)】</strong> 语言包,并在高级设置里把它设为“默认输入法”。<br />
这样电脑开机、打开任何软件(包括 CMD、VSCode),默认全是纯英文环境,敲命令再也不会打出中文字符。需要聊天打字时,按 <code>Win + Space(空格)</code> 临时切回中文即可。</p>
<p><strong>方案三:抛弃 CMD,拥抱 Windows Terminal</strong><br />
CMD 已经是上个世纪的产物了。建议直接去微软商店免费下载官方的 <strong>Windows Terminal</strong>。它不仅支持多标签页,而且对输入法的兼容性、环境变量的适配极佳,体验会直接提升一个时代。</p>

zjb0702 发表于 2026-7-15 09:51:25

MinecraftTAO 发表于 2026-7-13 14:07
如果你非要用脚本,技术上是完全可以实现的:可以通过修改注册表的 HKCU\Software\Microsoft\Command Pro ...

感谢老哥,方案一只有默认的微软输入法可以
页: [1]
查看完整版本: 对于 eNSP 强制关闭 Windows 视觉特效的自动化恢复实现