CMD PowerShell命令不允许使用管道符号

4

我正在尝试使用xp_cmdshell执行一些PowerShell命令,这一直在起作用,但是我遇到了一个不寻常的问题。当我尝试使用管道时,它无法识别管道后面的命令。我从标准cmd命令行中尝试了这个命令,并确认了相同的问题。这是我正在使用的命令:

powershell.exe -command get-eventlog -Newest 10 -LogName Application -Before "2018-04-18T22:02:23" -After "2018-04-17T22:02:23" -computername dk01sv1115 | Select Message

当我在命令结尾没有使用| Select Message时,它可以正常工作。问题是我没有收到完整的事件消息,我尝试使用Select和Format函数来获取完整的细节,但是管道好像是个问题。如果您启动powershell后再运行相同的命令(例如运行powershell.exe然后运行命令),它将正常工作,但是当您在SQL中使用单独的行运行powershell.exe时,它会无限期地运行。例如SQL:

Declare @command nvarchar(1000),@computername nvarchar(1000)

Set @computername = 'test'
Set @command = 'powershell.exe 
get-eventlog -Newest 10 -LogName Application -Before "' + REPLACE(Convert(VARCHAR(255),GETDATE(),120),' ','T') +'" -After "' + REPLACE(Convert(varchar(255),DateAdd(dd,-1,GETDATE()),120),' ','T') + '" -computername ' + @computername + '
exit'

exec xp_cmdshell @command 
2个回答

8

“| Select Message”这部分是由cmd.exe解释的,而不是PowerShell,因为在cmd.exe中,管道符号(|)也是特殊字符(具有大致相同的含义),并且您没有将其包含在“…”中。

从cmd.exe调用PowerShell的最佳方法是将整个PowerShell命令作为单个双引号字符串(“…”)传递给-Command参数:

powershell.exe -command "get-eventlog -Newest 10 -LogName Application -Before 2018-04-18T22:02:23 -After 2018-04-17T22:02:23 -computername dk01sv1115 | Select Message"

关于嵌套引用的提示:
  • 要引用文字,可以在整体"..."字符串中使用'...'

    • 请注意,在您原始命令中引用的值实际上不需要引用(例如"2018-04-18T22:02:23"),因此我在重新制定时使用了未引用的值。
  • 如果您需要嵌入"字符,请使用\"(尽管PowerShell内部使用的是转义字符`)。


1
如果您使用“PowerShell -command”形式,则将复杂命令放在引号或花括号中。
更新: 通过Invoke-SQLCommand添加^转义字符可以工作:
Invoke-Sqlcmd -ServerInstance ECS-DCTS05 -Database Test -Query "xp_cmdshell 'powershell -command dir c:\ ^| format-list'"

这可以从各种地方启动cmd.exe:
powershell -noprofile -command "get-childitem | format-list" # quoted

这不使用格式列表(format-list):

powershell -noprofile -command get-childitem | format-list # no quotes/braces

新增: 实际上,以下命令在我的Win7 PowerShell 5.1机器上都能正常工作:

开始搜索或WinKey+Run: cmd /k powershell -noprofile -command "get-childitem | format-table"

或者从已打开的cmd提示符中: powershell -noprofile -command "get-childitem | format-list" powershell -noprofile -command "get-childitem | format-table"

在每种情况下,格式命令都能按预期工作。

如果您在引用方面遇到问题,则在引号之外的CMD转义是^,因此有时在Cmd.exe中在管道前缀中加入^会有所帮助(例如,在cmd.exe for /f ...in ("command here with ^| pipe") do...语句中)。

所以: powershell -noprofile -command "get-childitem | ForEach-Object FullName"

这证明了PowerShell正在运行管道的第二个元素。

编辑:这也可以工作,但正如评论提到的那样,只能在PowerShell内部使用,因为CMD不理解花括号:

powershell -noprofile -command { get-childitem | format-list } # curly braces added

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接