【问题标题】:CMD powershell command not allowing pipeCMD powershell命令不允许管道
【发布时间】:2018-04-19 13:03:47
【问题描述】:

我正在尝试让 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 

【问题讨论】:

    标签: sql-server powershell cmd command-line-interface xp-cmdshell


    【解决方案1】:

    | Select Message 部分由 cmd.exe 解释,而不是 PowerShell,因为管道符号 (|) 在 cmd.exe 中也很特殊(含义大致相同),而您没有将其括起来在"..."

    cmd.exe 调用 PowerShell 的最佳方法是将整个 PowerShell 命令作为单双引号字符串 ("...") 传递给 @ 987654328@参数:

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

    【讨论】:

      【解决方案2】:

      如果您使用“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 for /f ...in ("command这里用 ^| pipe") 做 ... 语句。

      也是如此: powershell -noprofile -command "get-childitem | ForEach-Object FullName"

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

      已编辑:这也有效,但作为仅在 PowerShell 中提及的注释,因为 CMD 不理解花括号:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-28
        • 2012-05-21
        • 1970-01-01
        • 2013-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多