我有一个 Powershell 维护脚本,其工作方式如下:
kill explorer
do things
restart explorer
此脚本在提升模式下执行,但我需要重新启动没有管理员权限的资源管理器。有什么想法吗?
谢谢
答案1
据我所知,无法从提升权限的进程直接启动非提升权限的进程(即使用标准低权限令牌)。这不是 PowerShell 的限制,而是 Windows 中 UAC 的工作方式。
从http://msdn.microsoft.com/en-us/library/windows/desktop/bb756914.aspx:
一个常见问题是如何从提升的进程启动未提升的应用程序,或者更根本的是,如何在运行提升的进程后使用未提升的令牌启动进程。由于没有直接的方法可以做到这一点,通常可以通过以标准用户身份启动原始应用程序并仅提升需要管理权限的应用程序部分来避免这种情况。这样,总会有一个未提升的进程可用于以当前登录的桌面用户身份启动其他应用程序。但是,有时提升的进程需要让另一个应用程序以未提升的权限运行。这可以通过使用 Windows Vista® 中的任务计划程序来实现。提升的进程可以注册一个任务以作为当前登录的桌面用户运行。
该文章提到了两种可能的解决方案:
尽可能多地在非提升模式下运行脚本,并且只提升需要的部分。换句话说,在非提升脚本中终止并重新启动资源管理器,并在提升模式下运行第二个脚本来“执行操作”:
Stop-Process -ProcessName explorer Start-Process PowerShell.exe -Verb Runas -ArgumentList "-File path_to_script\script.ps1" Start-Process explorer.exe
该
Runas
动词将导致第二个 PowerShell 进程以提升模式启动。但是,这将触发 UAC 提示,因此如果要完全自动运行此脚本,这不是一个好的解决方案。创建一个计划任务,在提升的操作完成后启动资源管理器,运行该任务并将其删除。您可以使用
schtasks.exe
去做这个:schtasks /Create /TN "foobar" /TR explorer.exe /SC OnLogon schtasks /Run /TN "foobar" schtasks /Delete /TN "foobar" /F
只需确保为该任务选择一个不会与其他任务冲突的名称即可。
您还可以结合上述两种方法,创建一个计划任务,以提升模式运行第二个 PowerShell 脚本,其余脚本则以非提升模式运行。这样做的好处是不会产生 UAC 提示,但会带来安全风险,即任何拥有脚本写入权限的人都可以在您的计算机上执行几乎任何操作。不过,根据您运行和提升当前脚本的具体方式,这可能是一个没有实际意义的问题。
第三个选项是,如果您的脚本仅由您运行,则将其配置为使用您的凭据启动新的 explorer.exe 进程:
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList @("username", (ConvertTo-SecureString -String "password" -AsPlainText -Force))
Start-Process explorer.exe -Credential $Cred
缺点是您的密码会以纯文本形式存储在脚本中。您还可以通过在 PowerShell 提示符中输入以下内容,以加密形式将其存储在单独的文件中:
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\pw_encrypted.txt
然后输入您的密码(它将在 PS 提示符中显示为星号)并按 Enter。现在您可以在脚本中使用它,如下所示:
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList @("username", (Get-Content C:\pw_encrypted.txt | ConvertTo-SecureString))
Start-Process explorer.exe -Credential $Cred
答案2
唯一想到的办法是使用任务计划程序重新启动资源管理器。启动进程或任何其他方法似乎都可以保持提升状态。