首页 > 解决方案 > 在 PowerShell 脚本中将字符串导入 cmd 不起作用

问题描述

当我直接在我的 PowerShell 窗口中执行它时,我有以下工作调用:

$myexe = "C:\MyExe.exe"
"MyString" | & $myexe // works
Write-Output "MyString" | & $myexe // seems to work too

但是,当我在 PowerShell 脚本的函数中执行相同操作时,它不再起作用。该程序没有收到字符串......有什么想法吗?

标签: powershellpipelinestdin

解决方案


与 POSIX 兼容的 shell(例如 )不同bashPowerShell 不会自动将给定脚本或函数接收到的管道输入中继到您从该脚本或函数内部调用的命令。

为此,您必须使用自动$input变量[1]

例如:

function foo {
  # Relay the pipeline input received by this function 
  # to an external program, using `cat` as an example.
  $input | & /bin/cat -n # append $args to pass options through
}

'MyString' | foo

请注意,&在这种情况下它是可选的,因为/bin/cat它是一个不带引号的文字路径 - 请参阅此答案以了解 when &is required

输出(在类 Unix 平台上)是: 1 MyString,表明cat实用程序foo通过其标准输入接收到函数自己的管道输入,这要归功于使用$input.

如果没有$input到的管道cat,后者将根本不会收到标准输入输入(并且在cat阻塞的情况下,等待交互式输入)。

如果您也想支持传递文件名参数- 代替管道输入 - 需要做更多的工作:

function foo {
  if ($MyInvocation.ExpectingInput) { # Pipeline input present
    # Relay the pipeline input received by this function 
    # to an external program, using `cat` as an example.
    $input | /bin/cat -n $args
  } else { # NO pipeline input.
    /bin/cat -n $args
  }
}

'MyString' | foo  # pipeline input
foo file.txt      # filename argument

注意

  • 只有高级函数和脚本才能使用该变量,$input并且它的使用意味着通过管道传输到封闭函数/脚本的所有输入都在开始之前完全收集,在前面发送

  • 要将脚本/函数自己的管道输入真正流式传输到外部程序的单个调用- 即在脚本/函数接收输入时中继输入 -需要直接使用 .NET APISystem.Diagnostics.ProcessStartInfo,即System.Diagnostics.Process.


[1] 同样,$input需要通过 PowerShell 的CLI从 PowerShell外部访问通过管道传输到 PowerShell 命令的数据;例如,来自:bash
echo hi | pwsh -c '$input | ForEach-Object { "[{0}]" -f $_ }'


推荐阅读