Kee*_*rth 3 powershell powershell-2.0 powershell-3.0 powershell-4.0
我正在尝试从PowerShell启动提升的CMD窗口,但遇到了一些问题。以下是我现在拥有的代码。计算机上有一个管理员帐户,其用户名为“ test”,密码为“ test”
$username = "test"
$password = ConvertTo-SecureString "test" -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
Start-Process "cmd.exe" -Credential $cred
Run Code Online (Sandbox Code Playgroud)
对于从用户配置文件运行该脚本时没有管理员权限的应用程序,这一切都可以正常工作,但是在调用cmd.exe时,它将以提升的权限按预期方式启动,然后立即关闭。
我也尝试用以下命令调用它:
Start-Process "cmd.exe" -Credential $cred -ArgumentList '/k'
Run Code Online (Sandbox Code Playgroud)
这也不起作用。
我通过传递一个参数来测试提升的权限,如下所示,它可以正常工作。
Start-Process "cmd.exe" -Credential $cred -ArgumentList 'dir > dir.txt'
Run Code Online (Sandbox Code Playgroud)
这会将dir.txt文件写到C:\ Windows \ System32 \ WindowsPowerShell \ v1.0目录,该目录在用户帐户上被阻止,但对于管理员帐户测试则未被阻止。
非常感谢获得有关持久cmd窗口显示的任何帮助。
谢谢
注意:SomeShinyObject在他的答案中提出了该方法的基本原理,但是他的参数传递技术并不可靠(更新:由于已更正)- 请勿使用脚本块代替字符串 -参见底部。
-Verb RunAs是什么使得Start-Process 启动过程变得更加高级。
但是,-Verb RunAs不能与-Credential参数组合使用,因此您无法直接控制在哪个用户帐户下进行海拔升高-但这通常不是必需的:
安全警告:
如果你仍然想按照规定实行你的脚本,一个解决办法需要嵌套 2个Start-Process电话:
第一个在指定用户(假定是管理用户)中使用(不变)不可见地运行(非恒定)命令-Credential。
-Credential以非管理员用户为目标,则建议还指定一个-WorkingDir参数,表明已知该指定的用户具有访问权限-否则,调用可能会失败(当前位置被保留,并且可能不允许目标用户访问它)。第二个,嵌入在第一个中,然后用于-Verb RunAs运行提升的目标命令,然后在指定用户的上下文中发生此命令。
注意:即使使用包含密码的凭据对象,您仍然会收到是/否UAC提示,以确认意图进行举升 -除非已关闭UAC(不建议这样做)。
工作目录始终是$env:SYSTEMROOT\Windows32; -Verb RunAs甚至忽略一个-WorkingDirectory值;如果要更改到特定目录,请cd在传递给的命令中嵌入命令cmd.exe。
此命令完全符合您的要求- 请注意安全警告:
# Construct the credentials object
$username = "jdoe"
# CAVEAT: Storing a password as plain text is a security risk in general.
# Additionally, if you let non-administrative users execute this
# code with a stored password, you're effectively giving them
# administrative rights.
$password = ConvertTo-SecureString "test" -AsPlainText -Force
$cred = New-Object PSCredential -Args $username, $password
# Start an elevated Command Prompt (cmd) as user $username.
Start-Process powershell.exe -Credential $cred -WindowStyle Hidden `
'-noprofile -command "Start-Process cmd.exe -Verb RunAs"'
Run Code Online (Sandbox Code Playgroud)
请注意,嵌入的第二个命令作为单个字符串传递给(隐含的)-ArgumentList(aka -Args)参数。
在这种简单情况下,仅使用1级嵌入式引号(字符串内的"实例)'...'并且不需要扩展(字符串插值),传递单个字符串是一个可行的选择,但是使用更复杂的命令引号会比较棘手。
-ArgumentList被定义为type[string[]],即字符串参数数组。如果您传递多个 - ,分隔的参数,则是PowerShell为您合成了命令行,这通常使得更容易获得正确的引用,尤其是在涉及变量引用时:
以下命令演示了此技术:它是一种变体,它传递cmd.exe要执行的命令,并在该命令中使用变量引用:
$msg = 'This is an elevated Command Prompt.'
Start-Process powershell.exe -Credential $cred -WindowStyle Hidden -Args `
'-noprofile', '-command', "Start-Process cmd.exe -Verb RunAs -Args /k, echo, '$msg'"
Run Code Online (Sandbox Code Playgroud)
cmd.exe最终执行的命令(带有高程)为:
cmd /k echo This is an elevated Command Prompt.
tl; dr
乍一看,脚本块({ ... })似乎是一个方便的选项:
Start-Process cmd -ArgumentList { /k echo hi! }
Run Code Online (Sandbox Code Playgroud)
上面的代码cmd /k echo hi!将按预期在新的控制台窗口中执行。语法很方便,因为{ ... }看似提供了一个易于引用的上下文:您可以自由地使用嵌入式 "和'实例来构造命令行。
然而,发生了什么幕后是一个脚本块转换为字符串,因为这是争论的(一个或多个)类型-ArgumentList预期,并且当一个脚本块转换为字符串,其字面内容-之间的一切{和}-使用。
这意味着不会进行字符串插值,因此不能使用变量或子表达式。
尝试通过变量传递命令:
Start-Process cmd -ArgumentList { /k echo Honey, I`'m $HOME! }
Run Code Online (Sandbox Code Playgroud)
这将执行的是:cmd /k echo Honey, I'm $HOME!- $HOME未扩展。
相比之下,传递插值字符串或参数分别按预期工作:
# As a single string (argument list):
Start-Process cmd -ArgumentList "/k echo Honey, I'm $HOME!"
# As an array of arguments:
Start-Process cmd -ArgumentList /k, echo, "Honey, I'm $HOME!"
Run Code Online (Sandbox Code Playgroud)
$HOME在两种情况下都被扩展(内插),并且
cmd /k echo Honey, I'm C:\Users\jdoe执行类似的操作。
| 归档时间: |
|
| 查看次数: |
9276 次 |
| 最近记录: |