通过xp_cmdshell执行带管道的PowerShell命令失败问题排查
解决xp_cmdshell/CMD中PowerShell管道命令无法识别的问题
这个问题我太熟了!本质原因是CMD会优先解析管道符|——它不会把管道传递给PowerShell,反而会把管道后面的命令当成自己的CMD命令来执行,自然就识别不了啦。给你几个靠谱的解决办法:
方法1:用双引号包裹整个PowerShell命令,内部用单引号
把所有PowerShell逻辑(包括管道)都放在双引号里,同时把命令里的字符串参数(比如日期)换成单引号,避免和外层双引号冲突。举个完整的例子:
powershell.exe -command "get-eventlog -Newest 10 -LogName Application -Before '2018-04-18T22:02:23' -After '2018-04-17T22:02:23' -computername dk01sv1115 | Select-Object EventID, Message"
这样CMD就会把整个双引号里的内容都传给PowerShell,管道符也会被PowerShell正确解析。
方法2:使用Base64编码命令(适合复杂场景)
如果你的命令里有多层引号或者更复杂的逻辑,转义起来容易出错,那就用-EncodedCommand参数。步骤很简单:
- 先在PowerShell控制台里把你的目标命令转成Base64编码:
$cmd = "get-eventlog -Newest 10 -LogName Application -Before '2018-04-18T22:02:23' -After '2018-04-17T22:02:23' -computername dk01sv1115 | Select-Object EventID, Message" $encodedCmd = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($cmd))
- 把输出的
$encodedCmd字符串复制出来,放到xp_cmdshell或者CMD里执行:
powershell.exe -EncodedCommand <这里替换成你得到的编码字符串>
这种方式完全避免了引号和管道的解析冲突,绝对稳。
额外提醒
如果xp_cmdshell突然不能用了(虽然你说之前正常),可以检查下是否被禁用:
sp_configure 'xp_cmdshell', 1; RECONFIGURE;
执行这个SQL语句就能重新启用它。
内容的提问来源于stack exchange,提问作者Xanderu




