保亭黎族苗族自治县网站建设_网站建设公司_VPS_seo优化
2025/12/21 2:34:34 网站建设 项目流程

一、引子

每天下班前,我都有一个“强迫症”习惯:把电脑上所有打开的程序都关掉,再执行关机
这不仅是为了让第二天开机时系统清爽、启动迅速,更是为了避免:

  • 浏览器恢复几十个标签页,拖慢系统;
  • 微信/QQ 留在后台偷偷上传日志或接收消息;
  • 某些编辑器(如 Typora、Notion)因未保存而丢失草稿;
  • 文件资源管理器窗口残留,占用内存;
  • 最讨厌的是——有些软件关闭时还会弹出“是否保存?”“是否退出后台?”的二次确认对话框……

手动一个个点?效率太低,还容易遗漏托盘里的程序。
直接强制关机?又总觉得“不干净”,心理上过不去。

于是,我开始思考:有没有一种方法,能一键、安全、彻底地关闭当前用户启动的所有非系统应用程序?

答案是肯定的。


二、核心需求与设计目标

在动手写代码前,必须明确我们到底要什么:

需求说明
✅ 关闭所有用户启动的应用包括前台窗口、后台运行、最小化到托盘的程序
✅ 安全关闭文件资源管理器窗口不能杀explorer.exe,否则桌面消失
✅ 不影响系统关键进程dwm.exesihost.exe、任务栏、开始菜单等
✅ 提供图形化确认防止误操作导致数据丢失
✅ 脚本自身不被关闭避免“自杀式”执行
✅ 兼容中文路径与无窗口程序确保在各种环境下稳定运行
✅ 操作完成后有反馈告知用户关闭了多少程序

三、技术方案

3.1 为什么传统方法行不通?

很多网上教程推荐用:

Get-Process|Where MainWindowTitle|Stop-Process

但这种方法存在致命缺陷:

  • 托盘程序无窗口MainWindowTitle为空 → 被跳过;
  • 资源管理器窗口无法关闭→ 因为explorer.exe是外壳进程,通常被排除;
  • 无法区分“你的程序”和“系统程序”→ 可能误杀。

因此,我们必须放弃“窗口依赖”,转向更底层的进程归属判断

3.2 关键技术点

(1)通过 SID 识别用户进程

每个 Windows 进程都有一个所有者(Owner),其唯一标识是安全标识符(SID)
我们可以:

  • 获取当前登录用户的 SID;
  • 遍历所有进程,筛选出属于该 SID 的进程。
$currentUserSid=([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value$ownerSid=$proc.GetOwnerSid().Sidif($ownerSid-eq$currentUserSid){/*是用户程序*/}
(2)安全关闭资源管理器窗口

使用Shell.ApplicationCOM 对象,仅关闭窗口而不终止进程:

$shell=New-Object-ComObject Shell.Applicationforeach($windowin$shell.Windows()){if($window.FullName-like"*explorer.exe"){$window.Quit()}}
(3)图形化确认对话框

调用 .NET 的PresentationFramework,弹出标准 Windows 消息框:

Add-Type-AssemblyName PresentationFramework[System.Windows.MessageBox]::Show("确认关闭?","警告",'YesNo','Warning')

四、完整脚本:CloseAllUserApps.ps1

✅ 支持中文系统
✅ 兼容 PowerShell 5.1 及 PowerShell 7+
✅ 无需管理员权限
✅ 自动排除脚本自身

# ==============================================================================# CloseAllUserApps.ps1# 功能:一键关闭当前用户启动的所有非系统应用程序(含托盘程序)# 特性:# - 弹出标准 Windows 图形确认对话框# - 安全关闭所有文件资源管理器窗口(不终止 explorer.exe)# - 基于 SID 精准识别用户进程# - 多重防护:排除系统关键进程 + 系统目录程序 + 脚本自身# - 执行后弹出结果提示## 作者:xiaoli# 日期:2025-12-20# 许可:MIT(可自由使用、修改、分发,保留作者信息即可)# ==============================================================================# 加载 WPF 组件以支持图形消息框Add-Type-AssemblyName PresentationFramework# -----------------------------# 第一步:图形化确认# -----------------------------$caption="确认关闭所有应用程序?"$message= @" ⚠️ 此操作将强制关闭您当前登录用户启动的所有应用程序, 包括最小化到系统托盘的程序(如微信、QQ、网易云音乐、Steam 等), 并关闭所有文件资源管理器窗口。 ❗ 未保存的工作(文档、聊天记录、草稿等)将会永久丢失! 是否继续? "@$result=[System.Windows.MessageBox]::Show($message,$caption,'YesNo','Warning')if($result-ne'Yes'){[System.Windows.MessageBox]::Show('操作已取消。','已取消','OK','Information')exit}Write-Host"`n✅ 用户确认执行,开始清理..."-ForegroundColor Green# -----------------------------# 第二步:安全关闭资源管理器窗口# -----------------------------try{$shell=New-Object-ComObject Shell.Application$windows=$shell.Windows()if($windows-and$windows.Count-gt0){Write-Host"正在关闭$($windows.Count)个文件资源管理器窗口..."-ForegroundColor Cyan# 从后往前遍历,避免索引变化问题for($i=$windows.Count-1;$i-ge0;$i--){$window=$windows.Item($i)if($window.FullName-like"*explorer.exe"){try{$window.Quit()}catch{}}}}}catch{Write-Host"⚠️ 跳过资源管理器窗口关闭(COM 对象不可用)"-ForegroundColor Yellow}# -----------------------------# 第三步:获取当前用户 SID# -----------------------------try{$currentUserSid=([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value}catch{[System.Windows.MessageBox]::Show("无法获取当前用户身份,请重试。","错误","OK","Error")exit}# -----------------------------# 第四步:定义排除列表(关键系统进程)# -----------------------------$excludedNames= @('explorer.exe',# 桌面外壳(窗口已单独处理)'dwm.exe',# 桌面窗口管理器(关了会黑屏)'sihost.exe',# Shell 基础服务'taskhostw.exe','RuntimeBroker.exe','ShellExperienceHost.exe','StartMenuExperienceHost.exe','SearchApp.exe','TextInputHost.exe','SecurityHealthSystray.exe','conhost.exe',# 控制台宿主'powershell.exe',# 当前脚本进程(防止自杀)'pwsh.exe','WindowsTerminal.exe','ApplicationFrameHost.exe','dllhost.exe','fontdrvhost.exe','WUDFHost.exe')# -----------------------------# 第五步:筛选并终止用户应用程序# -----------------------------try{$allProcesses=Get-WmiObject-ClassWin32_Process-ErrorAction Stop}catch{[System.Windows.MessageBox]::Show("无法访问进程列表,请以普通用户身份运行此脚本。","权限错误","OK","Error")exit}$userAppProcesses=foreach($procin$allProcesses){# 跳过无效或系统保留 PIDif(-not$proc.ProcessId-or$proc.ProcessId-lt4){continue}# 获取进程所有者 SIDtry{$ownerSid=$proc.GetOwnerSid().Sid}catch{continue# 无权限或内核进程}# 仅处理当前用户的进程if($ownerSid-ne$currentUserSid){continue}# 排除关键进程名if($proc.Name-in$excludedNames){continue}# 排除位于系统目录(%windir%)下的程序(增强安全性)if($proc.ExecutablePath-and$proc.ExecutablePath.StartsWith("$env:windir\")){continue}# 输出符合条件的进程$proc}# -----------------------------# 第六步:执行终止并反馈结果# -----------------------------if($userAppProcesses){$count=($userAppProcesses|Measure-Object).CountWrite-Host"正在终止$count个用户应用程序..."-ForegroundColor Yellowforeach($procin$userAppProcesses){try{Stop-Process-Id$proc.ProcessId-Force-ErrorAction SilentlyContinue}catch{# 忽略已退出或受保护的进程}}[System.Windows.MessageBox]::Show("✅ 成功关闭$count个应用程序。","完成","OK","Information")}else{[System.Windows.MessageBox]::Show("未找到可关闭的用户应用程序。","提示","OK","Information")}

五、使用指南

步骤 1:保存脚本文件

  1. 复制上方完整脚本;
  2. 打开记事本(Notepad)
  3. 粘贴内容;
  4. 点击文件 → 另存为
  5. 文件名输入:CloseAllUserApps.ps1
    注意:务必选择“所有文件”类型,编码建议选UTF-8
  6. 保存到例如:C:\Scripts\或桌面。

步骤 2:设置 PowerShell 执行策略(首次使用)

Windows 默认禁止运行.ps1脚本。需临时允许本地脚本:

  1. Win + R,输入powershell,回车(不要用“以管理员身份运行”);
  2. 执行命令:
    Set-ExecutionPolicy-ExecutionPolicy RemoteSigned-Scope CurrentUser
  3. 输入Y并回车。

🔒 说明:RemoteSigned策略允许本地脚本运行,远程脚本需数字签名,兼顾安全与便利。

步骤 3:运行脚本

  • 推荐方式:右键CloseAllUserApps.ps1“使用 PowerShell 运行”
  • 或在 PowerShell 中执行:
    .\CloseAllUserApps.ps1

步骤 4:创建桌面快捷方式(可选但推荐)

  1. 右键桌面 → 新建 → 快捷方式;
  2. 在“位置”栏输入:
    powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Scripts\CloseAllUserApps.ps1"

    -WindowStyle Hidden可隐藏控制台窗口,仅显示图形对话框。

  3. 点击“下一步”,命名为 “一键清理应用”;
  4. 完成后,可右键快捷方式 → 属性 → 更换图标(建议使用红色 × 或垃圾桶图标)。

现在,双击该快捷方式即可一键清理!


六、注意事项

⚠️ 重要警告

  • 所有未保存的数据将永久丢失!请确保已保存工作。
  • 某些程序(如 OneDrive、Teams、钉钉)设计为“常驻后台”,关闭后可能自动重启,属正常行为。
  • 切勿以管理员身份运行此脚本,以免误杀系统服务。
  • 脚本不会关闭explorer.exe进程,因此桌面、任务栏、开始菜单始终可用。

七、常见问题解答(FAQ)

Q1:为什么资源管理器窗口关了,但桌面还在?
A:因为我们只调用了window.Quit()关闭窗口,没有终止explorer.exe进程。桌面由同一进程托管,不受影响。

Q2:脚本会关闭浏览器吗?
A:会。Chrome、Edge、Firefox 等均会被关闭。下次启动时可通过“恢复上次会话”找回标签页(需浏览器开启此功能)。

Q3:能否保留某个程序(如网易云音乐)?
A:可以!在脚本的$excludedNames数组中添加进程名,例如'cloudmusic.exe'

Q4:脚本在 PowerShell 7 中能用吗?
A:可以。已兼容 PowerShell 5.1(Windows 自带)和 PowerShell 7+。

Q5:能否做成计划任务自动运行?
A:可以,但强烈不建议自动执行(因无用户确认)。仅建议手动触发。


附:脚本维护建议

  • 定期检查$excludedNames列表,根据新安装的软件调整;
  • 如遇异常,可临时移除-WindowStyle Hidden查看控制台输出;

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询