通过 Invoke-Expression 传递 cmd 行 IF 语句会中断输出
Passing a cmd-line IF statement through Invoke-Expression breaks on output
如果我通过 PowerShell 的 Invoke-Expression
传递 IF 语句,该命令似乎正在 运行 正在完成,但随后似乎正在将输出作为新命令进行评估,而不是返回到 PowerShell。三个例子:
Invoke-Expression 'echo "hi"'
(无 IF 语句)
正常输出:hi
Invoke-Expression 'cmd /c IF exist C:\Windows (echo "hi")'
输出错误:'hi' is not recognized as an internal or external command, operable program or batch file.
Invoke-Expression 'cmd /c IF exist C:\Windows (query user)'
输出错误:
'" USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME"' is not recognized as an internal or external command, operable program or batch file.
从 PowerShell 运行 命令行 IF 语句并能够读取其输出的最佳方法是什么? 我试过 Start-Process
但不能为我的生活弄清楚如何阅读它的输出。尝试了从另一个 Whosebug post 复制的 System.Diagnostics.ProcessStartInfo
对象,但也没有成功。
因为人们一定会问:我首先通过 cmd 传递它的原因是因为整个代码块需要通过 Invoke-Command
传递到远程机器并且 cmd 具有 folder/file 访问其网络上的计算机,而 PowerShell 则不能。
您眼前的问题与 Invoke-Expression
、which should generally be avoided:
的使用无关
cmd /c IF exist C:\Windows (echo "hi") # WRONG
由 PowerShell 首先解释,预先 ,(echo "hi")
与 (Write-Output "hi")
相同,PowerShell 将其扩展(插入)到命令的输出, 内容为 hi
.
的字符串
cmd
exe 最终看到的 - 损坏的 - 命令行如下,它解释了错误消息:
cmd /c IF exist C:\Windows hi
有关 PowerShell 如何解析不带引号的命令行参数的概述,请参阅 。
有多种方法可以解决该问题,适用于不同的场景:
# Single-quoting - passed as-is.
cmd /c 'IF exist C:\Windows (echo "hi")'
# Double-quoting - PowerShell would still expand $-prefixed tokens up front.
cmd /c "IF exist C:\Windows (echo `"hi`")"
#`# The stop-parsing symbol, --%, prevents PowerShell from parsing subsequent arguments,
# with the exception of cmd-style environment-variable references (%FOO%)
cmd /c --% IF exist C:\Windows (echo "hi")
现在,使用 Invoke-Expression
您必须添加 escape 这些引号,因为必须将它们指定为 string[= 的一部分46=],但是,正如评论中提到的,很少需要 Invoke-Expression
,这里也不需要,我也不希望它对 "double hop" authentication problem 有帮助你在评论中描述.
要解决后者,请尝试 this answer,它使用显式传递的凭据在远程计算机上建立辅助驱动器映射。
如果我通过 PowerShell 的 Invoke-Expression
传递 IF 语句,该命令似乎正在 运行 正在完成,但随后似乎正在将输出作为新命令进行评估,而不是返回到 PowerShell。三个例子:
Invoke-Expression 'echo "hi"'
(无 IF 语句)
正常输出:hi
Invoke-Expression 'cmd /c IF exist C:\Windows (echo "hi")'
输出错误:'hi' is not recognized as an internal or external command, operable program or batch file.
Invoke-Expression 'cmd /c IF exist C:\Windows (query user)'
输出错误:
'" USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME"' is not recognized as an internal or external command, operable program or batch file.
从 PowerShell 运行 命令行 IF 语句并能够读取其输出的最佳方法是什么? 我试过 Start-Process
但不能为我的生活弄清楚如何阅读它的输出。尝试了从另一个 Whosebug post 复制的 System.Diagnostics.ProcessStartInfo
对象,但也没有成功。
因为人们一定会问:我首先通过 cmd 传递它的原因是因为整个代码块需要通过 Invoke-Command
传递到远程机器并且 cmd 具有 folder/file 访问其网络上的计算机,而 PowerShell 则不能。
您眼前的问题与 Invoke-Expression
、which should generally be avoided:
cmd /c IF exist C:\Windows (echo "hi") # WRONG
由 PowerShell 首先解释,预先 ,(echo "hi")
与 (Write-Output "hi")
相同,PowerShell 将其扩展(插入)到命令的输出, 内容为 hi
.
cmd
exe 最终看到的 - 损坏的 - 命令行如下,它解释了错误消息:
cmd /c IF exist C:\Windows hi
有关 PowerShell 如何解析不带引号的命令行参数的概述,请参阅
有多种方法可以解决该问题,适用于不同的场景:
# Single-quoting - passed as-is.
cmd /c 'IF exist C:\Windows (echo "hi")'
# Double-quoting - PowerShell would still expand $-prefixed tokens up front.
cmd /c "IF exist C:\Windows (echo `"hi`")"
#`# The stop-parsing symbol, --%, prevents PowerShell from parsing subsequent arguments,
# with the exception of cmd-style environment-variable references (%FOO%)
cmd /c --% IF exist C:\Windows (echo "hi")
现在,使用 Invoke-Expression
您必须添加 escape 这些引号,因为必须将它们指定为 string[= 的一部分46=],但是,正如评论中提到的,很少需要 Invoke-Expression
,这里也不需要,我也不希望它对 "double hop" authentication problem 有帮助你在评论中描述.
要解决后者,请尝试 this answer,它使用显式传递的凭据在远程计算机上建立辅助驱动器映射。