CMD powershell 命令不允许管道

CMD powershell command not allowing pipe

我试图让 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 时,它可以正常工作。问题是我没有收到完整的事件消息,我尝试使用 Select 和 Format 函数来尝试获取完整的详细信息,但管道似乎是问题所在。如果您在启动 powershell 后 运行 使用相同的命令(IE 运行 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+运行: 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 中用于 /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