CMD powershell 命令不允许管道



我正在尝试让SQL使用一直在工作的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时,它可以正常工作。问题是我没有收到我尝试使用选择和格式化函数尝试获取完整详细信息的完整事件消息,但管道似乎是问题所在。如果您在启动 powershell 后运行相同的命令(IE run powershell.exe然后运行该命令),它可以正常工作,但是当您使用 SQL 运行 powershell 时.exe作为 SQL 中的单独行,它会无限期运行。示例 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 

| 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内部是用作转义字符的`)。

如果使用"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

这不使用格式列表:

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

添加: 实际上,以下命令在我的Win7 PowerShell 5.1计算机上都按预期工作:

开始搜索或WinKey+Run: cmd/k PowerShell -noProfile -command "get-childitem |格式表">

或从打开的 cmd 提示符: PowerShell -noProfile -command "get-childitem |格式列表" PowerShell -noProfile -command "get-childitem |格式表">

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

如果您在引用时遇到问题,那么引号外的 CMD 转义是 ^,因此有时在管道前面加上 ^ 会在 Cmd 中有所帮助.exe(例如,在 cmd 中.exe 对于/f ...在("命令此处与 ^|管道")做...语句。

也是如此: PowerShell -noProfile -command "get-childitem |对于每个对象全名">

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

编辑:这也可以工作,但作为仅在PowerShell中提到的评论,因为CMD不理解大括号:

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

最新更新