关闭指定程序的 UAC 通知
在启动某些 Windows 程序时会弹出 UAC (用户账户控制)确认窗口,这表示该程序需要管理员权限来运行。用户可以选择批准或拒绝。

运行 Listary 每次都要弹出 UAC 通知

以管理员身份运行 Everything
用户可以通过控制面板 > 系统和安全 > 更改用户帐户控制设置来更改 UAC 的行为。将滑块移动到从不通知便可以全局关闭系统 UAC 通知。Windows 并没有提供 UAC 通知的白名单功能。

UAC 设置
程序触发 UAC 弹窗的方式基本分两种:
在程序清单 (Manifest) 中设置
requestedExecutionLevel
:xml
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo>
使用
ShellExecute()
启动程序,将lpOperation
参数设置为"runas"
针对第一种情况,可以通过简单注册表操作来实现 UAC 静默。Listary 属于第一种情况,以它为例。在注册表编辑器中访问如下路径:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
新建字符串值,数据名称为程序的路径,比如 D:\Apps\Listary\Listary.Service.exe, 数据值为 RunAsInvoker。其含义为忽略程序清单中的 requestedExecutionLevel,以程序调用者的权限运行。因此也就不会弹出 UAC 通知了。
该方法的缺点是,程序并没有获得管理员权限,可能会导致一些功能无法正常使用。
另外,也可以使用 NirSoft 的 AppCompatibilityView 图形工具来进行该操作。
对于第二种情况,则需要借助于任务计划程序。其原理为,新建一个不包含任何触发条件的任务,并设置为以最高权限运行,用户使用命令来触发该任务。由于任务本身具有管理员权限,因此不会弹出 UAC 通知。
用户可以在控制面板 > 管理工具 > 任务计划程序中以交互方式创建任务,或者使用命令行创建。
使用
schtasks
命令:cmd
rem 由于 sctasks 命令不支持创建无触发器的任务,因此设置了一个无效执行时间 schtasks /create /tn "RunAsAdmin\Everything" /tr "D:\Apps\Everything\everything.exe" /rl HIGHEST /sc once /st 00:00
使用 PowerShell 的
Register-ScheduledTask
命令:powershell
# 不能省略 -UserId 参数,且必须与当前登入用户一致,否则程序无法在桌面上显示 Register-ScheduledTask -TaskName "RunAsAdmin\Everything" -Action (New-ScheduledTaskAction -Execute "D:\Apps\Everything\everything.exe") -Principal (New-ScheduledTaskPrincipal -UserId ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) -RunLevel Highest)
使用下面的命令以管理员身份运行 Everything:
cmdschtasks.exe /run /tn "RunAsAdmin\Everything"
也可以将以上命令创建为快捷方式运行。